声明
- let
- 块级作用域,for 循环中设置循环变量的是一个父作用域,循环体内部是一个单独的子作用域。
for(let i = 0; i < 3; i++) { let i = '123'; console.log(i); } // 123 // 123 // 123
-
- 不存在变量提升:let声明的变量一定要在声明之后使用(和var不同)。
- 暂时性死区: 代码块内在用let声明之前使用已声明的全局变量会报错,在有let的代码块内会形成暂时性死区 (temporal dead zone)
- 不允许重复声明
- 块级作用域
- const 声明常量,在块级作用域内有效。
- 这里用const声明,不是变量的值不能改变,而是变量指向的那个内存地址所保存的数据不能改动,
- 对于复合类型的数据(对象和数组),变量指向实际数据的指针,指针指向的数据结构是可以改变的。
- 对于简单类型的数据(数值、布尔值、字符串),等同于常量。
const foo = {}; foo.prop = 123; // 可以为foo添加属性 foo = {} // 指向另一个对象,报错
- 顶层对象的属性
- var 和 function 声明的全局变量,是顶级对象(global或window)的属性。
- let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。
变量的解构赋值
- 数组的解构赋值
- 只要某种数据结构具有 Iterator 接口,都可以采用数组形式的解构赋值。
- 形式:let [x, y] = [1, 2]
- 默认值:let [x = 1, y = x] = []
- 对象的解构赋值
- 字符串的解构赋值:
- const [a,b,c,d,e] = 'hello'
- let { length : len } = 'hello' // len ---->5
- 函数参数的解构赋值:
- 对象:function move({x = 0, y = 0} = {}) {return [x, y];}
- 数组:function add([x, y]){ return x + y;}
- 用途:
- 交换变量的值:
let x = 1; let y = 2; [x, y] = [y, x]
-
- 从函数返回多个值:
function example() { return [1,2,3]; } let [a,b,c] = example();
字符串的扩展
- 字符的 Unicode 表示法
- 字符串的遍历器接口 (用for...of循环遍历)
- 直接输入U+2028 和 U+2029
- JSON.stringify()的改造
- 模版字符串 (无法加入其他语言)
- 标签模版: 函数调用的一种特殊形式
- String.raw() 返回一个斜杠都被转移的字符串,(在所有斜杠前都增加了一个字符串)
- codePointAt() 处理四个字节存储的字符,返回一个字符的码点(十进制)
- normalize() Unicode正规化
- includes(),startsWith(),endsWith() (返回布尔值)
- repeats() 返回一个新的字符串,表示将字符串重复n次
- padStart(),padEnd()
- matchAll()返回一个正则表达式在字符串的所有匹配。
正则的扩展
数组的扩展
- 扩展运算符
- 将一个数组转换为用逗号隔开的参数序列(...[1,2,3])// 1 2 3
- 主要用于函数调用
- 代替函数的apply方法
- 应用:
- 复制数组:es5用变通的方法复制数组 es6: const a2 = [...a1] || const [...a2] = a1; (深拷贝)
- 合并数组:es5: a1.concat[a2] es6: [...a1, ...a2, ...a3] (都是浅拷贝)
- 与解构赋值结合生成数组: const [first, ...rest] = [1, 2, 3, 4, 5] // first===1; rest ===[2,3,4,5]
- 将字符串转为真正的数组: [...'12345'] // [1,2,3,4,5]
- 实现了 Iterator 接口的对象,都可以用扩展运算符转为真正的数组(比如NodeList)
- Map,Set结构 Generator函数也能转化为数组
- Array.from()将类似数组的对象转化为真正的数组
- Array.of()方法应用于将一组值转化为数组 Array.of(1,2,3) // [1,2,3]
- Array.prototype.copyWithin(target, start = 0, end = this.length) 将指定位置的成员复制到其他位置,会改变原来的数组
- find()用于找出第一个符合条件的数组成员 findIndex()
- fill() 使用给定值填充数组
- entries(),keys(),values() 可以用for..of循环遍历 或者调用遍历器对象的next()
- entries() 对键值对的遍历:
for(let [index, elem] of [1,2,3].entries()) { console.log(index, elem) }
-
- keys() 是对键名的遍历
for(let index of [1,2].keys()) { console.log(index) }
-
- values() 是对键值的遍历
- includes() 返回一个布尔值,表示某个数组是否包含给定值
- flat() 用于扯平数组 [1,2,[3,4]].flat(1) // [1,2,3,4] 参数表示拉平的层数 会跳过空位,返回一个新数组
- flatMap()对愿数组的每一个成员执行一个函数(map())对返回值执行flat()方法, 返回一个新数组,但是只能展开一层数组
- es6明确将数组的空位都转化为undefined,array.from([1, ,2]) // [1, undefined, 2] 扩展运算符也是
- ES2019 明确规定,Array.prototype.sort()的默认排序算法必须稳定。这个规定已经做到了,现在 JavaScript 各个主要实现的默认排序算法都是稳定的。
对象的扩展
- 属性的简洁表示法: ES6允许在大括号里面直接写入变量和函数,作为对象的属性和方法。
- 属性名表达式: 方括号里可以为表达式
- obj.foo = true
- obj['a' + 'bc'] = 123
- let obj = { ['he' + 'llo'](){
return 'hi'
}
}
- 方法的name属性
- 属性的可枚举性和遍历
- 遍历对象的属性
- for..in (循环对象自身的和继承的属性
- object.Keys(obj)返回一个数组,包括对象自身的所有可枚举属性的键值
- Object.getOwnPropertyNames(obj)返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)的键名。
- Object.getOwnPropertySymbols返回一个数组,包含对象自身的所有 Symbol 属性的键名。
- Reflect.ownKeys返回一个数组,包含对象自身的所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举。
- super 关键字 指向对象原型上的属性
- 遍历对象的属性
- 对象的扩展运算符
- 解构赋值 用于从一个对象取值 let { x,y,...z } = { x:1, y:2, a:3, b;4 }
- x // 1
- y // 2
- z // { a:3, b:4 }
- 解构赋值必须是最后一个参数, 浅拷贝
- 如果使用解构赋值,扩展运算符后面必须是一个变量名,而不能是一个解构赋值表达式。
- 对象的扩展运算符 === Object.assign(),
- let aClone = { ...a }; === let aClone = Object.assign({}, a)
- 扩展运算符可以用于合并两个对象
- let ab = {...a , ...b} === let ab = Object.assign({}, a, b)
- 解构赋值 用于从一个对象取值 let { x,y,...z } = { x:1, y:2, a:3, b;4 }
- 对象的新增方法
- Object.is() 一是+0不等于-0,二是NaN等于自身
- Object.assign(target, source1, source2)