ES6语法扩展

Lán2022年11月8日
大约 9 分钟

ES6语法扩展

剩余参数

剩余参数永远是个数组,即使没有值,也是空数组

const add = (x, y, z, ...args) => {};

箭头函数的参数部分即使只有一个剩余参数,也不能省略圆括号,使用剩余参数替代 arguments 获取实际参数

const add = (...args) => {};

剩余参数只能是最后一个参数,之后不能再有其他参数,否则会报错

剩余参数不一定非要作为函数参数使用,也可以与解构赋值结合使用,并且必须是最后一个

const [num, ...args] = [1, 2, 3, 4];
console.log(num, args);

const func = ([num, ...args]) => {};
func([1, 2, 3]);

const { x, y, ...z } = { a: 3, x: 1, y: 2, b: 4 };
console.log(x, y, z);

const func = ({ x, y, ...z }) => {};
func({ a: 3, x: 1, y: 2, b: 4 });

数组的展开运算符

数组展开运算符的基本用法

console.log(Math.min(...[3, 1, 2]));
//相当于
//console.log(Math.min(3, 1, 2));

复制数组

const a = [1, 2];
const c = [...a];

合并数组

const a = [1, 2];
const b = [3];
const c = [4, 5];
console.log([...a, ...b, ...c]);

字符串转为数组

console.log([...'alex']);

常见的类数组转化为数组

  //arguments
  function func() {
    console.log([...arguments]);
  }
  func(1, 2);

  // NodeList
  console.log(document.querySelectorAll('p'));
  console.log([...document.querySelectorAll('p')].push); //变成数组,有数组方法

对象的展开运算符

对象的展开:把属性罗列出来,用逗号分隔,放到一个 {} 中,构成新对象

const apple = {
   color: '红色',
   shape: '球形',
   taste: '甜'
};
console.log({...apple});

合并对象时,新对象拥有全部属性,相同属性,后者覆盖前者

如果展开一个空对象,则没有任何效果

如果展开的不是对象,则会自动将其转为对象,再将其属性罗列出来

console.log({ ...1 }); // {}
console.log({ ...undefined }); // {}
console.log({ ...null });  // {}
console.log({ ...true }); // {}

如果展开运算符后面是字符串,它会自动转成一个类似数组的对象,因此返回的不是空对象

console.log({ ...'alex' });

如果展开运算符后面是数组,和字符串类似

console.log({ ...[1, 2, 3] });

不会展开对象中的对象属性,并且不会合并对象中对象的属性值

应用1:复制对象

const a = { x: 1, y: 2 };
const c = { ...a };

应用2:用户参数和默认参数

const logUser = userParam => {
    const defaultParam = {
      username: 'ZhangSan',
      age: 0,
      sex: 'male'
    };
    const param = { ...defaultParam, ...userParam };
    const { username, age, sex } = { ...defaultParam, ...userParam }; //解构赋值
    console.log(username, age, sex);
  };
logUser();
logUser({username: 'Xiaoming'});

Set

Set 是一系列无序、没有重复值的数据集合

  const s = new Set();
  s.add(1);
  s.add(2);
  console.log(s);

add方法,添加成员,可以使用连缀写法

 s.add(1).add(2).add(3);

has方法,判断是否有某成员

 console.log(s.has(1));

delete方法,删除指定成员

 s.delete(1);
 //使用 delete 删除不存在的成员,什么都不会发生,也不会报错
 s.delete(19);

clear方法,清空成员

 s.clear();

forEach方法遍历,按照成员添加进集合的顺序遍历

s.forEach(function(value,key,set){
    //Set 中,value == key
    console.log(value,key,set);
},document);

size属性

let size = s.size;

Set 构造函数的参数

构造函数的参数可以有,数组、字符串、arguments、NodeList、Set 等

const s1 = new Set([1, 2, 1]);
const s2 = new Set('hello');
const s3 = new Set(document.querySelectorAll('p'));
const s4 = new Set(new Set([1,2,3,6]));
function func(){
    const s5 = new Set(arguments);
}
func(1,2,1);

Set 对重复值的判断基本遵循严格相等(===)
但是对于 NaN 的判断与 === 不同,Set 中 NaN 等于 NaN

什么时候使用 Set

  • 数组或字符串去重时
  • 不需要通过下标访问,只需要遍历时
  • 为了使用 Set 提供的方法和属性时(add delete clear has forEach size 等)

应用1:数组去重

console.log([...new Set([1, 2, 1])]);

应用2:字符串去重

console.log([...new Set('abbacbd')].join(''));

应用3:存放 DOM 元素

const s = new Set(document.querySelectorAll('p'));
s.forEach(function(v){
    v.style.color = 'red';
})

Map

Map 和对象都是键值对的集合

Map 和对象的区别:
对象一般用字符串当作键
基本数据类型:数字、字符串、布尔值、undefined、null,引用数据类型:对象([]、{}、函数、Set、Map 等)。以上都可以作为 Map 的键

set方法,添加成员,可以使用连缀写法, 使用 set 添加的新成员,键如果已经存在,后添加的键值对覆盖已有的

const map = new Map();
map.set('age',18).set(true,'true');

get方法获取指定成员,get 获取不存在的成员,返回 undefined

cosole.log(map.get('age'));
cosole.log(map.get(true));

has方法,判断是否有某成员

console.log(map.has('age')); //true

delete方法,删除指定成员,使用 delete 删除不存在的成员,什么都不会发生,也不会报错

map.delete('age');

clear方法,清空成员

map.clear();

forEach方法遍历

map.forEach(function(value,key,map){
    console.log(value,key,map)
});

size属性

let size = map.size;

Map 构造函数的参数有哪些

传入数组

只能传二维数组,而且必须体现出键和值

console.log(new Map([
    ['name', 'alex'],
    ['age', 18]
]));

传入Set、Map 等

Set 中也必须体现出键和值

const s = new Set([
  ['name', 'alex'],
  ['age', 18]
]);
console.log(new Map(s));
console.log(s);

// 复制了一个新的 Map
const m1 = new Map([
   ['name', 'alex'],
   ['age', 18]
]);
console.log(m1);
const m2 = new Map(m1);
console.log(m2, m2 === m1);

Map中如何判断键值对是否相同

基本遵循严格相等(===)
例外就是 NaN,Map 中 NaN 也是等于 NaN

什么时候使用 Map

如果只是需要 key -> value 的结构,或者需要字符串以外的值做键,使用 Map 更合适

遍历器与for...of循环

Iterator:遍历器(迭代器)

const it = [1, 2][Symbol.iterator]();
console.log(it.next()); // {value: 1, done: false}
console.log(it.next()); // {value: 2, done: false}
console.log(it.next()); // {value: undefined, done: true}
console.log(it.next()); // {value: undefined, done: true}

Symbol.iterator(可遍历对象的生成方法) -> it(可遍历对象) -> it.next() -> it.next() -> ...(直到 done 为 true)

for...of 的用法

const arr = [1,2,3,4,5,6,7,8]
for(const item of arr){
    console.log(item);
}

for...of 循环只会遍历出那些 done 为 false 时,对应的 value 值

可以与 break、continue 一起使用

在 for...of 中取得数组的索引

keys() 得到的是索引的可遍历对象,可以遍历出索引值

const arr = [1,2,3,4,5,6,7,8]
for (const key of arr.keys()) {
    console.log(key);
}

values() 得到的是值的可遍历对象,可以遍历出值

for (const value of arr.values()) {
    console.log(value);
}

entries() 得到的是索引+值组成的数组的可遍历对象

for (const entries of arr.entries()) {
    console.log(entries);
}

//解构写法
for (const [index,value] of arr.entries()) {
    console.log(index, value);
}

只要有 Symbol.iterator 方法,并且这个方法可以生成可遍历对象,就是可遍历的

只要可遍历,就可以使用 for...of 循环来统一遍历

原生可遍历的有哪些

  • 数组
  • 字符串
  • Set
  • Map
  • arguments
  • NodeList

非原生可遍历的有哪些

  • 一般的对象

数组的展开运算符使用了for...of机制,因此可遍历的对象也都可以使用展开运算符
数组的解构赋值使用了for...of机制,因此可遍历的对象也都可以使用解构赋值

Set、Map的构造函数也是使用了迭代器的原理,因此可以传入可迭代对象作为初始化数据

ES6字符串新增方法

includes()方法

查找是否包含字符内容

console.log('abc'.includes('a'));
console.log('abc'.includes('ab'));
console.log('abc'.includes('bc'));
console.log('abc'.includes('ac')); // false

第二个参数,表示开始搜索的位置,默认是 0

console.log('abc'.includes('a'));
console.log('abc'.includes('a', 0));
console.log('abc'.includes('a', 1)); // false

padStart()、padEnd()方法

补全字符串长度

console.log('x'.padStart(5, 'ab')); //ababx
console.log('x'.padEnd(5, 'ab')); //xabab
console.log('x'.padEnd(4, 'ab')); //xaba

原字符串的长度,等于或大于最大长度,不会消减原字符串,字符串补全不生效,返回原字符串

console.log('xxx'.padStart(2, 'ab')); //xxx
console.log('xxx'.padEnd(2, 'ab')); //xxx

用来补全的字符串与原字符串长度之和超过了最大长度,截去超出位数的补全字符串,原字符串不动

console.log('abc'.padStart(10, '0123456789')); //0123456abc
console.log('abc'.padEnd(10, '0123456789')); //abc0123456

如果省略第二个参数,默认使用空格补全长度

console.log('x'.padStart(4)); //空格空格空格x
console.log('x'.padEnd(4)); //x空格空格空格

trimStart()、trimEnd()方法

清除字符串的首或尾空格,中间的空格不会清除

const s = '  a b c  ';
console.log(s);
console.log(s.trimStart()); //清楚前面的空格
console.log(s.trimLeft()); //清楚前面的空格
console.log(s.trimEnd()); //清楚结尾的空格
console.log(s.trimRight()); //清楚结尾的空格
console.log(s.trim()); //清楚左右两边的空格

ES6数组新增方法

includes()方法

判断数组中是否包含某个成员

console.log([1, 2, 3].includes('2')); // false console.log([1, 2, 3].includes(2)); // true

第二个参数表示搜索的起始位置,默认值是 0

console.log([1, 2, 3].includes(2, 2));

基本遵循严格相等(===),但是对于 NaN 的判断与 === 不同,includes 认为 NaN === NaN

Array.from()

将其他数据类型转换成数组

基本用法
console.log(Array.from('str'));

哪些可以通过 Array.from() 转换成数组
所有可遍历的,数组、字符串、Set、Map、NodeList、arguments
拥有 length 属性的任意对象,但只遍历数值类型的键

console.log(Array.from(new Set([1, 2, 1])));
console.log([...new Set([1, 2, 1])]);

const obj = {
  '0': 'a',
  '1': 'b',
  name: 'Alex', //不会被转换
  length: 3
};
console.log(Array.from(obj)); 
第二个参数

作用类似于数组的 map 方法,用来对每个元素进行处理,将处理后的值放入返回的数组

console.log(
  [1, 2].map(value => {
    return value * 2;
  })
);
console.log(Array.from('12', value => value * 2));
console.log(Array.from('12').map(value => value * 2));
第三个参数

修改this指向

Array.from(
    '12',
    value => {
      console.log(this);
    },
    document
  );
Array.from(
  '12',
  function () {
    console.log(this);
  },
  document
);

find()、findIndex()

find():找到满足条件的一个立即返回
findIndex():找到满足条件的一个,立即返回其索引
第二个参数为this指向

基本用法

let v = [1, 5, 10, 15].find(function (value, index, arr) {
  // console.log(value, index, arr);
  console.log(this);
  return value > 9;
}, document);
let index = [1, 5, 10, 15].findIndex((value, index, arr) => {
  // console.log(value, index, arr);
  return value > 9;
}, document);

ES6对象新增方法

Object.assign()

用来合并对象,直接合并到了第一个参数中,返回的就是合并后的对象

Object.assign(目标对象, 源对象1,源对象2,...): 目标对象

注意事项,基本数据类型作为源对象,与对象的展开类似,先转换成对象,再合并

console.log(Object.assign({}, undefined));
console.log(Object.assign({}, null));
console.log(Object.assign({}, 1));
console.log(Object.assign({}, true));
console.log(Object.assign({}, 'str'));

Object.keys()、Object.values() 和 Object.entries()

基本用法

const person = {
  name: 'Alex',
  age: 18
};

console.log(Object.keys(person));
console.log(Object.values(person));
console.log(Object.entries(person));

与数组类似方法的区别
数组的 keys()、values()、entries() 等方法是实例方法,返回的都是 Iterator
对象的 Object.keys()、Object.values()、Object.entries() 等方法是构造函数方法,返回的是数组

Object.keys()/values()/entires() 并不能保证顺序一定是你看到的样子,这一点和 for in 是一样的

上次编辑于: 2022/11/8 16:59:05
贡献者: lanjd