js实现call

643 阅读1分钟

js实现call方法

用原生js实现call方法,实际上就是改变了this的指向。废话不多说直接看代码,代码中有注释。

//首先在函数Function的原型上定义mycall方法(有关原型的内容请自行了解)
Function.prototype.mycall = function (context) {
   // 获取传送进来的对象context
    var context = context || window
   // 为context定义一个属性fn方法,赋值为this,改变this指向,当前this指向
   // context,也就是指向传进来的对象或者下文的foo
   context.fn = this
   // 定义一个数组,获取传递进来的参数
   var args = []
   for (var i = 1, len = arguments.length; i < len; i++) {
       args.push('arguments[' + i + ']')
       // 重点:这块使用字符串拼接后并push进数组,
       // 当前args = ['arguments[0]','arguments[1]']
       // 重点来啦,这个时候肯定会有人问,为什么不直接push进数组呢?这是
       // 因为如果直接push进数组,则args =  ['jxd',18],而在当前的
       // 上下文中并没有定义变量jxd和18,所以就会报错。
   }
   // 因此这儿使用eval函数来执行,因为当执行函数作为函数参数的时候
   // eval会调用toString()方法,将['arguments[0]','arguments[1]']转为
   // 'arguments[0]','arguments[1]' 
   eval('context.fn(' + args +')
   // 执行完后删除fn属性,保持函数的清洁
   delete context.fn
  
}
var foo = {
    value:1
}
function bar(name,age) {
    console.log(name + '今年' + age)
}
// 调用
bar.call2(foo,'jxd',18) // jxd今年18

es6语法实现

Function.prototype.call2 = function (context) {
   var context = context || window
   context.fn = this
   var args = [...arguments].slice(1)
   // es6扩展符可以把数组转换为参数添加到函数中执行
   context.fn(...args)
   delete context.fn
}
var foo = {
    value:1
}
function bar(name,age) {
    console.log(name + '今年' + age)
}
bar.call2(foo,'jxd',18) // jxd今年18