Call、Bind、Apply重写

1
2
3
4
5
6
7
8
9
10
11
const name = "window"
const person = {
name: 'CNY',
say(age, sex) {
console.log(this.name, age, sex);
}
}

let Person2 = {
name: 'CY'
}

call

1
2
3
4
5
6
7
8
9
Function.prototype.MyCall = function (target, ...args) {
console.log('target: ', target, ...args);
target = target || window
const symbolKey = Symbol()
target[symbolKey] = this
const res = target[symbolKey](...args) //args 本身是rest参数
delete target[symbolKey]
return res
}

apply

1
2
3
4
5
6
7
8
Function.prototype.MyApply = function (target, ...args) {
target = target || window
const symbolKey = Symbol()
target[symbolKey] = this
const res = target[symbolKey](...args) //args 本身是数组
delete target[symbolKey]
return res
}

bind

1
2
3
4
5
6
7
8
9
10
Function.prototype.MyBind = function (target, ...outArgs) {
target = target || {} //处理边界条件
const symbolKey = Symbol()
target[symbolKey] = this
return function (...innerArgs) {
const res = target[symbolKey](...outArgs, ...innerArgs)
// delete target[symbolKey] //不应销毁,存在多次调用情况
return res
}
}

与原生bind执行期上下文一致写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Function.prototype.binder = function (context) {
var _self = this
var args = Array.prototype.slice.call(arguments, 1)
var tempFn = function () { }

var fn = function () {
var newArgs = Array.prototype.slice.call(arguments)
_self.apply(this instanceof _self ? this : context, args.concat(newArgs))
}

tempFn.prototype = this.prototype
fn.prototype = new tempFn()

return fn
}