var,let,const
var
- 声明只区分全局或者函数作用域里
- 全局声明时(在最顶部的范围)创建
window对象的属性 - 可重复声明(在同一个作用域里)
- 会声明提升,在赋值前访问返回
undefined
let
- let和const声明在块作用域
{}里,for(let a of [])属于块作用域 - 全局声明时,不会创建
window对象的属性 - 不可重复声明(在同一个作用域里)
1.
switch不同的case里声明属于不同的作用域
- 不会声明提升,在赋值前访问会ReferenceError,该变量处在一个当前块顶部到初始化处理的“暂存死区”中
const
- 不能重新赋值
- 必须在声明的同一语句中指定它的值,否则
SyntaxError - 声明其实创建的是一个值的只读引用
所以可以声明为
object,可以改变object的key或者value或者数组的单元,但是不能整个赋值一个新的对象或者数组
this
文档
developer.mozilla.org/zhCN/docs/W…
普通函数this运行时绑定
//
fn(1,2) // fn.call(undefined,1,2)
obj.fn(1,2) // obj.fn.call(obj,1,2)
arr[0](1,2) // arr[0].call(arr,1,2)
箭头函数
//箭头函数this永远指向定义时的词法作用域,不会通过call,apply,bind改变
()=>{return this}
bind(this)
//如果通过bind生成了一个指定this的函数,其this永远绑定在第一次绑定的this上
let fn2=fn.bind(this1)
fn2.bind(this2)
构造函数
//构造函数与普通函数this差不多,在调用成员对象时候决定this指向调用者obj
function ClassObj(name){
this.name=name
//当new一个函数的时候,return this绑定到构建的对象上
//return this
}
var obj=new ClassObj('张三')
obj.name// 张三
原型链上的this
var o = {
f: function() {
return this.a + this.b;
}
};
var p = Object.create(o);
p.a = 1;
p.b = 4;
console.log(p.f()); // 5
//如果在一个对象上的原型上找到,this还是指向这个对象
Promise
then
调用 Promise 的 then(..) 会自动创建一个新的 Promise 从调用返回
catch
promise.then(null,function(err){})
等价于
promise.catch(function(err){})
Promise.resolve
Promise.resolve(fn)如果fn是一个promise那么返回fn,两者是相等的,如果是其他函数,会转成一个带有fn返回值的promise
Promise.all
Promise.all([])
如果都fulfilled返回一个数组,包含所有同步或异步的值;如果有一个失败(rejected),则返回失败,失败的原因是第一个失败 promise 的结果。
[[PromiseStatus]]: "rejected"
[[PromiseValue]]: 2
如果是空数组,将直接完成
Promise.allSettled
Promise.allSettled([])
如果都已经fulfilled或者rejected返回[]包含所有同步或异步的状态和值。
[[PromiseStatus]]: "fulfilled"
[[PromiseValue]]: Array(2)
0: {status: "fulfilled", value: 1}
1: {status: "rejected", value: 2}
如果是空数组,将直接完成
Promise.race
Promise.race([])只要有其中一个promise完成或者拒绝,就返回那个promise的值多个promise竞速
如果是空数组,那么将一直是pending
[[PromiseStatus]]: "pending"
[[PromiseValue]]: undefined
setTimeout(fn,time)
只是在一定时间time后将fn放入事件队列中,所以不能保证在time时间点执行fn,可能在这个时间点之后,但一定不在这个时间之前
==与===
==会进行强制类型转换,===不进行强制类型转换,所以如果能保证两边的类型是一样的,==也是安全效率的
generator与yield
文档
developer.mozilla.org/zh-CN/docs/…*
function* foo(x) {
var y = x * (yield);
return y;
}
var it = foo( 6 );
// 启动foo(..)
it.next();
var res = it.next( 7 );
res.value; // 42
!!!第一个 next(..) 总是启动一个生成器,并运行到第一个 yield 处。不过,是第二个 next(..) 调用完成第一个被暂停的 yield 表达式,第三个 next(..) 调用完成第二个 yield,以此类推
Array
Array.from
生成0-10的数组
Array.from({length: 11},(item,i => i))
Array.prototype.every
[].every(()=>{}) // true
every 和数学中的"所有"类似,当所有的元素都符合条件才会返回true。正因如此,若传入一个空数组,无论如何都会返回 true。(这种情况属于无条件正确:正因为一个空集合没有元素,所以它其中的所有元素都符合给定的条件。)
indexOf和includes区别
indexOf不能匹配NaN这个值,includes可以- 当
indexOf()和includes()无参调用时,将匹配数组中的undefined
Array.prototype.{flat,flatMap}
let r;
r = ["1", ["8", ["9", ["1"]]]].flat();//4维数组,默认降维1,变成3维数组
console.log(r); //>> [ '1', '8', [ '9', ['1'] ] ]
r = ["1", ["8", ["9", ["1"]]]].flat(2); //4维数组,降维2,变成2维数组
console.log(r); //>> [ '1', '8', '9', ['1'] ]
r = ["1", ["8", ["9", ["1"]]]].flat(Infinity);//4维数组,最多变成1维数组
console.log(r); //>> [ '1', '8', '9', '1' ]
接着来看看flatMap()
let r;
r = ["I love", "coffe 1891"].map(item => item.split(" "));
console.log(r); //>> [ [ 'I', 'love' ], [ 'coffe', '1891' ] ]
r = ["I love", "coffe 1891"].flatMap(item => item.split(" "));
console.log(r); //>>[ 'I', 'love', 'coffe', '1891' ]
正则表达式
正则表达式命名捕获组
const reDate = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/,
match = reDate.exec("2018-08-06");
console.log(match);
//>> [2018-08-06, 08, 06, 2018, groups: {day: 06, month: 08, year: 2018}]
//此时用groups对象来获取年月日,无论正则表达式怎么变换,这下面三行不用改了,省事!
let year = match.groups.year; //>> 2018
let month = match.groups.month; //>> 08
let day = match.groups.day; //>> 06
可以提取指定结构中的内容
数据结构互转
arrayArray.from()
setnew Set()
map new Map()
objectObject.fromEntries()
for...in 和for...of
for...in不仅会遍历原型链上的属性,而且会遍历出其所有可枚举属性
for...of不会遍历原型链的属性,而且对于可迭代对象[Symbol(Symbol.iterator)](数组、类数组、Set、Map)不会遍历出额外的属性