Javascript 中的“this”关键字如何在对象字面量中起作用?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13441307/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How does the "this" keyword in Javascript act within an object literal?
提问by brownegg
I've seen How does "this" keyword work within a function?, but I don't see that it answers the following.
我已经看到“this”关键字如何在函数中工作?,但我没有看到它回答以下问题。
Given this code:
鉴于此代码:
var MyDate = function(date) {
this.date = date;
};
var obj1 = {
foo: new Date(),
bar: new MyDate(this.foo) // this.foo is undefined
};
var obj2 = {};
obj2.foo = new Date();
obj2.bar = new MyDate(this.foo); // this.foo is undefined
var obj3 = {
foo: new Date(),
bar: new MyDate(obj3.foo)
};
var obj4 = {};
obj4.foo = new Date();
obj4.bar = new MyDate(obj4.foo);
Why do the first two attempts fail, but the last two work? If this
isn't bound to the current object literal, what isit bound to?
为什么前两次尝试失败,但后两次成功?如果this
没有绑定到当前对象的文字,什么是它必然?
回答by slebetman
Javascript is a late binding language. In fact, it is very late binding. Not only is this
not bound during compile time, it is not even bound during runtime (as most other late binding languages do). In javascript, this
is bound during call time.
Javascript 是一种后期绑定语言。事实上,这是非常晚的绑定。不仅this
在编译时不受约束,甚至在运行时也不受约束(就像大多数其他后期绑定语言一样)。在 javascript 中,this
在调用时绑定。
The binding rules are quite different from most other OO languages which is why it seems to confuse a lot of people not familiar with javascript.
绑定规则与大多数其他 OO 语言有很大不同,这就是为什么它似乎让很多不熟悉 javascript 的人感到困惑。
Basically, how and where you use this
in the code does not affect how this
behaves (it does not matter if it's a standalone function, an object literal etc.) what determines the value of this
is how you call the function.
基本上,您this
在代码中使用的方式和位置不会影响this
行为方式(无论它是独立函数还是对象文字等都没有关系)。决定 值的this
是您如何调用函数。
The rules are:
规则是:
1- When a function is called as a constructor, a new object is created and this
is bound to that object. For example:
1- 当函数作为构造函数被调用时,会创建一个新对象并将this
其绑定到该对象。例如:
function Foo () {
this.bar = 1; // when called with the new keyword
// this refers to the object just created
}
new Foo().bar;
2- When called as an object method this
refers to the object the method belongs to. Basically the name before the last dot. For example:
2- 当作为对象调用时,方法this
是指该方法所属的对象。基本上是最后一个点之前的名称。例如:
foo.bar = 1;
foo.baz = function () {
alert(this.bar); // this refers to foo when called as foo.baz()
}
foo.baz();
3- If used outside of any function or if a function is not called as a method this
refers to the global object. The javascript spec doesn't give a name to the global object apart from saying that one exists but for browsers it is traditionally called window
. For example:
3- 如果在任何函数之外使用,或者如果一个函数没有被调用作为方法this
引用全局对象。javascript 规范除了说存在一个全局对象外,并没有为全局对象命名,但对于浏览器,它传统上称为window
. 例如:
bar = 1;
alert(this.bar); // this refers to the global object
foo = {
bar: this.bar // also global object
}
function foofoo () {
alert(this.bar); // also refers to the global object
}
foofoo();
4- In an event handler (such as onclick etc.) this
refers to the DOM element that triggered the event. Or for events not associated with the DOM like setTimeout
or XMLHTTPRequest
, this
refers to the global object. For example:
4- 在事件处理程序中(例如 onclick 等)this
是指触发事件的 DOM 元素。或者对于与 DOM 无关的事件,例如setTimeout
或XMLHTTPRequest
,this
指的是全局对象。例如:
foo.bar = 1;
foo.baz = function () {
alert(this.bar); // this would normally be foo but if this
// function is assigned to an event it would
// point to the element that triggered the event
}
somediv.bar = 2;
somediv.onclick = foo.baz; // clicking on somedive alerts 2 instead of 1
5- Finally, when a function is called using either the call()
or apply()
methods this
can be reassigned to anything whatsoever (google "mdn function.prototype.call"). In this way, any object in javascript can borrow/steal another objects' methods. For example:
5- 最后,当使用call()
或apply()
方法调用函数时,this
可以将其重新分配给任何东西(谷歌“mdn function.prototype.call”)。这样,javascript 中的任何对象都可以借用/窃取另一个对象的方法。例如:
cat = {
type: "cat",
explain: function () {
return "I am a " + this.type;
}
}
dog = {
type: "dog"
}
cat.explain.call(dog); // returns "I am a dog"
With Function.bind()
in modern javascript implementations we now have another rule:
随着Function.bind()
现代JavaScript实现我们现在有另一个规则:
6- Functions can also explicitly bind this
to an object using the bind()
method. The bind
method returns a new instance of the function where this
is bound to the argument passed to bind
. For example:
6- 函数还可以this
使用该bind()
方法显式绑定到对象。该bind
方法返回函数的一个新实例,其中this
绑定到传递给 的参数bind
。例如:
function explain () {
return "I am a " + this.type;
}
dog = {
type: "dog"
}
var dog_explain = explain.bind(dog);
dog_explain(); // returns "I am a dog"
ECMAscript 5 introduced strict mode which changes the meaning of this in functions that isn't called as a method or called with call or apply so we have to add a new rule:
ECMAscript 5 引入了严格模式,它改变了不是作为方法调用或通过 call 或 apply 调用的函数中 this 的含义,因此我们必须添加新规则:
7- When in strict mode, this
isn't allowed to refer to the global object (window in browsers). So when a function is not called as a method or this
isn't bound to anything manually via call
or apply
or bind
then this
becomes undefined
:
7- 在严格模式下,this
不允许引用全局对象(浏览器中的窗口)。因此,当函数未作为方法调用或未this
通过call
或手动绑定到任何内容时apply
,bind
则this
变为undefined
:
"use strict";
function foo () {
return this;
}
foo(); // returns undefined instead of the global object
ECMAscript 6 introduced arrow functions. Arrow functions change how this behaves by binding early.
ECMAscript 6 引入了箭头函数。箭头函数通过提前绑定来改变它的行为方式。
8- In arrow functions, this
is bound at the time the function is declared. So this
in the following code:
8- 在箭头函数中,this
在声明函数时绑定。所以this
在下面的代码中:
var x = () => {return this};
behaves as if the function is declared like the following code:
就像函数被声明为如下代码一样:
var x = function () {return this}.bind(this);
Note that since the this
in arrow functions are bound at the time the function is declared you can't use arrow functions if you want to use inheritance. That's because the this
in the function will alwayspoint to the parent object and will never point to the child object. That means that the only way to make inheritance work with arrow function is to override all arrow functions from the parent object.
请注意,由于this
in 箭头函数在声明函数时绑定,如果您想使用继承,则不能使用箭头函数。那是因为this
函数中的 将始终指向父对象,而永远不会指向子对象。这意味着使继承与箭头函数一起工作的唯一方法是覆盖父对象的所有箭头函数。
回答by Mark Reed
I think you may be missing a key difference between functions and object literals:
我认为您可能遗漏了函数和对象文字之间的一个关键区别:
The body of a function is not evaluated until the function is called.
在调用函数之前,不会评估函数的主体。
The body of an object literal is evaluated right away.
立即评估对象文字的主体。
When you define a function, this
isn't bound to anything related to the function you're defining. But by the time the function is called, it is bound to the object on which the function was called as a method.
当您定义一个函数时,this
不会绑定到与您定义的函数相关的任何内容。但是当函数被调用时,它被绑定到作为方法调用函数的对象。
回答by 0x499602D2
this.foo
is undefined because in all your examples, this
is referring to the global window
object. Also, even if you tried obj1.foo
, it will stillreturn undefined because the property hasn't been created until the entire expression is evaluated. Try this instead:
this.foo
未定义,因为在您的所有示例中,this
都指的是全局window
对象。此外,即使您尝试了obj1.foo
,它仍然会返回 undefined ,因为在评估整个表达式之前尚未创建该属性。试试这个:
var obj1 = {
foo: new Date(),
bar: function() {
return new MyDate( this.foo ); // will work
}
};
It works because by the time you call obj1.bar()
, the object will have been created by then; and because you're in a function, the this
object will reference the current object.
之所以有效,是因为在您调用 时obj1.bar()
,该对象将在那时创建;并且因为您在函数中,该this
对象将引用当前对象。
回答by lanzz
In Javascript, only function calls establish a new this
context. When you call foo.bar()
, within the bar
function, this
will be bound to foo
; when you call foo()
, inside it this
will be bound to window
. An object literal constructor is not a method call, so it does not affect this
in any way; it will still refer to whatever it was referring to outside of the object literal.
在 Javascript 中,只有函数调用才能建立新的this
上下文。当您调用 时foo.bar()
,在bar
函数内,this
将绑定到foo
; 当你调用的时候foo()
,里面this
会绑定到window
. 对象字面量构造函数不是方法调用,因此它不会this
以任何方式影响;它仍然会引用它在对象文字之外引用的任何内容。