function foo(){
console.log('foo', this);
}
foo();
foo.call({ bar: 1 });
foo.apply([{ bar: 1 }]);
有没有办法知道使用普通调用或foo()
调用call/apply
?
答案 0 :(得分:3)
没有。您无法检测是否从call/apply
或正常调用函数。
他们不是神奇的存在,他们所做的只是设置参数和this
值。对于未定义/未声明的值,有subtle difference,但就是这样。
返回调用func的[[Call]]内部方法的结果,将thisArg作为此值,将argList作为参数列表。
它正确设置了内部caller
属性,因此像this这样天真的东西不起作用。
答案 1 :(得分:2)
除非你重新定义Function.prototype.call
和Function.prototype.apply
(并将另一个参数传递给你的函数),否则无法这样做 - 实际的内部机制([[Call]]
内部函数)做不提供使用()
调用它的任何信令方法。
比较general function call和Function.prototype.apply
的规范 - 每个都以完全相同的方式调用函数的内部代码,并且没有外部属性集可以提供给你是否是使用或不使用。
请参阅内部函数[[Call]]
的规范:
13.2.1
[[Call]]
当使用此值和参数列表调用Function对象F的
[[Call]]
内部方法时,将执行以下步骤:
- 让funcCtx成为使用F的[[FormalParameters]]内部属性的值,传递的参数List args以及10.4.3中描述的该值为函数代码建立新执行上下文的结果。
- 让结果为评估作为F [[Code]]内部属性值的FunctionBody的结果。如果F没有[[Code]]内部属性或者其值为空FunctionBody,则结果为(normal,undefined,empty)。
- 退出执行上下文funcCtx,恢复先前的执行上下文。
- 如果result.type是throw,则抛出result.value。
- 如果result.type为return,则返回result.value。
- 否则result.type必须正常。返回undefined。
醇>
没有规定更改函数的运行是否使用call
/ apply
调用它 - 唯一改变它的功能的是函数本身的参数和什么是this
意味着在函数内。
答案 2 :(得分:1)
我希望这能解决你的问题:
function foo(){
console.log('foo', this);
if (typeof this.length === "number") {
//function has been apply
} else {
//function has been call
}
}
foo();
foo.call({ bar: 1 });
foo.apply([{ bar: 1 }]);
答案 3 :(得分:1)
尝试这样的事情:
function foo(){
console.log('foo', this);
console.log( arguments );
}
Function.prototype._apply = Function.prototype.apply;
Function.prototype.apply = function(ths,args){
args.unshift('apply');
this._apply(ths,args);
};
foo();
foo.call(this, { bar: 1 });
foo.apply(this, [{ bar: 1 }]);
答案 4 :(得分:1)
肮脏,肮脏的黑客:
function foo() {
var isNatural = !/foo\.(call|apply)/.test("" + foo.caller)
console.log(isNatural ? "foo()" : "foo.{call,apply}()")
}
function caller1() {
foo()
}
function caller2() {
foo.call(null, { bar: 1 })
}
function caller3() {
foo.apply(null, [{ bar: 1 }])
}
caller1()
caller2()
caller3()
这只是思考的问题。不要在生产中使用它。
答案 5 :(得分:-1)
我想不出你应该检查这个的原因但是,你可以通过比较this === window
进行检查,因为这是默认范围(假设基于浏览器的Javascript),但这可以通过简单地调用来伪造foo就像这样foo.call(window)
,这基本上就是调用foo()
正常做的事情。
对于属于其他对象或原型的函数,这也可能无法使用window
。