1.剩余参数(…rest)
作用:将一个不定数量的参数表示为一个数组(旨在取代arguments)
- 首先,我们看看arguments
function show(){
return arguments;
}
console.log(show(1,2,3,4));// [Arguments] { '0': 1, '1': 2, '2': 3, '3': 4 }
- arguments是一个类数组对象,表示输入的所有实参,但没法直接使用Array的方法。
console.log(show(1,2,3,4).sort());// TypeError: show(...).sort is not a function
- 转换arguments为数组
// Array.from()
console.log(Array.from(show(1,2,3,4)));// [1,2,3,4]
// Array.prototype.slice.call()
console.log(Array.prototype.slice.call(show(1,2,3,4)));// [1,2,3,4]
- 剩余参数居然是一个真正的数组,而且看起来作用和arguments一样,那有什么不同或者是改进呢?来看下一个例子
function show(a,...args){
return args;
}
console.log(show(1,2,3,4));// [2,3,4]
估计大家都猜到了,剩余参数顾名思义就是剩下的参数,指没有对应形参的实参(也就是没显式命名的那些参数),上一个例子中…args对应的是后面三个参数
- 同时,配合ES6的解构赋值可以方便取参
function show(a,...[b,c,d]){
return b + c + d;
}
console.log(show(1,2,3,4));// 9
- 总结:
剩余参数可以看做是arguments的升级版,直接返回一个数组,可以更方便使用数组的方法来操作参数。
2.扩展运算符(…)
原理:遍历数组或对象内的可枚举元素,并展开。
- 展开字符串,返回数组
let arr1 = [...'hello'];
console.log(arr1);// [ 'h', 'e', 'l', 'l', 'o' ]
// 等价于
let arr2 = 'hello'.split('');
console.log(arr2);// [ 'h', 'e', 'l', 'l', 'o' ]
- 合并数组或对象
// 合并数组
let arr1 = [1,2,3];
let arr2 = [4,5,6];
console.log([...arr1,...arr2]);// [ 1, 2, 3, 4, 5, 6 ]
// 等价于
console.log(arr1.concat(arr2));// [ 1, 2, 3, 4, 5, 6 ]
// 合并对象
let obj1 = {name:'tom'};
let obj2 = {age:21};
console.log({...obj1,...obj2});// { name: 'tom', age: 21 }
// 等价于
console.log(Object.assign(obj1,obj2));// { name: 'tom', age: 21 }
- 函数传参
function sum(a,b,c){
return a + b + c;
}
let arr = [1,2,3];
console.log(sum(...arr));
- 解构赋值
let [first,...arr] = [1,2,3,4,5];
console.log(arr);// [2,3,4,5]
- 转Set结构为数组(用于数组去重)
let arr = [1,2,2,'a','a'];
let result = [...new Set(arr)];
console.log(result);// [ 1, 2, 'a' ]
- 替代apply
let max1 = Math.max.apply(null,[1,2,3,4]);
// 等价于
let max2 = Math.max(...[1,2,3,4]);
// 等价于
let max3 = Math.max(1,2,3,4);
console.log(max1);// 4
console.log(max2);// 4
console.log(max3);// 4
3.ES6新增数据结构Set和Map
Set
S6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。Set本身是一个构造函数,用来生成 Set 数据结构。Set函数可以接受一个数组(或者具有 iterable 接口的其他数据结构)作为参数,用来初始化。
// 例一
const set = new Set([1, 2, 3, 4, 4]);
[...set]
// [1, 2, 3, 4]
// 例二
const items = new Set([1, 2, 3, 4, 5, 5, 5, 5]);
items.size // 5
// 例三
const set = new Set(document.querySelectorAll('div'));
set.size // 56
// 类似于
const set = new Set();
document
.querySelectorAll('div')
.forEach(div => set.add(div));
set.size // 56
上面代码中,例一和例二都是Set函数接受数组作为参数,例三是接受类似数组的对象作为参数。
去除数组重复成员的方法:[…new Set(array)]
去除字符串里面的重复字符:[…new Set(‘ababbc’)].join(’’)
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(1).add(2).add(2);
// 注意2被加入了两次
s.size // 2
s.has(1) // true
s.has(2) // true
s.has(3) // false
s.delete(2);
s.has(2) // false
遍历方法:
- Set.prototype.keys():返回键名的遍历器
- Set.prototype.values():返回键值的遍历器
- Set.prototype.entries():返回键值对的遍历器
- Set.prototype.forEach():使用回调函数遍历每个成员
let set = new Set(['red', 'green', 'blue']);
for (let item of set.keys()) {
console.log(item);
}
// red
// green
// blue
for (let item of set.values()) {
console.log(item);
}
// red
// green
// blue
for (let item of set.entries()) {
console.log(item);
}
// ["red", "red"]
// ["green", "green"]
// ["blue", "blue"]
Map
JavaScript 的对象(Object),本质上是键值对的集合(Hash 结构),但是传统上只能用字符串当作键。这给它的使用带来了很大的限制。为了解决这个问题,ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。
const m = new Map();
const o = {p: 'Hello World'};
m.set(o, 'content')
m.get(o) // "content"
m.has(o) // true
m.delete(o) // true
m.has(o) // false
上面代码使用 Map 结构的set方法,将对象o当作m的一个键,然后又使用get方法读取这个键,接着使用delete方法删除了这个键。
上面的例子展示了如何向 Map 添加成员。作为构造函数,Map 也可以接受一个数组作为参数。该数组的成员是一个个表示键值对的数组。
const map = new Map([
['name', '张三'],
['title', 'Author']
]);
map.size // 2
map.has('name') // true
map.get('name') // "张三"
map.has('title') // true
map.get('title') // "Author"
Map实例的属性和方法
属性:
- size:返回 Map 结构的成员总数。
操作方法:
- Map.prototype.set(key, value):set方法设置键名key对应的键值为value,然后返回整个 Map 结构。如果key已经有值,则键值会被更新,否则就新生成该键。
- Map.prototype.get(key):get方法读取key对应的键值,如果找不到key,返回undefined。
- 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 的所有成员。
需要特别注意的是,Map 的遍历顺序就是插入顺序。
4.es6新增方法
字符串新方法
- includes():返回布尔值,表示是否找到了参数字符串。
- startsWith():返回布尔值,表示参数字符串是否在源字符串的头部。
- endsWith():返回布尔值,表示参数字符串是否在源字符串的尾部。
var s = 'zfpx';
s.startsWith('z') // true
s.endsWith('x') // true
s.includes('p') // true
- repeat:repeat方法返回一个新字符串,表示将原字符串重复n次。
数值的新方法
- Number.isNaN()用来检查一个值是否为NaN。
Number.isNaN(NaN) // true
Number.isNaN(15) // false
Number.isNaN('15') // false
Number.isNaN(true) // false
Number.isNaN(9/NaN) // true
Number.isNaN('true' / 0) // true
Number.isNaN('true' / 'true') // true
- Number.isInteger()用来判断一个数值是否为整数。
Number.isInteger(25) // true
Number.isInteger(25.1) // false
- from:方法
用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括 ES6 新增的数据结构 Set 和 Map)。
let arrayLike = {
'0': 'a',
'1': 'b',
'2': 'c',
length: 3
};
// ES5的写法
var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']
// ES6的写法
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
- of:是为了将一组数值,转换为数组(弥补Array方法的不足)
let arr1=Array.of(2,7,9); //输出[ 2, 7, 9 ]
- find和findIndex:查到对应的元素和索引
let arr = [1, 2 ,3, 3, 4, 5];
let find = arr.find((item, index, arr) => {
return item === 3;
});
let findIndex = arr.findIndex((item, index, arr) => {
return item === 3;
});
console.log(find, findIndex);
- fill :就是填充数组的意思 会更改原数组 Array.prototype.fill(value, start, end = this.length);
let arr = [1, 2, 3, 4, 5, 6];
arr.fill('a', 1, 2);
console.log(arr);
ES6 提供三个新的方法——entries(),keys()和values()——用于遍历数组可以用for…of循环进行遍历,唯一的区别是keys()是对键名的遍历、values()是对键值的遍历,entries()是对键值对的遍历。
for (let index of ['a', 'b'].keys()) {
console.log(index);
}
// 0
// 1
for (let elem of ['a', 'b'].values()) {
console.log(elem);
}
// 'a'
// 'b'
for (let [index, elem] of ['a', 'b'].entries()) {
console.log(index, elem);
}
// 0 "a"
// 1 "b"
对象新方法
- Object.is对比两个值是否相等
相等运算符(==)和严格相等运算符(===)。它们都有缺点,前者会自动转换数据类型,后者的NaN不等于自身,以及+0等于-0。
console.log(Object.is(NaN,NaN));
这个方法与'==='的行为基本一致
- Object.assign把多个对象的属性复制到一个对象中,第一个参数是复制的对象,从第二个参数开始往后,都是复制的源对象
var nameObj = {name:'zfpx'};
var ageObj = {age:8};
var obj = {};
Object.assign(obj,nameObj,ageObj);
console.log(obj);
//克隆对象
function clone (obj) {
return Object.assign({}, obj);
}
- Object.setPrototypeOf将一个指定的对象的原型设置为另一个对象或者null
var obj1 = {name:'zfpx1'};
var obj2 = {name:'zfpx2'};
var obj = {};
Object.setPrototypeOf(obj,obj1);
console.log(obj.name);
console.log(Object.getPrototypeOf(obj));
Object.setPrototypeOf(obj,obj2);
console.log(obj.name);
console.log(Object.getPrototypeOf(obj));
- proto 直接在对象表达式中设置prototype
var obj1 = {name:'zfpx1'};
var obj3 = {
__proto__:obj1
}
console.log(obj3.name);
console.log(Object.getPrototypeOf(obj3));
- super 通过super可以调用prototype上的属性或方法
let person ={
eat(){
return 'milk';
}
}
let student = {
__proto__:person,
eat(){
return super.eat()+' bread'
}
}
console.log(student.eat());
- Object.keys(),Object.values(),Object.entries()
- Object.keys()
ES5 引入了Object.keys方法,返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名
var obj = { foo: 'bar', baz: 42 };
Object.keys(obj)
// ["foo", "baz"]
ES2017 引入了跟Object.keys配套的Object.values和Object.entries,作为遍历一个对象的补充手段,供for…of循环使用。
- Object.entries会把对象转化为二维数组
let {keys, values, entries} = Object;
let obj = { a: 1, b: 2, c: 3 };
for (let key of keys(obj)) {
console.log(key); // 'a', 'b', 'c'
}
for (let value of values(obj)) {
console.log(value); // 1, 2, 3
}
for (let [key, value] of entries(obj)) {
console.log([key, value]); // ['a', 1], ['b', 2], ['c', 3]
}