判断数据类型
- typeof 判断除 null 以外的基础类型
- instanceof 判断引用类型
- Object.prototype.toaString.call()判断所有类型 instanceof 原理
function instanceof(L, O) {
L = L.__proto__;
O = O.prototype;
while(true){
if(L===null)return false;
if(L===O){
return true;}
else{
L=L.__proto__
}
}
apply, call, bind 区别
三者都是用来改变 this 的指向,this 被指定为传入函数的第一个参数。 bind 是返回新的函数以便稍后调用,call、apply 是立即调用函数。 call: 第二个参数是参数列表。 apply: 第二个参数是一个数组或类数组的对象。
事件循环
Javascript是单线程,基于事件循环
js事件分为同步任务和异步任务,遇到异步任务分类为宏任务(macro-task)和微任务(micro-task)。
- 宏任务:包括整体代码script,setTimeout,setInterval
- 微任务:Promise.then,process.nextTick(node中)
事件的执行过程: 1、遇到同步任务,进入调用栈,立即执行 2、遇到异步任务,异步任务有了结果后,宏任务和微任务分别进入不同的事件队列 3、同步任务执行完后,先检查微任务队列,进入调用栈执行 4、微任务队列清空后,执行宏任务队列,依次进入调用栈执行
// 这是一个同步任务
console.log('1') --------> 直接被执行
目前打印结果为:1
// 这是一个宏任务
setTimeout(function () { --------> 整体的setTimeout被放进宏任务列表
console.log('2') 目前宏任务列表记为【s2】
});
new Promise(function (resolve) {
// 这里是同步任务
console.log('3'); --------> 直接被执行
resolve(); 目前打印结果为:1、3
// then是一个微任务
}).then(function () { --------> 整体的then[包含里面的setTimeout]被放进微任务列表
console.log('4') 目前微任务列表记为【t45】
setTimeout(function () {
console.log('5')
});
});
浏览器瞅了一眼微任务列表 发现里面有微任务 就开始全部执行
then(function () {
console.log('4') --------> 直接被执行
目前打印结果为:1、3、4
setTimeout(function () { --------> 被放进宏任务列表了
console.log('5') 目前宏任务列表记为【s2、s5】
});
});
浏览器发现微任务执行完毕了
开始执行宏任务列表
setTimeout(function () {
console.log('2') --------> 直接被执行
目前打印结果为:1、3、4、2
});
setTimeout(function () {
console.log('5') --------> 直接被执行
目前打印顺序为: 1、3、4、2、5、5
});
最终结果为: 1、3、4、2、5
Promise
1、promise是一个容器,保存某个异步操作的结果,这个结果决定promise当前是什么状态,promise有三种状态,pending,fulfilled,rejected,并且只有两种可能,pending=>fulfilled,pending=>rejected
2、promise通过then方法给异步操作结果添加事件回调,有两种情况,
一是先获得了异步操作结果,后添加事件回调,会立即执行 二是先添加了回调,会保存在一个回调数组里面,等异步操作结果返回了执行
问题1
有一个非常长的链式调用, 怎么让它在某一个函数中停下来,为什么可以这样做
let promise = new Promise(function(resolve, reject){
resolve('第一次成功')
})
promise.then(function(val) {
//第一种方法
throw new error()
// 第二种方法
return Promise.reject()
}).then(function(val) {
console.log('被跳过的方法')
}).catch(function(val) {
console.log('返回失败')
})