我在浏览器的控制台中进行了一次JavaScript实验 -
首先,我创建了一个新的对象foo,如下所示
var foo = {
bar: function() { return this.baz; },
baz: 1
};
现在,当我在控制台中再次运行以下代码时,它会返回"number"
(function(){
return typeof foo.bar();
})();
但是当我按照匿名函数运行时,它会返回"undefined"
(function(){
return typeof arguments[0]();
})(foo.bar);
据我所知arguments[0]
,上面的函数返回foo.bar
(以下示例也证明了),为什么上面的代码会返回"undefined"
而不是"number"
?< / p>
当我跑步时
(function(){
return arguments[0];
})(foo.bar);
返回function () { return this.baz; }
另外
(function(){
return typeof arguments[0];
})(foo.bar());
返回"number"
,然后返回
(function(){
return typeof arguments[0]();
})(foo.bar);
返回相同的? JavaScript中有没有基本法在这里工作?
答案 0 :(得分:2)
this
取决于您调用该函数的如何。使用点表示法时,JavaScript会将this
的上下文设置为接收者。在你的情况下,没有接收器,但是对函数的引用,所以你丢失了上下文。你必须明确地传递它:
arguments[0].call(foo);
arguments[0]
与foo.bar
的功能对象相同,但this
的值是动态的。在foo.bar()
中,this
被分配到foo
,因为您使用了foo.
(点表示法)。但在arguments[0]()
中没有点(没有接收者),因此this
是默认值,或window
。
它的功能相同但调用不同。
答案 1 :(得分:1)
对elclanrs&#39;的详细说明答案。
foo.bar
是一种方法;如何做某事的指示。在面向对象的编程语言中,唯一可以使用该指令的对象是foo
或与foo
相关的对象;但是在JavaScript中,如果代码要求,任何人都可以尝试运行它。
在第二个匿名函数中,您将获得一个运行,运行它并返回结果类型的方法。但是,它不是运行此功能的foo
;它是匿名的,因此window
是运行它的对象。 window
运行foo
,尝试返回this.baz
;但是,window
没有baz
,这就是您未定义的原因。
要进一步测试,请尝试设置window.baz
并查看您是否获得了正确的结果,并尝试使用elclanrs&#39;建议使用call()
方法确保从foo
范围调用它。
修改强>
你是对的,arguments[0]
和foo.bar
的类型是相同的;他们都是&#34;功能&#34;。我认为混淆是因为JavaScript将函数视为一流对象。
如果您熟悉面向对象的语言(如Java或C ++),那么当您致电bar
时,您会发现foo
始终会调用它。有一个baz
属性;但是,JavaScript的情况并非如此。任何函数都可以被任何对象调用,这意味着结果可能有意义。
正如elclanrs所说,两者之间的区别在于.
。我们说我做了自己的对象phew = {baz: 44}
。我可以,有效地,&#34;窃取&#34; foo
这样的方法:phew.myMethod = foo.bar
。现在,phew
知道bar
中包含的说明,如果我调用phew.myMethod()
,我会得到44作为结果,因为phew
正在调用方法,而{{1} } phew
是44; 方法的定义并不重要!重要的是该方法要做什么,而baz
表示返回任何调用它的人bar
。
现在,回到您的代码,您正在调用baz
。看起来它应该是相同的,但因为函数是第一类对象,当你将它作为参数传递时,你真正传递的只是一个名为arguments[0]()
的函数。当您拨打bar
时,就像拨打arguments[0]()
一样,这与呼叫bar()
不同,就像调用foo.bar()
,一样它们都是完全相同的功能。
有关详细信息,请尝试this SO post
答案 2 :(得分:1)
让我简化问题......
var foo = {
bar: function() { return this.baz; },
baz: 1
};
var ref = foo.bar;
console.log(typeof ref()); // undefined
console.log(typeof foo.bar()); // number
这是因为函数对象'bar'中的'this'并不总是引用'foo'。它会改变你的称呼方式。如果你从一个不是foo的对象中调用它,它将显示undefined。请注意,ref不是foo而是foo.bar。
现在,如果将foo更改为以下内容,则会在两种情况下都给出“数字”输出...
var foo = {
bar: function() { return foo.baz; },
baz: 1
};
请注意
console.log(ref === foo.bar); // true
但是foo.bar()不等于ref()(在第一种情况下),因为当你调用foo.bar()时,javascript引擎将foo作为'this'传递,但是当你调用ref()时它是最初的窗口.ref(),它将窗口对象(或非浏览器环境中的其他全局对象)传递为'this'