一、块级作用域可以替换立即执行函数表达式
// IIFE 写法 (function () { var tmp = ...; ... }()); // 块级作用域写法 { let tmp = ...; ... }
二、es6允许在块级作用域内部定义函数,在浏览器环境类似于var函数表达式,在其它环境类似于let;块级作用域必须使用{}。
三、申明变量的六种方法var、let、const、import、class、function;
四、es6的默认赋值使用严格相等运算(===),判断一个位置是否有值.undefined会触发默认值;对象的解构赋值可以取到继承的属性
let [x = 1] = [undefined]; x // 1 let [x = 1] = [null]; x // null
let obj1 = {};
var obj2 = {a: 1];
Object.setPrototypeOf(obj1, obj2);
var {a} = obj1;
a // 1
解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。
五、正则的先行断言与后行断言
// 先行断言 /d+(?=%)/.exec('100% of US presidents have been male') // ["100"] /d+(?!%)/.exec('that’s all 44 of them') // ["44"] //后行断言 /(?<=$)d+/.exec('Benjamin Franklin is on the $100 bill') // ["100"] /(?<!$)d+/.exec('it’s is worth about €90') // ["90"]
六、函数参数设置默认值的时候,参数会形成一个单独的作用域(context)。如果参数没有默认值,则和函数体共享作用域。
七、函数的name属性,bind函数的name为加上bound前缀,getter取值函数的name加上get,存值函数setter的name值是加上set,如果是Symbol值,name返回这个symbol的描述
八、箭头函数没有自己的this,所以当然不能用call、apply、bind方法改变this的指向,以及双冒号调用
九、字符串的includes、startWith、endWith方法,数组的includes方法、find(fn)、findIndex(fn)方法------可以识别NaN
十、数组的fill方法、数组copyWithin方法、对象的Object.assign(arr,arr)是用来批量修改数组元素,如果fill的是一个引用数据类型,那么被赋值的是一个内存地址的对象
十一、具有entries、keys、values、forEach方法的对象有数组、对象(没有forEach)、Set、get
十二、数组对空位的处理
十三、Object.is判断两个对象是否恒等
十四、对象属性的遍历方法(五种)
for...in、Object.keys()、Object.getOwnPropertyNames(obj)、Object.getOwnPropertySymbols(obj)、Reflect.ownKeys(obj)
遍历的规则是先遍历数值键(数值大小升序)、再遍历字符串键(加入时间顺序)、最后遍历所有Symbol键(加入时间顺序)
十五、weakSet与weakMap不能遍历,也没有size属性
十五、对象方法添加super关键字,指向对象的原型对象
十六、扩展运算符使用范围:iterator解构与对象,后面可以跟表达式
const obj = { ...(x > 1 ? {a: 1} : {}), b: 2, };
十七、Proxy拦截代理、Relect是对象的补存(感觉就是一堆语法糖)
十八、遍历器对象部署了next()方法;return()方法-----for...of循环内的break、continue、throw new Error()触发,手动触发可以传入参数;throw()方法
十九、类数组对象的定义:其property名为正整数,且其length属性会随着数组成员的增减而发生变化,同时又从Array构造函数中继承了一些用于进行数组操作的方法。都可以用Array.from转为数组对象
二十、Generator函数可以不用yied表达式,这时就变成一个单纯的暂缓执行函数
function* f() { console.log('执行了!') } var generator = f(); setTimeout(function () { generator.next() }, 2000);
二十一、遍历器对象iterator是Generator函数类的实例
function* F() { this.a = 1; yield this.b = 2; yield this.c = 3; } var f = F.call(F.prototype); f.next(); // Object {value: 2, done: false} f.next(); // Object {value: 3, done: false} f.next(); // Object {value: undefined, done: true} f.a // 1 f.b // 2 f.c // 3 Object.getPrototype(f) //Generator f instanceof F //true
二十二、async函数返回一个Promise对象,函数内部的return值会传给then方法的回调函数,函数内部的错误会被返回的promise的catch方法捕获到
await命令后面是一个promise对象,如果不是,会被转成一个立即resolve的promise对象,await命令后的promise的状态如果变为reject,则终止async函数的执行,被async函数返回的promise对象的catch方法捕获 ,所以
async function myFunction() { try { await somethingThatReturnsAPromise(); } catch (err) { console.log(err); } } // 另一种写法 async function myFunction() { await somethingThatReturnsAPromise() .catch(function (err) { console.log(err); }); }
多个await命令后面的异步操作如果不存在继发关系,最好让同时触发
// 写法一 let [foo, bar] = await Promise.all([getFoo(), getBar()]); // 写法二 let fooPromise = getFoo(); let barPromise = getBar(); let foo = await fooPromise; let bar = await barPromise;
二十三、Promise内部的错误不会影响到promise外部的代码,通俗的说法是“promise 会吃掉错误”
const someAsyncThing = function() { return new Promise(function(resolve, reject) { // 下面一行会报错,因为x没有声明 resolve(x + 2); }); }; someAsyncThing().then(function() { console.log('everything is great'); }); setTimeout(() => { console.log(123) }, 2000); // Uncaught (in promise) ReferenceError: x is not defined // 123
// 写法一
let [foo, bar] = await Promise.all([getFoo(), getBar()]);
// 写法二
let fooPromise = getFoo();
let barPromise = getBar();
let foo = await fooPromise;
let bar = await barPromise;
二十四、Class类的概念:实例属性(定义在construcor方法中、用等式写入类的定义中)、原型方法、私有属性(#开头)、私有方法、取值函数、存值函数、Generator方法、静态方法(static关键字,父类的静态方法可以被子类继承)、静态属性
构造函数内部新加new.target属性,返回使用new 命令的构造函数
二十五、super的指向问题
1、在子类constructor内部作为函数使用,指向父类---构造函数
2、在子类constructor内部作为对象使用,取值的时候指向父类的实例属性与原型方法(父类的原型方法this绑定子类的实例this),赋值的时候指向子类的实例this对象
3、在静态方法内部作为对象使用,指向父类的静态方法与属性,父类的静态方法内部使用的this绑定当前子类(不是子类的实例)
super作为对象使用时自带call方法,绑定子类的实例对象this
二十六、export
命令规定的是对外的接口,必须与模块内部的变量建立一一对应关系,不能直接输出值。import命令具有变量提升,模块内部的this指向undefined(用来侦测当前代码是否在es6模块之中)
二十七、如果模块默认输出一个函数,函数名的首字母应该小写。如果模块默认输出一个对象,对象名的首字母应该大写。
二十八、全局对象:globalThis、this、self、window、global的区别
浏览器 | Node | webwork | |
this |
在全局环境,指向顶层对象; 在es模块,指向undefined; 函数内部:指向顶层对象,严格模式指向undefined; new Function('return this')():总是指向顶层对象; |
当前模块 | 同浏览器 |
self | 顶层对象 | 不支持 | 顶层对象 |
window | 顶层对象 | 不支持 | 不支持 |
global | 不支持 | 顶层对象 | 不支持 |
globalThis | 顶层对象 | 顶层对象 | 顶层对象 |
二十九、解决浮点数计算的误差Number.EPSILON
Number.EPSILON代表极小的数字,是2的-52次方,用于解决我们日常在运算中遇到类似0.1+0.2 === 0.3不成立的问题
可以使用
function withinErrorMargin (left, right) { return Math.abs(left - right) < Number.EPSILON * Math.pow(2, 2); }
来排查在误差范围之内的数的等于判断
三十、大数计算:bigInt
javascript64位浮点数,所以只能在2的53次内的精度,大于2的1024就会表示为Infinited
所以新增一个大数计算的数据类型,bigInt用“数字n”的表示方式
三十一、函数的length表示函数预期传入的参数个数,但是在函数可以设定默认值以及rest参数后,length将失真。某个参数指定默认值以后,预期传入的参数个数就不包括这个参数了。同理,后文的 rest 参数也不会计入length
属性。如果设置了默认值的参数不是尾参数,那么length
属性也不再计入后面的参数了。
三十二、链运算符?.用来判断属性与方法是否存在,null判断运算符??用来判断是左边是否是null或者undefined,如果是返回右边的值
链判断运算符有三种用法。
obj?.prop
// 对象属性obj?.[expr]
// 同上func?.(...args)
// 函数或对象方法的调用
三十四、