KFCVme50-CrazyThursday / sheng-study

个人学习总结与代码知识点
1 stars 0 forks source link

4、call/apply #4

Open KFCVme50-CrazyThursday opened 4 years ago

KFCVme50-CrazyThursday commented 4 years ago

mdn 中对 call 的描述是: call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。

注意:该方法的语法和作用与 apply() 方法类似,只有一个区别,就是 call() 方法接受的是一个参数列表,而 apply() 方法接受的是一个包含多个参数的数组。
KFCVme50-CrazyThursday commented 4 years ago

用例1:

var foo = {
    value: 111
}
function fun() {
    console.log(this.value)
}

fun() // undefined
fun.call(foo) // 111

call 主要做了一下事情:

针对以上事情,当调用 call 的时候,把 foo 对象改造成如下::

var foo = {
    value: 111,
    fun: function() {
        console.log(this.value)
    }
}
foo.fun()

这个时候给foo对象添加了一个属性,使用delete删除即可。 因此,call 的过程为一下几步:

以上例子就是:

// first
foo.fn = fun
// second
foo.fn()
// third
delete foo.fn

根据这个思路,call的模拟实现即是以下过程:

Function.prototype.call1 = function(ctx) {
    // 获取调用call的函数,用this可以获取
    ctx.fn = this
    ctx.fn()
    delete ctx.fn()
}
KFCVme50-CrazyThursday commented 4 years ago

接上

还存在以下特殊点:

Function.prototype.call2 = function (ctx) {
    var ctx = ctx || window;
    ctx.fn = this;
    var args = [];
    for(var i = 1, len = arguments.length; i < len; i++) {
        args.push('arguments[' + i + ']');
    }
    var result = eval('ctx.fn(' + args +')');
    delete context.fn
    return result;
}

// 这里使用es6语法的话会精简一点:
Function.prototype.call3 = function (ctx, ...args) {
    var ctx = ctx || window;
    ctx.fn = this;
    var result = eval('ctx.fn(...args)');
    delete context.fn
    return result;
}
KFCVme50-CrazyThursday commented 4 years ago

apply与call原理类似,主要传入参数形式不同。当使用es6展开运算符时候,两者基本一致。上面es6版的call3也即为apply的实现