js call和apply的实现吧

115 阅读1分钟

今日学习啥呢。。 学习实现call吧; 反正没事干。。记录一波 ##call call怎么使用相信大家一定不陌生了。看一下概念:call() 方法在使用一个指定的 this 值和若干个指定的参数值的前提下调用某个函数或方法。

举个栗子:

var foo = {
    value: 1
};
function bar() {
    console.log(this.value);
}
bar.call(foo); // 1

基本效果:

  • call 改变了this的方向,指向了foo
  • bar函数依旧正常执行了

我们如果实现它,大概思路是什么呢;我们先看下下面的代码;

var foo = {
    value: 1,
    bar: function() {
        console.log(this.value)
    }
};
foo.bar(); // 1

当我们调用call的时候。代码执行方式和上面是一样的。大概 思路就是foo对象本身添加了bar的属性。然后this就自动指向了foo对象; 但是总是给对象添加一个新的属性。是 有点不太合适。but我们可以用js的 delete属性删除掉; 看下主要逻辑:

  • 1.将函数设为对象的属性
  • 2.执行传入的函数
  • 3.删除对象上的属性 ##模拟实现第一版
// 第一版
Function.prototype.call2 = function(context) {
    // 首先要获取调用call的函数,用this可以获取
    context.fn = this;
    context.fn();
    delete context.fn;
}
// 测试一下
var foo = {
    value: 1
};
function bar() {
    console.log(this.value);
}
bar.call2(foo); // 1

基本的功能实现了。但是我们通常函数还可以传入参数;比如下面的例子;

//测试代码
var foo = {
    value: 1
};
function bar(name, age) {
    console.log(name)
    console.log(age)
    console.log(this.value);
}
bar.call(foo, 'kevin', 18);

继续实现吧; ##代码第二版(函数支持传入参数) 对于参数实现思路。可以通过Arguments里面取出来。从第二位取到最后然后在放入参数;直接看代码吧

//第二版
Function.prototype.call2 = function(context) {
    context.fn = this;
    var args = [];
    for(var i = 1, len = arguments.length; i < len; i++) {
        args.push('arguments[' + i + ']');
    }
   eval('context.fn(' + args +')');
    delete context.fn;
}