我正在开发灵活的JavaScript小部件。在一些测试过程中,我注意到this
的上下文根据用于调用函数的括号是放在对象内还是放在调用的全局上下文中而发生变化。为什么括号很重要?为什么对象内的括号引用窗口,当放置在全局上下文中时引用该对象。看起来好像是另一种方式。
在两个实例中都返回undefined
。有没有办法在不返回任何内容的情况下执行该函数?
我觉得我遗漏了一些关于this
的重要内容,不想错过。
//this refers to window
var dataSource = {
read: read()
};
function read(){
console.log(this);
}
dataSource.read;
//this refers to dataSource object
var dataSource = {
read: read
};
function read(){
console.log(this);
}
dataSource.read();
答案 0 :(得分:3)
您的代码正在做两件事。
第一个例子是在执行对象定义时执行read()
(read()
可用,因为它是一个函数声明并且被挂起,尽管这与您遇到的问题无关) 。它在没有任何上下文的情况下被调用,因此它的this
是window
(根据规范,其中window
是浏览器的全局对象)。
第二个示例引用了read()
,然后在块的末尾执行。因为它作为dataSource
的属性执行,所以this
将成为this
。但是,如果您首先将该引用分配给其他地方,然后通过该引用调用它,那么您将再次失去该this
上下文。
要对bind()
进行细粒度控制,请查看call()
,apply()
和undefined
。
在两个实例中都返回
undefined
。有没有办法在不返回任何内容的情况下执行该函数?
函数总是有一个返回值({{1}},如果没有明确设置),但你可以自由地忽略它。
答案 1 :(得分:2)
this
的范围可能是javascript中一个棘手的主题。也就是说,如果需要,我可以扩展关于this
范围的一般规则的答案。
但要回答您的具体问题,无论何时在对象文字中引用this
,默认情况下都会引用对象文字本身。
编辑:只要该函数被调用为对象文字的属性。
除非在使用this
或apply()
调用所述函数时指定,否则几乎在任何其他情况下我都会想到call()
将引用窗口对象。
答案 2 :(得分:0)
在对象之外使用this
时,它引用浏览器环境中window
的全局对象。否则它引用调用中最后一个点之前的最后一个裸字。
例如:
function foo () {return this};
var bin = {bar:{foo:foo},foo:foo};
foo(); // returns window
bin.foo(); // returns bin
bin.bar.foo(); // returns bar
// ^
// |
// '------ last bareword before the last dot in the invocation
现在,至于为什么括号的位置很重要。我想你现在应该可以猜到:
当我们为一个单词(变量/名称/引用)添加一个括号时,我们正在做的是进行函数调用:
foo(); // call foo
如果我们不添加括号,我们正在做的是引用对象:
foo; // this contains the function foo
请注意,不添加parens不会调用该函数。因此,当您这样做时,显而易见:
var bar = { foofoo : foo() }
您正在做的是将函数foo
的结果传递给bar.foofoo
。调用该函数时,其调用路径中没有任何“点”。因此,它不属于任何对象,因此this == window
的规则适用。
另一方面,如果你这样做:
var bar = { foo : foo }
您正在做的是将功能foo
分配给bar.foo
。以后将其称为:
bar.foo()
调用包含一个“点”,因此关于最后一个点之前的最后一个对象的规则适用。
有关this
在javascript中的工作原理的详细解释,请参阅我之前对相关问题的回答:How does the "this" keyword in Javascript act within an object literal?