js手写call、apply、bind
程序员文章站
2022-07-14 14:28:22
...
三者异同
三者都用于改变this指向
- call:
func.call(thisArg, arg1, arg2, ...)
- 第一个参数作为this(func 的 this 指向 thisArg),后面的参数可以由很多个
- 返回函数执行结果
- func 会被调用
- apply:
func.call(thisArg, [arg1, arg2, ...])
- 第一个参数作为 this,后面只有一个数组参数
- 返回函数执行结果
- func 会被调用一次
- bind:
func.call(thisArg)
- 参数作为 this
- 返回一个函数
- func 不会被调用
手写call
// 保证所有函数都可以调用,所以得写到Function的原型上
Function.prototype.call2 = function (con) {
// 确保是函数在调用call方法
if (typeof this !== 'function') { // this指向调用call的函数
throw new TypeError('Error')
}
// con为null、undefined则赋值window,否则转化为对象类型
con = Object(con) || window // T1
const args = [...arguments].slice(1) // 从第二个参数开始存进args
// 给con添加属性fn
con.fn = this // T2
// 将args传入fn并执行它
const n = con.fn(...args) // T3
delete con.fn // 删掉fn属性
return n
}
- 关于T1
- 此处源码则写了一个类型处理的函数,根据不同类型做不同的包装。引用类型可以直接扩展属性,原始类型则得被相应的包装对象所代替(例:
Number(num)
)
- 此处源码则写了一个类型处理的函数,根据不同类型做不同的包装。引用类型可以直接扩展属性,原始类型则得被相应的包装对象所代替(例:
- 关于T2、T3步骤的解释
- 假设是 func.call(…),T1的 this 是 func 的,赋值给 con 的新属性 fn,然后再执行 con.fn,则fn的this指向了 con,则相当于 func 的 this 指向了 con
- 注意:虽然只写了 con 一个参数,但是传参时并不代表只能传一个,可以传任意多个甚至不传,因为参数都会传入一个数组,然后再被函数接收,所以数组里包含了什么并不重要
- 如果 this 不熟悉可以参考详解this
手写apply
- 实现apply只要修改传参方式即可,且相同注释不再粘贴
Function.prototype.apply2 = function (con) {
if (typeof this !== 'function') {
throw new TypeError('Error')
}
con = Object(con) || window
con.fn = this
let n
// 此处只对第二个参数起效,多余参数忽略
if (arguments[1]) {
// 假如传入了第二个参数,则将该参数传入fn并调用fn
n = con.fn(...arguments[1])
} else {
// 未传入第二个参数则不传参给fn
n = con.fn
}
delete con.fn
return n
}
手写bind
- bind 得返回一个新函数。注意:MDN中介绍到,当 bind 返回的函数被 new 时,忽略传入的 this 值
Function.prototype.bind2 = function (con) {
if (typeof this !== 'function') {
throw new TypeError('Error')
}
const args = [...arguments].slice(1)
const that = this // 牵涉到 “闭包”,得一次性定死this的值,指向调用函数
return function f () {
if (this instanceof f) { // T1
return new that(...args, ...arguments)
}
return that.apply(con, args.concat(...arguments))
}
}
- 关于T1
- 判断this是否是构造函数的实例(通过
new 函数名()
而来,或者说调用了 new 运算符),如果是则会创建了新对象,而 this 指向了新对象,所以得重新调用new that()
将this指回去(因为that是不变的) - instanceof 用于判断一个对象的原型链是否存在于一个构造函数的prototype属性上,即可以用来判断 this 是否通过 new 而来
- 判断this是否是构造函数的实例(通过
- 如果对 new 不了解,可以参考js的new操作符的详解和实现
- 如果对闭包不了解,可以参考js闭包详解
上一篇: JS手写call,apply,bind
下一篇: 数据结构——数组模拟实现队列
推荐阅读
-
javascript中apply、call和bind的使用区别
-
【THE LAST TIME】this:call、apply、bind
-
使用 js 简单的实现 bind、call 、aplly代码实例
-
Javascript中apply、call、bind的用法讲解
-
浅谈JavaScript中的apply/call/bind和this的使用
-
javascript中call,apply,bind函数用法示例
-
js中apply()和call()的区别与用法实例分析
-
apply、bind、call方法的作用与区别
-
apply,call,bind区别
-
JS 关于 bind ,call,apply 和arguments p8