Call 的原理 MDN

修改函数的this指向 会立即执行函数

Call 的手写实现

1
2
3
4
5
6
7
8
Function.prototype.MyCall = function (target) {
var self = target || window
self.fn = this
var args = [].slice.call(arguments, 1)
const result = self.fn(...args)
delete self.fn
return result
}

Apply 的原理 MDN

修改函数的this指向 会立即执行函数 第二个参数是一个数组 会自动展开到真是执行的函数中

Apply 的手写实现

1
2
3
4
5
6
7
8
9
10
Function.prototype.MyApply = function (target, arr) {
var self = target || window
self.fn = this

var args = arr || []

const result = self.fn(...args)
delete self.fn
return result
}

Bind 的原理 MDN

修改函数的this指向,不会立即执行函数 返回值是一个函数 真是传入函数的参数从 第二位开始

Bind 的手写实现

最小的实现 没有解决 bind 方法绑定后 调用传参的问题

1
2
3
4
5
6
7
8
Function.prototype.MyBind1 = function (target) {
var self = this
var args = [].slice.call(arguments, 1)
var f = function () {
return self.apply(target || window, args)
}
return f
}

加强版 解决的调用传参的问题 但是还有函数指针指向的问题

1
2
3
4
5
6
7
8
9
Function.prototype.MyBind2 = function (target) {
var self = this
var args = [].slice.call(arguments, 1)
var f = function () {
var _arg = [].slice.call(arguments, 0)
return self.apply(target || window, args.concat(_arg))
}
return f
}

终极版

1
2
3
4
5
6
7
8
9
10
11
12
Function.prototype.MyBind3 = function (target) {
var self = this
var args = [].slice.call(arguments, 1)
var temp = function () { }
var f = function () {
var _arg = [].slice.call(arguments, 0)
return self.apply(this instanceof temp ? this : (target || window), args.concat(_arg))
}
temp.prototype = self.prototype
f.prototype = new temp()
return f
}

参考文档

1号传送门
2号传送门
3号传送门