首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >做了一个小小的javascript实验,需要你的帮助来理解意想不到的结果

做了一个小小的javascript实验,需要你的帮助来理解意想不到的结果
EN

Stack Overflow用户
提问于 2013-12-16 04:15:30
回答 2查看 124关注 0票数 0

我在浏览器的控制台做了一个JavaScript实验-

首先,我创建了一个新对象foo,如下所示

代码语言:javascript
复制
  var foo = {
    bar: function() { return this.baz; },
    baz: 1
  };

现在,当我在控制台中再次运行以下代码时,它将返回"number"

代码语言:javascript
复制
  (function(){
    return typeof foo.bar();
  })();

但是,当我运行以下匿名函数时,它返回"undefined"

代码语言:javascript
复制
  (function(){
    return typeof arguments[0]();
  })(foo.bar);

据我所知,在上面的函数中,arguments[0]返回foo.bar (下面的例子也证明了),那么为什么上面的代码返回"undefined"而不是"number"

当我跑的时候

代码语言:javascript
复制
      (function(){
        return arguments[0];
      })(foo.bar);

返回function () { return this.baz; }

也是

代码语言:javascript
复制
  (function(){
    return typeof arguments[0];
  })(foo.bar());

返回"number"为什么不

代码语言:javascript
复制
  (function(){
    return typeof arguments[0]();
  })(foo.bar);

还是一样的?在JavaScript中有什么基本定律在这里起作用吗?

EN

回答 2

Stack Overflow用户

发布于 2013-12-16 04:19:52

this取决于如何调用函数。当使用点表示法时,JavaScript将this的上下文设置为接收方。在您的示例中,没有接收方,而是对函数的引用,因此您丢失了上下文。您必须显式传递它:

代码语言:javascript
复制
arguments[0].call(foo);

arguments[0]是与foo.bar相同的函数对象,但是this的值是动态的。在foo.bar()中,this被分配给foo,因为您使用了foo. (点符号)。但是在arguments[0]()中没有点(没有接收者),所以this是默认值,也就是window

这是相同的函数,但调用不同。

票数 2
EN

Stack Overflow用户

发布于 2013-12-16 04:30:37

详细阐述艾尔克罗的回答。

foo.bar是一种方法,是关于如何做某事的指导。在面向对象的编程语言中,唯一可以使用该指令的对象是foo或与foo相关的对象;但是在JavaScript中,任何人都可以尝试运行它,如果代码要求的话。

在第二个匿名函数中,您将获得一个要运行的方法,运行它,并返回结果的类型。但是,运行这个函数的不是foo;它是匿名的,所以window是运行它的对象。window运行foo,它试图返回this.baz;然而,window没有baz,这就是为什么没有定义的原因。

要进一步测试它,请尝试设置window.baz并查看您是否得到了正确的结果,还尝试了elclanrs关于使用call()方法来确保从foo的作用域调用它的建议。

编辑

没错,arguments[0]foo.bar的类型是相同的;它们都是“函数”。我认为,对于JavaScript将函数作为头等对象的处理,存在混淆之处。

如果您熟悉像Java或C++这样的面向对象语言,那么当您调用bar时,它总是被具有baz属性的foo调用;然而,在JavaScript中并非如此。任何函数都可以被任何对象调用,这意味着结果可能有意义,也可能没有意义。

正如埃克尼尔斯所说,这两者之间的区别在于.。假设我创建了自己的对象phew = {baz: 44}。我可以有效地从foo中“偷”一种方法:phew.myMethod = foo.bar。现在,phew知道bar中包含的指令,如果我调用phew.myMethod(),我的结果将是44,因为phew正在调用该方法,而phewbaz是44;在哪里定义该方法并不重要!重要的是该方法要做什么,而bar要求返回调用它的人的baz

现在,回到您的代码,您正在调用arguments[0]()。看起来应该是一样的,但是因为函数是一流的对象,所以当您将它作为参数传递时,您真正传递的只是一个名为bar的函数。当您调用arguments[0]()时,它就像调用bar()一样,这与调用foo.bar()不同,就像调用phew.myMethod()一样,尽管它们都是完全相同的函数

有关更多信息,请访问this SO post

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20603381

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档