function f(a) { return a}
f(1) // => 1
f.call(null, 1) // => 1
Function.prototype.call(f, null, 1) // => undefined
为什么最后一行返回undefined
,我认为它们是相同的。
答案 0 :(得分:2)
这些将是相同的:
function f(a) { return a}
console.log(f(1)); // => 1
console.log(f.call(null, 1)); // => 1
console.log(Function.prototype.call.call(f, null, 1)); // => 1
这是一个解释:
根据spec,Function.prototype.call
返回抽象操作 Call(func,thisArg,argList)。
因此,f.call(null, 1)
将返回抽象操作 Call(f,null,1)其中 f 是被调用的函数, null < / em>是调用它的上下文, 1 是传递给 f 的参数。这将为您提供所需的输出。
基于此,Function.prototype.call(f, null, 1)
将导致抽象操作调用(Function.prototype,f,null,1)其中 Function.prototype 是调用函数, f 是上下文, null 和 1 是传递给 Function.prototype 的参数。当然,这不会按预期工作。
但是,Function.prototype.call.call(f, null, 1)
将返回抽象调用操作 Call(Function.prototype.call,f,null,1),其中 Function.prototype.call 是要调用的函数, f 是调用它的上下文, null 和 1 作为参数传递。
那会是什么样子?
好吧,因为 f 是上下文而调用是用(null,1)调用的函数,所以最终结果是相同的致:f.call(null, 1)
。
答案 1 :(得分:2)
让我们从这开始:
function fn() { console.log(this); }
fn.a = function(){console.log(this)}
fn.a() // function fn() { console.log(this); }
因此,让我们深入挖掘并尝试实现假call
函数:
Function.prototype.fakeCall = function () {
// console.log(this)
// taking the arguments after the first one
let arr = Array.prototype.slice.call(arguments, 1);
// on the first run this will be Function.fakeCall but on the second pass it will be the first argument (the a function)
this.apply(arguments[0], arr);
}
function a(ar){ console.log(ar + this.name) };
let obj = {name : "thierry"};
// a.fakeCall( obj, 'hi ')
Function.fakeCall.fakeCall(a, obj, 'hi ');
因此,当我们这样做时:Function.prototype.fakeCall.fakeCall(a, obj, 'hi ')
首先,我们有:
arr = [ obj, 'hi ']
- 醇>
this = Function.fakeCall
所以我们最终得到Function.fakeCall.apply(a, [ obj, 'hi ']);
然后在第二轮比赛中我们
arr = ['hi']
- 醇>
this = a
因此我们最终得到的a.apply(obj, ['hi'])
与a.call(obj, 'hi');
但是,如果我们Function.fakeCall(a, obj, 'hi ');
在第一次运行时,我们将this = Function
,这将无法正常工作。在这种情况下它会抛出一个错误,在你的情况下它只返回undefined。这可以通过try-catch
轻松实现。
Function.prototype.fakeCall = function () {
let arr = Array.prototype.slice.call(arguments, 1);
try{
return this.apply(arguments[0], arr);
}catch(e){}
}
function a(ar){ return ar + this.name };
let obj = {name : "thierry"};
console.log(Function.fakeCall(a, obj, 'hi ')); // undefined
console.log(Function.fakeCall.fakeCall(a, obj, 'hi ')); // hi thierry