一、手写call
-
先来看下call的使用
let obj = { name: 'obj' } var name = 'window' function f(lastname) { console.log(this.name + ' ' + lastname) } f.call(obj, 'sun')
// 输出obj sun
-
思考:能直接通过函数.调用,通过我们学到的原型链的知识,我们可以将callFun写到prototype上
Function.prototype.callFun = function(obj, ...args) {
}
-
思考:现在关键的部分是怎么能让callFun中执行function f中的代码,然后让this优先寻找obj中的值,那么还是结合之前学的原型链的知识,将方法f赋给obj的原型,然后执行obj原型的这个方法,这样this优先寻找obj的属性,找不到才会像上一级找
Function.prototype.callFun = function(obj, ...args) { obj.proto._fn = this let result = obj._fn(args) delete obj.proto._fn return result }
-
测试
f.callFun(obj, 'sun') // obj sun
二、手写apply
-
先来看下apply的使用
let obj = { name: 'obj' } var name = 'window' function f(lastname) { console.log(this.name + ' ' + lastname) } f.apply(obj, ['dong'])
// 输出obj dong
-
思考:能直接通过函数.调用,通过我们学到的原型链的知识,我们可以将applyFun写到prototype上
Function.prototype.applyFun = function(obj, args) {
}
-
思考:理解了call的写法就能很快反应到apply的写法,只需要理解ES6的结构赋值即可
Function.prototype.applyFun = function(obj, args) { obj.proto._fn = this let result = obj._fn(args) delete obj.proto._fn return result }
-
测试
f.applyFun(obj, ['dong']) // obj dong
三、手写bind
-
先来看下bind的使用
let obj = { name: 'obj' } var name = 'window' function f(lastname) { console.log(this.name + ' ' + lastname) } f.bind(obj, 'mei')()
// 输出obj mei
-
思考:看到上面调用的方式我们就可以指定bind返回的一定一个函数
Function.prototype.bindFun = function(obj, ...args) { let result = function () {
} return result }
-
思考:函数中执行的一定也是函数f的方法,那我们可以模仿call和apply
Function.prototype.bindFun = function(obj, ...args) { obj.proto._fn = this let result = function () { return obj._fn(args) } return result }
-
测试
f.bindFun(obj, 'mei')() // obj mei