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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 18:47:31  来源:igfitidea点击:

How does the "this" keyword in Javascript act within an object literal?

javascript

提问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 thisisn'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 thisnot bound during compile time, it is not even bound during runtime (as most other late binding languages do). In javascript, thisis 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 thisin the code does not affect how thisbehaves (it does not matter if it's a standalone function, an object literal etc.) what determines the value of thisis 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 thisis 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 thisrefers 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 thisrefers 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.) thisrefers to the DOM element that triggered the event. Or for events not associated with the DOM like setTimeoutor XMLHTTPRequest, thisrefers to the global object. For example:

4- 在事件处理程序中(例如 onclick 等)this是指触发事件的 DOM 元素。或者对于与 DOM 无关的事件,例如setTimeoutXMLHTTPRequestthis指的是全局对象。例如:

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 thiscan 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 thisto an object using the bind()method. The bindmethod returns a new instance of the function where thisis 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, thisisn't allowed to refer to the global object (window in browsers). So when a function is not called as a method or thisisn't bound to anything manually via callor applyor bindthen thisbecomes undefined:

7- 在严格模式下,this不允许引用全局对象(浏览器中的窗口)。因此,当函数未作为方法调用或未this通过call或手动绑定到任何内容时applybindthis变为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, thisis bound at the time the function is declared. So thisin 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 thisin 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 thisin 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.

请注意,由于thisin 箭头函数在声明函数时绑定,如果您想使用继承,则不能使用箭头函数。那是因为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, thisisn'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.foois undefined because in all your examples, thisis referring to the global windowobject. 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 thisobject will reference the current object.

之所以有效,是因为在您调用 时obj1.bar(),该对象将在那时创建;并且因为您在函数中,该this对象将引用当前对象。

回答by lanzz

In Javascript, only function calls establish a new thiscontext. When you call foo.bar(), within the barfunction, thiswill be bound to foo; when you call foo(), inside it thiswill be bound to window. An object literal constructor is not a method call, so it does not affect thisin 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以任何方式影响;它仍然会引用它在对象文字之外引用的任何内容。