原生js,call,apply,bind的区别以及实际应用场景是什么
js的this指向只有在运行时才能确定,一般都是.
前面的对象,但是有时候代码需要手动的改变this指向,会有两种情况
- 改变this指向,函数立即执行
- 改变this指向,函数稍后执行
立即执行可以使用 call、apply
稍后执行可以使用bind
call、apply的第一个参数都是函数调用的this指向,apply第二个参数是数组,call是一个一个传参
bind比较特殊,会返回一个绑定过this的绑定函数
- 调用bind的时候第一个参数是this,后面可以传多个参数
- 执行绑定函数的时候还可以继续传参,新传的参数会跟之前绑定的参数合并
- 绑定函数的返回值,与原先函数的返回值一样
- 绑定函数可以使用new声明实例对象,效果就跟new 之前的构造函数一样 不过绑定的this会失效
手写一个call
Function.prototype.mycall = function (context, ...args) {
context = context || window
const key = Symbol()
context[key] = this
const x = context[key](...args)
delete context[key]
return x
}
手写一个apply
Function.prototype.myapply = function (context, args) {
context = context || window
args = args || []
const key = Symbol()
context[key] = this
const x = context[key](...args)
delete context[key]
return x
}
手写一个bind
Function.prototype.mybind = function (context, ...args) {
context = context || window
const fn = this
const bindFn = function (...args2) {
const newArgs = [...args, ...args2]
if (new.target !== undefined) {
// 说明在new 绑定函数 忽略绑定的 context
context = this
}
const x = fn.apply(context, newArgs)
return x
}
/* 绑定函数使用new时 需要考虑原型链 使用寄生组合继承 */
let TempFn = function () {}
TempFn.prototype = fn.prototype
bindFn.prototype = new TempFn()
bindFn.prototype.constructor = fn
return bindFn
}
Math.max如何实现传入数组的形式去对比最大值
两种方式
- 使用扩展运算符
Math.max(...[1, 2, 3])
- 使用apply
Math.max.apply(null, [1, 2, 3])
promise为什么可以then,为什么可以实现链式调用,以及说一下如果自己封装promise的思路
promise是一个类,上面有个then
方法,每次执行.then
都会返回一个新的promise,所以可以链式调用。
js是单线程语言,为了避免阻塞主线程,js设计了异步函数,可以将大量的操作放在异步函数中执行,避免阻塞主线程。
但是处理复杂逻辑时,回调函数的嵌套层级过深时,会导致回调地狱,使得代码难以维护。
promise的出现就是为了解决这个问题。它有下面几个优势
- 解决了回调地狱问题
- 很方便处理代码错误:使用
.catch
- 提高了代码可读性可维护性
自己设计一个Promise 思路
Promise使用 new 所以设计成一个类
有三种状态 pending fulfilled rejected
实例属性 有 value reason status fulfilled_callback_list rejected_callback_list
resolve 干了两件事 设置value 更改状态为 fulfilled
reject 干了两件事 设置reason 更改状态为 rejected
status一改变 遍历回调数组 执行数组里收集的方法
then 方法
接收两个回调参数 onFulfilled onRejected
返回的一个新的 Promise
是微任务 讲 onFulfilled onRejected 两个函数使用queueMicrotask函数包裹下
判断当前状态 状态为pending时,将 onFulfilled onRejected 保存到等待执行数组
状态为fulfilled时,执行onFulfilled 回调
状态为rejected时,执行 onRejected 回调
链式调用then方法的返回值会传递给下一个Promise中,创建解析函数 递归解析then的返回值
resolvePromise(promise2, x, resolve, reject)
promise2是上一个then创建的新的Promise
x是上一个then方法的返回值
resolve reject 是新Promise的resolve和reject
如果 x 是 Promise,执行 x.then 继续递归解析
如果 x 是 null,直接返回
如果 x 是 对象 或者方法 看看有没有 then方法 有的话 执行then方法 然后继续递归解析返回值
既不是Promise也不是对象或者方法,其他情况就是普通值,resolve(x)
中间有报错 直接reject(r)
说一下判断数据类型的方法都有哪些
typeof
number boolean string undefined bitint symbol object function
Object.prototype.toString.call()
[object Function]
[object Array]
[object String]
...Array.isArray()
instanceof