一、解构赋值
1.完全解构
比如这里有个对象,在ES5中获取对象里的值我们都这么干
let obj = {
uname: 'zzy',
age: 20
}
let uname = obj.uname;
let age = obj.age;
但是现在,我们用解构赋值就可以直接这么干
非常简便
let { uname, age } = obj;
console.log(uname, age); //'zzy',20
在Vue2插槽中也用到了这个,可以去翻翻
2.不完全解构
或者也可以用一下子剩余运算符
let book = {
content: {
title: 'zzy',
sell: 5
},
author: 'ht',
page: 20
}
let { content, ...rest } = book;
console.log(content); //{title: 'zzy', sell: 5}
console.log(rest); //{author: 'ht', page: 20}
3.重命名
如果想给某个属性重命名,可以使用冒号
比如上面的案例可以这样:
let { uname: myname, age: myage } = obj;
console.log(myname, myage);
let { content: a } = book;
console.log(a); //{title: 'zzy', sell: 5}
4.数组解构
let arr = [1, 2, 3];
let [a, b, c] = arr;
console.log(a, b, c);
二、Symbol数据类型
ES6单独引入Symbol,其目的是防止对象的属性名冲突,存在及合理,但我get不到具体的应用场景……
1.相同参数的Symbol函数返回值不等:
let a = Symbol('zzy');
let b = Symbol('zzy');
console.log(a === b); //false
console.log(a); //Symbol(zzy)
2.如果参数是个对象,那么返回的是这玩意儿
const obj = {name: 'zzy'};
const c = Symbol(obj);
console.log(c); //Symbol([object Object])
3.给上面这个obj对象添加一个属性
obj[a] = '张大仙';
console.log(obj); //{name: 'zzy', Symbol(zzy): '张大仙'}
上面这段代码相当于:
let obj = {
name: 'zzy',
[a]: '张大仙'
};
console.log(obj); //{name: 'zzy', Symbol(zzy): '张大仙'}
在对象的内部,使用 Symbol 值定义属性时,Symbol 值必须放在方括号[]之中
4.获取对象中的Symbol属性值
获取对象中的Symbol属性值,必须用[symbol变量名]
,不能用点,因为用点意思就是obj里有个属性名叫做a,而这个Symbol不是属性名a,而是a对应的Symbol(zzy)
console.log(obj[a]); //张大仙
console.log(obj.a); //undefined
5.Symbol属性名是遍历不到的
Symbol 作为属性名,遍历对象的时候,该属性不会出现在for...in、for...of
循环中,也不会被Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()
返回。
但是,它也不是私有属性,有一个Object.getOwnPropertySymbols()
方法,可以获取指定对象的所有 Symbol 属性名。该方法返回一个数组,成员是当前对象的所有用作属性名的 Symbol 值。
还有个Reflect.ownKeys()
方法可以返回所有类型的键名,包括常规键名和 Symbol 键名。
const o = {};
const name = Symbol('name');
o[name] = 'zzy';
o['age'] = 20;
for (let i in o) {
console.log(i); // 只有age
}
console.log(Object.getOwnPropertyNames(o)); //['age']
console.log(Object.getOwnPropertySymbols(o)); // [Symbol(name)]
console.log(Reflect.ownKeys(o)); //['age', Symbol(name)]
其他的内容遇到了再翻文档吧
三、Map和Set数据结构
这两个内置对象最大的区别,我认为是Set是只有值没有键,Map是键值对,而且键可以为任意类型(不局限于字符串,键可以是字符串、数组、undefined、甚至函数等等)
下面这些东西记的不全,有需要去查文档
1.Set
Set实际上类似于数组,但是成员的值都是唯一的,没有重复的值。其本身是个构造函数,是个内置对象
(1)Set的属性和方法
属性:
Set.prototype.constructor
:构造函数,默认就是Set函数。
Set.prototype.size
:返回Set实例的成员总数。
方法:
Set.prototype.add(value)
:添加某个值,返回 Set 结构本身。
Set.prototype.delete(value)
:删除某个值,返回一个布尔值,表示删除是否成功。
Set.prototype.has(value)
:返回一个布尔值,表示该值是否为Set的成员。
Set.prototype.clear()
:清除所有成员,没有返回值。
const s = new Set();
s.add(2);
s.add('4');
s.add([4, 3, 2]);
console.log(s); // {2, '4', Array(3)}
console.log(s.size); //3
s.delete('4');
console.log(s); // {2, Array(3)}
console.log(s.has('4')); //false
遍历操作:
Set.prototype.keys()
:返回键名的遍历器
Set.prototype.values()
:返回键值的遍历器
Set.prototype.entries()
:返回键值对的遍历器
Set.prototype.forEach()
:使用回调函数遍历每个成员
这里需要注意的是,Set 结构没有键名,只有键值(或者说键名和键值是同一个值),所以keys方法和values方法的行为完全一致。
//1.遍历Set中的键
let set1 = new Set(['red', 'green', 'blue']);
console.log(set1.keys()); //SetIterator {'red', 'green', 'blue'}
for (let i of set1.keys()) {
console.log(i);
// red
// green
// blue
}
//2.遍历Set中的值
console.log(set1.values()); //SetIterator {'red', 'green', 'blue'}
for (let i of set1.values()) {
console.log(i);
// red
// green
// blue
}
//3.遍历Set中的键值对
console.log(set1.entries()); //SetIterator {'red' => 'red', 'green' => 'green', 'blue' => 'blue'}
for (let i of set1.entries()) {
console.log(i);
// ["red", "red"]
// ["green", "green"]
// ["blue", "blue"]
}
当然啊,如果想遍历Set,直接这么写就行了
console.log(set1); //Set(3) {'red', 'green', 'blue'}
for (let i of set1) {
console.log(i);
// red
// green
// blue
}
Set 结构的实例与数组一样,也拥有forEach
方法,用于对每个成员执行某种操作,没有返回值。
let set = new Set([1, 4, 9]);
set.forEach((value, key) => console.log(key + ' : ' + value))
// 1 : 1
// 4 : 4
// 9 : 9
(2)Set实现数组去重
1.可以直接用剩余运算符进行数组去重,set接过来的是一个去重之后的{2, 3, 4, 5}这玩意儿,用剩余运算符拆开,然后再放进[]里面,就成数组了
const set = new Set([2, 3, 3, 3, 4, 5]);
console.log([...set]); //[2,3,4,5]
2.Array.from
方法可以将 Set 结构转为数组。
const items = new Set([1, 2, 3, 4, 5]);
const arr = Array.from(items);
这就提供了去除数组重复成员的另一种方法。
function dedupe(arr) {
let s = new Set(arr);
return Array.from(s);
}
console.log(dedupe([1, 1, 2, 3])); // [1, 2, 3]
以上这两种方法原理是一样的,都是利用Set对象的去重能力
(3)Set实现字符串去重
还是一样,都是利用Set对象的去重能力,只是我没想到Set的参数还可以是字符串
let str = new Set('aabbbcc');
console.log(str); //{'a', 'b', 'c'}
str = [...str].join('');
console.log(str); //'abc'
2.Map
和Set类似,Map解决的是传统Object对象里只能用字符串作为键的缺陷,它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。
(1)Map的属性和方法
属性:
Map.prototype.size
:返回Map实例的成员总数。
方法:
Map.prototype.set(key, value)
Map.prototype.get(key)
Map.prototype.has(key)
has方法返回一个布尔值,表示某个键是否在当前 Map 对象之中。
Map.prototype.delete(key)
delete方法删除某个键,返回true。如果删除失败,返回false。
Map.prototype.clear()
clear方法清除所有成员,没有返回值。
遍历操作:
Map.prototype.keys()
:返回键名的遍历器
Map.prototype.values()
:返回键值的遍历器
Map.prototype.entries()
:返回键值对的遍历器
Map.prototype.forEach()
:遍历 Map 的所有成员
大部分和Set一样,就不解释了,不懂了去翻文档好了
其中主要看下这个set和get
Map.prototype.set(key, value)
set方法设置键名key对应的键值为value,然后返回整个 Map 结构。如果key已经有值,则键值会被更新,否则就新生成该键。.键可以是任何东西
const m = new Map();
m.set('name', 'zzy'); //键是字符串
m.set(undefined, 12); //键是undefined
m.set(666, 'ht'); //键是数值
m.set(function () { }, '不错'); //键是函数
console.log(m); //Map(4) {'name' => 'zzy', undefined => 12, 666 => 'ht', ƒ => '不错'}
Map支持链式写法:
const m = new Map().set(1, 'a').set(2, 'b');
console.log(m); //{1 => 'a', 2 => 'b'}
Map.prototype.get(key)
get方法读取key对应的键值,如果找不到key,返回undefined。
console.log(m.get(666)); //ht
console.log(m.get('age')); //undefined
除此之外Map也可以用多维数组设置默认值
const map = new Map([[1, 'a'], [2, 'b']]);
console.log(map); //{1 => 'a', 2 => 'b'}
四、数组的扩展方法
1.from()
将伪数组转换为真数组
比如把arguments转换为一个真数组
function add() {
let arr = Array.from(arguments);
console.log(arr); //[1, 2, 3]
}
add(1, 2, 3);
比如ul里面的好多li的数组集合,转换为真正的数组
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
let lis = document.querySelectorAll('li');
console.log(lis); //NodeList(4) [li, li, li, li]
console.log(Array.from(lis)); // [li, li, li, li]
当然上面这个其实可以直接用扩展运算符
console.log([...lis]); // [li, li, li, li]
from()还可以有第二个参数,可以对每一个元素进行处理
let liContents = Array.from(lis, c => c.innerHTML);
console.log(liContents); //['1', '2', '3', '4']
2.of()
将任意数据类型转换为数组
也不知道这个有啥用
console.log(Array.of('2', [2, 3], { 'a': 1 }, undefined));
//['2', Array(2), {…}, undefined]
3.find()
和findiIndex()
find()是找出数组中符合条件的第一个数组成员
findexIndex()是找出数组中符合条件的第一个数组成员的索引
let num = [1, 2, -10, 23, -34].find(n => n < 0);
let numindex = [1, 2, -10, 23, -34].findIndex(n => n < 0);
console.log(num, numindex); //-10 2
4.数组中的keys()
和values()
和entries()
遍历
它们都返回一个遍历器对象,可以用for…of循环进行遍历,唯一的区别是keys()是对键名的遍历、values()是对键值的遍历,entries()是对键值对的遍历。(数组中键名就是索引,键值就是元素)这个和前边Set,Map差不多
let arr = ['a', 3, 5]
for (let key of arr.keys()) {
console.log(key); //0 1 2
}
for (let value of arr.values()) {
console.log(value); // a 3 5
}
for (let [key, value] of arr.entries()) {
console.log(key, value);
//0 'a'
//1 3
//2 5
}
注意理解这三个方法返回的是一个遍历器对象,我们也可以用遍历器对象的next方法对其遍历
//返回一个遍历器对象
let item = arr.entries();
console.log(item.next()); //{value: [0,'a'], done: false}
console.log(item.next().value); //[1,3]
console.log(item.next().value); //[2,'b']
console.log(item.next().value); //undefined
5.includes()
判断某个元素是否在数组中
这个其实是为了替代之前的indexOf,省的再去写判断条件indexOf() === -1了,如果忘了就去翻数组内置对象的数组去重那个案例。
let a = ['zzy', 23, 'ht', 18];
console.log(a.includes('z')); //false
console.log(a.includes(23)); //true