做了一点javascript实验,需要你的帮助才能理解意外的结果

时间:2013-12-16 04:15:31

标签: javascript anonymous-function javascript-objects

我在浏览器的控制台中进行了一次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中有没有基本法在这里工作?

3 个答案:

答案 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'