call:
Function.prototype.myCall = function(context, ...args) {
if (typeof context === 'undefined' || context === null) {
context = window
}
let fnSymbol = Symbol()
context[fnSymbol] = this
let fn = context[fnSymbol] (...args)
delete context[fnSymbol]
return fn
}
核心思路是:
1.为传入的context扩展一个属性,将原函数指向这个属性
2.将context之外的所有参数全部传递给这个新属性,并将运行结果返回。
一些细节:
1.利用rest 参数(…args)可以存储函数多余的参数
2.为传入的context扩展参数扩展新属性使用了Symbol()数据类型,这样确保不会影响到传入的context,因为Symbol值一定是独一无二的。
3.用扩展运算符(…)将原来是数组的args转发为逗号分隔一个个参数传入到函数中
为什么能找到this.name呢?因为context[fnSymbol]中的this指向的是context。
手写bind方法
Function.prototype.myBind = function(context) {
if (typeof context === "undefined" || context === null) {
context = window;
}
self = this;
return function(...args) {
return self.apply(context, args);
}
}
手写apply方法
Function.prototype.myApply = function(context, args) {
if (typeof context === 'undefined' || context === null) {
context = window
}
let fnSymbol = Symbol()
context[fnSymbol] = this
let fn = context[fnSymbol] (...args)
return fn
}
思路和call是一样的只是传参不同方式而已