wangyuan0108 / fe-qa

知识和笔记,整理分享,以便提升和巩固
https://github.com/wangyuan0108/blog/issues
13 stars 0 forks source link

模拟实现call方法 #89

Open wangyuan0108 opened 4 years ago

wangyuan0108 commented 4 years ago

思路: 1.将函数设为对象的属性 2.执行该函数 3.删除该函数

// 初实现
Function.prototype.myCall = function(context) {
    // 首先要获取调用call的函数,用this可以获取
    context.fn = this;
    context.fn();
    delete context.fn;
}

// 测试
var foo = {
    value: 1
};

function bar() {
    console.log(this.value);
}

bar.myCall(foo); // 1

是可以简单改变this的指向的

wangyuan0108 commented 4 years ago

上述实现未带参数,加参数实现

Function.prototype.myCall = 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;
}

// 测试一下
var foo = {
    value: 1
};

function bar(name, age) {
    console.log(name)
    console.log(age)
    console.log(this.value);
}

bar.myCall(foo, 'hello', 2); 
// hello
// 1
// 1
wangyuan0108 commented 4 years ago

最终代码实现

Function.prototype.mycall = function (context) {
    var context = context || window;
    context.fn = this;

    var args = [];
    for(var i = 1, len = arguments.length; i < len; i++) {
        args.push('arguments[' + i + ']');
    }

    var result = eval('context.fn(' + args +')');

    delete context.fn
    return result;
}

// 测试一下
var value = 2;

var obj = {
    value: 1
}

function bar(name, age) {
    console.log(this.value);
    return {
        value: this.value,
        name: name,
        age: age
    }
}

bar.myCall(null); // 2

console.log(bar.myCall(obj, 'hello', 2));
// 1
// Object {
//    value: 1,
//    name: 'hello',
//    age: 2
// }