还是对JavaScript''这个'感到困惑

时间:2010-04-28 11:09:01

标签: javascript

在使用JavaScript对象时,我一直在阅读关于'this'关键字的相当多的文章,我仍然有些困惑。我很乐意编写面向对象的Javascript,我通过引用完整的对象路径来解决'this'问题,但我不喜欢我仍然觉得'这'令人困惑的事实。

我找到了一个很好的答案here,这对我很有帮助,但我仍然不能100%肯定。所以,举个例子。以下脚本从test.html与<script src="js/test.js"></script>

链接
if (!nick) {
    var nick = {};
}

nick.name= function(){
    var helloA = 'Hello A';
    console.log('1.',this, this.helloA);

    var init = function(){
        var helloB = 'Hello B';
        console.log('2.',this, this.helloB);
    }

    return {
        init: init
    }
}();

nick.name.init();

期待看到的是什么

1. Object {} nick.name, 'Hello A'
2. Object {} init, 'Hello B'

但我得到的是这个吗?

1. Window test.html, undefined
2. Object {} init, undefined

我想我理解那里发生的一些事情,但我会介意那里有人向我解释。

另外,我不完全确定为什么第一个'console.log'被调用?如果我删除了对init函数//nick.name.init()的调用,则firebug仍会输出1. Window test.html, undefined。这是为什么?当html页面加载时,为什么nick.name()会被window对象调用?

非常感谢

4 个答案:

答案 0 :(得分:3)

  

另外,我不完全确定为什么要调用第一个'console.log'?

nick.name = function(){
    // ...
}();

在这里定义一个函数,立即调用它(因此())并将其返回值({init: init})分配给nick.name

所以执行是:

  1. 如果没有非假名值的变量
  2. ,则创建一个名为nick的变量
  3. 创建一个匿名函数......
  4. 在自己的范围内创建一个名为helloA的变量
  5. 使用包含“1”(原样)的console.log输出数据,thiswindow因为函数在全局上下文中而不是作为方法执行),并且{ {1}}(this.helloA,不存在。
  6. 定义名为window.helloA
  7. 的函数
  8. 返回分配给init
  9. 的对象
  10. 然后致电nick.namenick.name.init()init的上下文中执行name功能。
  11. 这定义了helloB
  12. 然后console.logs带有“2”(按原样),thisname)和this.helloBnick.name.helloB - 不存在)
  13. 因此,您获得的第一个输出来自console.log('1.',this, this.helloA);

    我认为你的主要问题是你混淆了this.foo(调用方法的对象的属性)和变量范围(函数可用的变量)

答案 1 :(得分:2)

  1. this在进行函数调用时基于每个函数定义。当您将函数调用为o.f()时,this将在函数内o,当您将其称为f()时,this将成为全局对象(对于浏览器,这是窗口)。 您撰写了nick.name = function(){...}();,右侧部分的格式为f(),因此Window

  2. var foo = bar;定义了一个局部变量。它可能不会被this.foo访问(好吧,除非你处于全球范围,但这很愚蠢)。要定义成员,通常要改为this.foo = bar;

答案 2 :(得分:2)

如果将this视为一个函数而不是变量,那就简单多了。本质上,this是一个返回当前“执行上下文”的函数,即当前函数被“应用”的对象。例如,请考虑以下

function t() { console.log(this)}

根据您的称呼方式,这将返回截然不同的结果

t() // print window

bar = { func: t }
bar.func() // print bar

foo = { x: 123 }
t.apply(foo) // print foo

答案 3 :(得分:1)

这就是您的代码所做的事情:

  • 它创建一个对象并分配给变量nick
  • 它创建了一个匿名函数。
  • 调用该函数(在窗口范围内)。
  • 它将返回值(包含init属性的对象)分配给对象的name属性。
  • 它从init属性中获取值,该属性是方法委托,并调用该方法。

匿名函数执行此操作:

  • 它声明了一个名为helloA的局部变量,并为其指定一个字符串。 (创建局部变量不会将其作为属性添加到当前对象。)
  • 它记录this(窗口)和helloA属性(不存在)。
  • 它创建一个匿名函数并分配给局部变量init
  • 它创建一个具有属性init的对象和来自局部变量init的值。

分配给init属性的匿名函数执行此操作:

  • 它声明了一个名为helloB的局部变量,并为其指定一个字符串。 (创建局部变量不会将其作为属性添加到当前对象。)
  • 它记录this(来自name属性的对象,而不是nick变量)和helloB属性(不存在)。