- JS的类型
- 常见值类型:boolean,symbol,string,number,undefined
- 引用类型:array,object,function,null
- typeof 运算符
- 识别所有值类型
- 识别函数
- 判断是否是引用类型(不可在细分)
-
==除了判断==null的时候其他都用===,其中if(obj == null)等价于if(obj === null || obj === undefined)null == undefined 结果为 true -
0,'',undefined,null,NAN,false为falsely值 ,falsely值是指!!即,两次取反,返回的值 -
Object.__proto__为null
6. instanceof (a instanceof Array)的实现原理其实就是判断a的__proto__是否指向了Array的prototype
- 闭包
- 函数作为返回值
function fn(){
const a = 100;
return function(){
console.log(a)
}
}
const fn1 = fn()
const a = 200
fn1()// 100
- 函数作为参数
function print(fn){
const a =100
fn()
}
const a = 200
function fn(){
console.log(a)
}
print(fn)//200
闭包是自由变量的查找,是在函数定义的地方,向上级作用域查找,不是在执行的地方查找
-
hasOwnProperty()方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性(也就是,是否有指定的键)。 -
call,apply,bind实现
- call
Function.prototype.mycall = function(obj){
//获取剩余元素
const args = [...arguments].slice(1)
obj.fn = this//this指向调用的fn1
console.log(this)
const newfn = obj.fn(...args)
delete obj.fn
return newfn
}
function fn1(a, b, c) {
console.log('this', this)
console.log(a, b, c)
return 'this is fn1'
}
fn1.call([1,2],3,4,5)
fn1.mycall([1,2],3,4,5)
- apply
Function.prototype.myapply = function(obj){
//获取剩余元素
const args = [...arguments].slice(1)
obj.fn = this
const newfn = obj.fn(...args[0])//相当于包这一个array
return newfn
}
function fn1(a, b, c) {
console.log('this', this)
console.log(a, b, c)
return 'this is fn1'
}
fn1.apply([1,2],[3,4,5])
fn1.myapply([1,2],[3,4,5])
- bind
Function.prototype.mybind = function(){
//获取剩余元素
const t = [...arguments].shift()
const args = [...arguments].slice(1)
self= this
return function (){
self.apply(t,args)
}
}
function fn1(a, b, c) {
console.log('this', this)
console.log(a, b, c)
return 'this is fn1'
}
const fn2 =fn1.bind([1,2],3,4,5)
fn2()
const fn3 =fn1.mybind([1,2],3,4,5)
fn3()
- 异步应用场景
- 网络请求,如ajax图片加载
- 定时任务,setTimeout promise的出现是为了解决callback hell (回调地狱) 问题
-
eventloop 异步:ajax和setTimeout都是使用了回调,基于event loop dom也是使用了回调,基于eventloop
-
promise 三个状态 pending resolved rejected pending状态不会触发then和catch
then和catch无论是哪个,只要是里面没有返回一个error都是resolved的promise
const p = Promise.resolve().then(()=>{console.log(1); throw Error('Err')})//rejected
p.catch(()=>{console.log(2)}) //resolved
.then(()=>{console.log(3)}) //resolved
const p = Promise.resolve().then(()=>{console.log(1); throw Error('Err')})//rejected
p.catch(()=>{console.log(2)}) //resloved
.catch(()=>{console.log(3)})
async 封装promise,执行async函数,return 一个promise对象,await相当于promise.then try...catch...可捕获异常,代替了promise的catch
!(async function fn1 (){
const p= Promise.reject('err')
const res = await p
console.log(res)
})()
!(async function fn1 (){
const p= Promise.resolve(100)
const res = await p
console.log(res)
})()
for.. of..(for in)和forEach不同,他是必须等一个回调结束才会调取下一个,也就是说2,4,6会1秒钟一个的出现
const arr =[1,2,3]
arr.forEach(async (i)=>{
const p = await add(i)
console.log(p)
})
------
function add(num){
return new Promise((resolve)=>{
setTimeout(()=>
resolve(num+num),1000)
})
}
const arr =[1,2,3]
!(async function fn1(){
for(let i of arr){
console.log(i)
const p = await add(i)
console.log(p)
}
})()
为什么
宏任务的执行时间比微任务要晚
是因为宏任务是在DOM渲染之后触发的,而微任务是在DOM渲染之前触发的
微任务是由ES6规定的,宏任务是由浏览器规定的