在使用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对象调用?
非常感谢
答案 0 :(得分:3)
另外,我不完全确定为什么要调用第一个'console.log'?
nick.name = function(){
// ...
}();
在这里定义一个函数,立即调用它(因此()
)并将其返回值({init: init}
)分配给nick.name
所以执行是:
nick
的变量
helloA
的变量console.log
输出数据,this
(window
因为函数在全局上下文中而不是作为方法执行),并且{ {1}}(this.helloA
,不存在。window.helloA
init
nick.name
,nick.name.init()
在init
的上下文中执行name
功能。helloB
console.logs
带有“2”(按原样),this
(name
)和this.helloB
(nick.name.helloB
- 不存在)因此,您获得的第一个输出来自console.log('1.',this, this.helloA);
我认为你的主要问题是你混淆了this.foo
(调用方法的对象的属性)和变量范围(函数可用的变量)
答案 1 :(得分:2)
this
在进行函数调用时基于每个函数定义。当您将函数调用为o.f()
时,this
将在函数内o
,当您将其称为f()
时,this
将成为全局对象(对于浏览器,这是窗口)。
您撰写了nick.name = function(){...}();
,右侧部分的格式为f()
,因此Window
。
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
属性(不存在)。