手写call,bind,apply方法

116 阅读1分钟

call:

   Function.prototype.myCall = function(context, ...args) {
      // 判断是否是undefined和null
      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) {
// 判断是否是undefined和null
    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) {
  // 判断是否是undefined和null
  if (typeof context === 'undefined' || context === null) {
    context = window
  }
  let fnSymbol = Symbol()
  context[fnSymbol] = this
  let fn = context[fnSymbol] (...args)
  return fn
}
思路和call是一样的只是传参不同方式而已