目录
一、对象扩展
二、函数的扩展
三、Symbol
四、Iterator 迭代器
五、Set结构
六、Map 数据结构
一、对象扩展
1. 对象简写
对于对象属性,属性名与属性值对应的变量相同时,可简写为属性名
对于对象方法,将 :function 去掉
let name = 'pink'
const obj = {
name, //是 name: name的简写属性名与属性值的变量相同,
test1(){ //是 test1: function(){ }的简写
console.log('test1')
},
test2(){
console.log('test2')
}
}
2. 对象属性 表达式
使用 [ ] 操作属性时,可以使用变量
let name = 'pink'
const obj = {
name, //是 name: name的简写属性名与属性值的变量相同,
[name + 'test1'](){ //属性表达式,表示为 pinktest1
console.log(1);
}
}
3. 扩展运算符
const obj = {
name: 'pink'
}
const obj1 = {
...obj
}
console.log(obj1) //{name: 'pink'}
const obj2 = {
age: 100
}
const obj3 = {...obj1, ...obj2}
console.log(obj3) //{name: 'pink', age: 100}
4. Object.assign( )、Object.is( )
Object.assign( )
语法:
Object.assign(target, ...sources)
target 目标对象,接收源对象属性的对象,也是修改后的返回值。
sources 源对象,包含将被合并的属性。
会直接将目标对象修改,破坏性方法
Object.is( ) 判断两个值是否为同一个值
Object.is( ) 与 == 不相同 ,==会进行类型转换 ,而Object.is( )不会进行类型转换。
Object.is( ) 与 === 不相同,差别是对待有符号的零和 NaN不同,===运算符将数字 +0 与 -0判断为true, 对于两个 NaN判断为 false; Object.is( )将两个 NaN 视为相等。
console.log(Object.is(5, '5')) //false
console.log(Object.is(parseInt('pink'), NaN)) //true
console.log(parseInt('pink') === NaN) //false
二、函数的扩展
1. 参数默认值
2. 剩余参数
得到的是真数组
3. name属性
4. 箭头函数 ,使得写法更简洁
只有return 可省略
如果返回对象需注意加上小括号
如果只有一个参数,可以省略 ( )
箭头函数中没有 arguments ,无法 new(作为构造函数)
箭头函数没有 this, this 指向父作用域
三、Symbol
ES6引入了一种新的原始数据类型 symbol,表示独一无二的值(不能进行运算)
let s1 = Symbol() //生成了一个 Symbol类型的数据
let s2 = Symbol() //生成了一个 Symbol类型的数据
console.log(typeof s1) //symbol
console.log(s1 == s2) //false
1. 使用 Symbol 作为对象属性名,保护对象的属性,避免冲突的机制
可传参,对 symbol 的描述,可用于调试但不是访问 symbol 本身
注意: for in 只能遍历出普通属性和方法,对于使用 Symbol建立的属性及方法无法遍历
可使用Object.getOwnPropertySymbols( ) 获得 symbol属性名
Reflect.ownKeys( )获得所有的属性名(返回一个数组)
let name = Symbol("name")
let age = Symbol("age")
const obj = {
[name]: 'pink',
[age]: 18,
name: 'tiechui',
getName(){
console.log(this.name);
}
}
console.log(obj[name]);
console.log(obj);
obj.getName()
console.log(Object.getOwnPropertySymbols(obj));
console.log(Reflect.ownKeys(obj));
Reflect.ownKeys(obj).forEach(item => {
console.log(item, obj[item]);
})
2. Symbol( ) 函数可以接收一个字符串作为参数,表示对 Symbol 实例的描述
3. 作为常量
function play(type) {
// 该函数想播放视频、音频
switch(type) {
case VIDEO:
console.log('视频播放');
break
case AUDIO:
console.log('音频播放');
break
case IMAGE:
console.log('图片播放');
break
}
}
const VIDEO = Symbol()
const AUDIO = Symbol()
const IMAGE = Symbol()
play(VIDEO)
四、Iterator 迭代器
Iterator 的作用有三个:
1. 是为各种数据结构,提供一个统一的,简便的访问接口;
2. 使得数据结构的成员能够按某种次序排列
3. ES6 创造了一种新的遍历命令 for ... of 循环,iterator 接口主要供 for ... of 循环
Symbol.iterator 是一个内置值
const obj = {
name: 'hh',
age: 18,
[Symbol.iterator](){
console.log('iterator');
}
}
console.log(obj);
const arr = ['red', 'pink', 'blue']
let iter = arr[Symbol.iterator]()
// 返回的就是遍历器对象
console.log(iter);
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());
原生默认具备 iterator 接口的数据结构如下:
Array
Set
Map
String
Arguments 对象,函数中的内置对象(伪数组)
NodeList 对象, 获取的DOM节点(伪数组)
如何对对象进行 for of 遍历?(对象不能迭代是因为对象是非线性的,无序的)
const obj = {
0: 'red',
1: 'blue',
2: 'pink',
length: 3,
[Symbol.iterator]: Array.prototype[Symbol.iterator]
}
如果对象中有某个属性是数组,但是该对象是传过来的黑盒子,不知道该属性名称,之前对该对象添加迭代器是非常有必要的,以至于让该对象通过 for of进行遍历该属性的数组
const obj2 = {
code: 200,
name: 'hh',
list: ['a', 'b','c'],
// 迭代器
[Symbol.iterator](){
let index = 0
return {
next:() => {
return {
value:this.list[index++],
done: index >=(this.list.length + 1) ? true : false}
}
}
}
}
let iter = obj2[Symbol.iterator]()
// console.log(iter);
// console.log(iter.next());
// console.log(iter.next());
for(let i of obj2) {
console.log(i);
}
五、Set结构
类似于数组,但成员的值都是唯一的,没有重复的值。
Set 是一系列无序、没有重复值的数据集合。数组是一系列有序(下标索引)的数据集合。
可以通过Set( ),与展开运算符对数组进行去重,[...new Set(数组)]
1.初识Set,两种初始化的方法,使用Set( )对数组去重
// Set初始化第一种方式
const s1 = new Set([1,2,3,2,4])
console.log(s1); //Set(4) {1, 2, 3, 4}
console.log([...s1]); // [1, 2, 3, 4]
console.log(Array.from(s1)); // [1, 2, 3, 4]
//Set初始化第二种方式
let s2 = new Set()
s2.add(1)
s2.add(2)
s2.add(2)
s2.add(4)
console.log((s2)); //Set(3) {1, 2, 4}
for(let i of s1) {
console.log(i);
}
2. Set 构造函数的参数
数组、字符串、arguments、NodeList、Set 等
数组:
const s = new Set([1, 2, 1]);
console.log(s); // Set(2) { 1, 2 }
字符串:
const s = new Set('hello')
console.log(s); //Set(4) {'h', 'e', 'l', 'o'}
arguments:
function func() {
console.log(new Set(arguments));
}
func(1, 2, 1); // Set(2) { 1, 2 }
NodeList:
<p>1</p>
<p>2</p>
<p>3</p>
<script>
console.log(new Set(document.querySelectorAll('P')));//Set(3) {p, p, p}
</script>
Set:
const s = new Set([1, 2, 1]);
console.log(new Set(s)); // Set(2) { 1, 2 }
console.log(s); // Set(2) { 1, 2 }
// 这也是复制一个 Set 的方法
3. Set 实例属性和方法
实例属性 :size 返回Set 对象中值的个数
实例方法:
add(value) Set对象中没有具有相同值的元素,则将插入一个具有指定值的新元素到Set对象中
has( value)方法返回一个布尔值来指示对应的值是否存在于Set对象中
delete( value) 从对象中删除指定的值(该值存在于Set对象中),成功删除返回true,否则返回 false
clear( ) 移除Set对象中所有元素,没有返回值 undefined
forEach( ) 用于遍历 Set 的(按照成员添加进集合的顺序遍历)
forEach 方法可以接受两个参数,第一个是:回调函数,第二个是指定回调函数的 this 指向。
const s = new Set();
s.add(0);
s.add(1).add(2).add(2).add(3);
s.forEach(function (value, key, set) {
// Set 中 value = key,原因:好多数据结构都有 forEach 方法,为了方便统一,所以参数是统一的,但是参数的意义各有不同
// set 就是 s 本身
console.log(value, key, set === s);
console.log(this);
});
/*
0 0 true
Window
1 1 true
Window
2 2 true
Window
3 3 true
Window
*/
const s = new Set();
s.add(0);
s.add(1).add(2).add(2).add(3);
s.forEach(function (value, key, set) {
// Set 中 value = key,原因:好多数据结构都有 forEach 方法,为了方便统一,所以参数是统一的,但是参数的意义各有不同
// set 就是 s 本身
console.log(value, key, set === s);
console.log(this);
}, document);
/*
0 0 true
#document
1 1 true
#document
2 2 true
#document
3 3 true
#document
*/
4. Set 注意事项
【Set 如何判断重复】
Set 对重复值的判断基本遵循严格相等(===)
但是对于 NaN 的判断与 === 不同,Set 中 NaN 等于 NaN
const s = new Set();
s.add({}).add({});
console.log({} === {}); // false
console.log(s); // Set(2) { {}, {} }
【什么时候使用 Set】
- 数组或字符串需要去重时
- 不需要通过下标访问,只需要遍历时
- 为了使用 Set 提供的方法和属性时
5. Set的应用
数组去重
const s = new Set([1, 2, 1]);
console.log(s); // Set(2) { 1, 2 }
console.log([...s]); // [ 1, 2 ]
字符串去重
const s = new Set('abbacbd');
console.log(s); // Set(4) { 'a', 'b', 'c', 'd' }
console.log([...s].join('')); // abcd
复杂数据类型去重
let list = [1,2,2,'ke','ke',[1,2],[3,4],[1,2],{name:'ke'},
{name:'ke'},undefined,undefined,NaN,NaN]
function uni(arr) {
let res = new Set()
return arr.filter(item => {
// 判断 已经存在 ,return false
// 判断 没有,return true
let id = JSON.stringify(item)
// console.log(id);
if(res.has(id)) {
return false
} else {
res.add(id)
return true
}
})
}
console.log(uni(list));
存放DOM元素
<p>1</p>
<p>2</p>
<p>3</p>
<script>
// 这里使用 Set 是因为我们不需要通过下标去访问,只需直接遍历即可
const s = new Set(document.querySelectorAll('p'));
s.forEach(function (elem) {
elem.style.color = 'red';
});
</script>
遍历
数组的map
和filter
方法也可以间接用于 Set 了。
let set = new Set([1, 2, 3]);
set = new Set([...set].map(x => x * 2));
// 返回Set结构:{2, 4, 6}
let set = new Set([1, 2, 3, 4, 5]);
set = new Set([...set].filter(x => (x % 2) == 0));
// 返回Set结构:{2, 4}
因此使用 Set 可以很容易地实现并集(Union)、交集(Intersect)和差集(Difference)
let a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);
// 并集
let union = new Set([...a, ...b]);
// Set {1, 2, 3, 4}
// 交集
let intersect = new Set([...a].filter(x => b.has(x)));
// set {2, 3}
// (a 相对于 b 的)差集
let difference = new Set([...a].filter(x => !b.has(x)));
// Set {1}
六、Map 数据结构
类似于对象,也是键值对的集合,但是“键"的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
1. Map 构造函数中的参数
- 二维数组
- Set、Map 等
【二维数组】
console.log(new Map([
['name', 'alex'],
['age', 18]
]));
// Map(2) { 'name' => 'alex', 'age' => 18 }
【Set、Map】
console.log(new Map([
['name', 'alex'],
['age', 18]
]));
// Map(2) { 'name' => 'alex', 'age' => 18 }
【Set、Map】
// Set
// Set 中也必须体现出键和值
const s = new Set([
['name', 'alex'],
['age', 18]
]);
console.log(new Map(s));
console.log(s);
// Map(2) { 'name' => 'alex', 'age' => 18 }
// Set(2) { [ 'name', 'alex' ], [ 'age', 18 ] }
// Map
const m = new Map([
['name', 'alex'],
['age', 18]
]);
console.log(m);
const m2 = new Map(m);
console.log(m2, m2 === m);
// Map(2) { 'name' => 'alex', 'age' => 18 }
// Map(2) { 'name' => 'alex', 'age' => 18 } false
// Map 复制的方法
2. Map 实例方法和属性
set( ) 方法 设置键名key 对应的键值为value,然后返回整个 Map 结构。如果key已经有值,则键值会被更新,否则就新生成该键。方法返回的是当前的Map
对象,因此可以采用链式写法。
const m = new Map();
m.set('edition', 6) // 键是字符串
m.set(262, 'standard') // 键是数值
m.set(undefined, 'nah') // 键是 undefined
get( ) 方法 读取key对应的键值,如果找不到key,返回undefined。
const m = new Map();
const hello = function() {console.log('hello')}
m.set(hello, 'Hello ES6!') // 键是函数
m.get(hello) // Hello ES6!
has( ) 方法 返回一个布尔值,表示某个 键是否在当前 Map对象中
const m = new Map();
m.set('edition', 6);
m.set(262, 'standard');
m.set(undefined, 'nah');
console.log(m.has('edition') ); // true
console.log(m.has('years') ); // true
console.log(m.has(262) ); //false
delete( ) 方法 删除某个键,返回 true。如果删除失败,返回 false
clear( ) 方法 清除所有成员,没有返回值
forEach( ) 方法
const m = new Map([['name','hh'],[undefined,1]]);
m.forEach(function (value, key, map) {
console.log(value,key,map);
console.log(this);
}, document);
size 属性
3. Map 注意事项
【Map 如何判断键名是否相同】
在 Set 中遇到重复的值直接去掉后者,而 Map 中遇到重复的键值则是后面的覆盖前面的。
- 基本遵循严格相等(===)
- Map 中 NaN 也是等于 NaN
【什么时候使用 Map】
- 如果只是需要键值对结构
- 需要字符串以外的值做键
- 对象一般用在模拟实体上