1. let、const、var
- 块级作用域:let和const都有块级作用域,var声明的是函数作用域。
- 变量提升:var命令会产生变量提升现象,即变量可以在声明之前使用,值为undefined;let和const没有变量提升,它所声明的变量一定要在声明后使用,否则报错。
- 暂时性死区:在代码块内,在let或const命令声明之前,该变量都是不可用的,即使前面存在var声明的相同变量名。
- let和const不允许在相同作用域内,重复声明同一变量。
- 在全局作用域中使用var声明的变量会成为window对象的属性,let和const不会。
- const声明一个只读的常量,一旦声明,常量的值就不能改变。这意味着,const一旦声明,就必须立即初始化,不能留到以后赋值。本质:const实际上保证的,并不是变量的值不能改动,而且变量指向的那个内存地址所保存的数据不能改动。如果真的想冻结对象,可以使用Object.freeze({})
彻底冻结对象的方法:var constantize = obj => { Object.freeze(obj); Object.keys(obj).forEach( key => { if(typeof obj[key] === 'object'){ constantize(obj[key]) } }) }
- es6声明变量的六种方法:
es5只有两种:var和function,es6:let、const、import、class
2. 变量的解构赋值
ES6允许按照一定方式,从数组和对象中提取值,对变量进行赋值,这被称为解构。
- 数组的解构赋值
(1)按照对应位置,从数组中提取值给变量赋值;如果解构不成功,变量的值就等于undefined。只要某种数据结构具有Iterator接口,都可以采用数组形式的解构赋值。
(2)解构赋值允许指定默认值。ES6内部使用严格相等运算符,只有当一个数组成员严格等于undefined,默认值才会生效。 - 对象的解构赋值
(1)数组的元素是按照次序的,而对象的属性没有顺序,变量必须与属性同名,才能取到正确的值。解构失败,值为undefined。
(2)同数组一样,允许指定默认值,当严格等于undefined时,才会生效。 - 字符串的解构赋值
字符串也可以解构赋值,这是因为此时,字符串被转换成了一个类似数组的对象
3. 字符串
- 模板字符串
反引号(`)表示,它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。将变量放在${}中 - 字符串的新增方法
includes():返回布尔值,表示是否找到了参数字符串;
startsWith():返回布尔值,表示参数字符串是否在原字符串的头部;
endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部。
这三个参数都支持第二个参数,表示开始搜索的位置。
使用第二个参数n时,endsWith的行为与其他两个方法有所不同,它针对前n个字符,其他两个针对从第n个位置开始直到字符串结束。let s = 'Hello world!'; s.startsWith('world', 6) // true s.endsWith('Hello', 5) // true s.includes('Hello', 6) // false
- padStart(len,str)、padEnd(len,str):在头部或尾部补全长度
4. 数组的扩展
- 扩展运算符…
将一个数组转为用逗号分隔的参数序列。
应用:
(1)复制数组
es5:concat() es6:…
这两种都是浅拷贝,只对数组一层有效
(2)与解构赋值结合,用于生成数组。
[0,…rest] = [1,2,3,4]
如果将扩展运算符用于数组赋值,只能放在参数的最后一位,否则会报错。
(3)字符串:扩展运算符还可以将字符串转换为真正的数组[...'hello'] // [ "h", "e", "l", "l", "o" ]
- Array.from():将两类对象转为真正的数组:类似数组的对象和可遍历的对象(包含Set和Map)
- Array.prototype.includes:返回一个布尔值,表示某个数组是否包含给定的值,与字符串的includes相似。
5. 对象的新增方法
- Object.assign():将所有可枚举属性的值从一个或多个源对象复制到目标对象,返回目标对象。用于对象的合并,第一个参数是目标对象,后面都是源对象,拷贝是有限制的,只拷贝源对象的自身属性(不拷贝继承属性),也不拷贝不可枚举的属性(enumerable:false) 是浅拷贝。
- Object.keys():返回一个数组,成员是参数对象自身的(不含继承)所有可遍历属性的键名。
- Object.values():同上,返回的是键值。
- Object.entries():同上,返回键值对数组。
- Object.fromEntries():entries的逆操作,用于将一个键值对数组转为对象。
6.类和对象
- 面向对象思维的特点:
抽取对象共有的属性和行为封装成一个类;对类进行实例化,获取类和对象 - 类和对象的区别
类抽象了对象的公共部分,泛指某一大类;
对象特指某一个,通过类实例化一个具体的对象;
类必须使用new实例化对象。 - 语法规范
(1)用class关键字声明一个类,首字母大写;
(2)类里面的constructor函数,存放的是类的共有属性,可以接受传递过来的参数,同时返回实例对象,只要new生成实例时,就会自动调用这个函数,如果我们不写这个函数,类会自动生成这个函数;
(3)生成实例的new不能省略;
(4)创建类时,类名后面不加小括号,生成实例,类后面加小括号
(5)构造函数不需要加function
(6)多个函数方法之间不需要用逗号 - 静态方法
在方法前加上static关键字,该方法不会被实例继承,而是直接通过类来调用。 - 继承
通过extends关键字实现继承,子类必须在constructor方法中调用super方法,否则新建实例时会报错,因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法。父类的静态方法,也会被子类继承。
es5的继承,实质上是先创造子类的实例对象this,然后再将父类的方法添加到this上面。es6的继承机制完全不同,实质是先将父类实例对象的属性和方法,加到this上面(所以要先调用super),然后再用子类的构造函数修改this。
7.Promise
- Promise是异步编程的一种解决方案,它有两个特点:
(1)对象的状态不受外界影响。共有三种状态:pending进行中、fulfilled已成功和rejected已失败,只有异步操作的结果,可以改变这种状态。
(2)一旦状态改变,就不会再变。 - Promise对象是一个构造函数,用来生成Promise实例。它接受一个函数作为参数,该函数有两个参数resolve和reject
- then方法:then方法的第一个参数是resolved状态的回调函数,第二个是rejected状态的回调函数,它们都是可选的。then方法返回的是一个新的Promise实例,因此可以采用链式写法。
- catch方法:用于指定发生错误时的回调函数。如果异步操作抛出错误,状态就会变为rejected,就会调用catch方法,另外,then方法指定的回调函数,如果运行中抛出错误,也会被catch捕获。
- finally方法:不管Promise最后状态如何,都会执行的操作。
- all方法:接受一个数组作为参数,数组元素都是Promise实例。只有所有的状态都是fulfilled,最终状态才是fulfilled,每个实例的返回值组成一个数组;只要有一个是rejected状态,最终状态就是rejected,第一个被reject的实例的返回值,会传递给最终实例的回调函数。
8.展开多维数组
除了使用arr.flat()外,还可以通过以下方法实现:
arr = [1,2,4,6,[5,4,5,[98,3],[34],[7]]]
arr.toString().split(‘,’).map(Number)
[1,2,4,6,5,4,5,98,3,34,7]