Javascript中的"this"关键字如何在对象文字中起作用?

bro*_*egg 45 javascript

我已经看到"this"关键字如何在函数中起作用?,但我不认为它回答了以下问题.

鉴于此代码:

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);
Run Code Online (Sandbox Code Playgroud)

为什么前两次尝试失败,但最后两次失败?如果this没有绑定到当前对象的文字,什么它必然?

sle*_*man 97

Javascript是一种后期绑定语言.事实上,这是非常晚的约束力.不仅this在编译期间没有绑定,它甚至在运行时也没有绑定(正如大多数其他后期绑定语言那样).在javascript中,this在通话时间内受到约束.

绑定规则与大多数其他OO语言完全不同,这就是为什么它似乎让很多不熟悉javascript的人感到困惑.

基本上,您this在代码中使用的方式和位置不会影响this行为(如果它是独立函数,对象文字等无关紧要)决定this调用函数的方式的价值.

规则是:

1 - 当函数作为构造函数调用时,将创建一个新对象并将this其绑定到该对象.例如:

function Foo () {
    this.bar = 1; // when called with the new keyword
                  // this refers to the object just created
}
new Foo().bar;
Run Code Online (Sandbox Code Playgroud)

2 - 当作为对象调用时,方法this指的是方法所属的对象.基本上是最后一个点之前的名字.例如:

foo.bar = 1;
foo.baz = function () {
    alert(this.bar); // this refers to foo when called as foo.baz()
}
foo.baz();
Run Code Online (Sandbox Code Playgroud)

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();
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

5 - 最后,当使用call()或者apply()方法调用函数时,this可以将其重新分配给任何东西(google"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"
Run Code Online (Sandbox Code Playgroud)

更新:

随着Function.bind()现代JavaScript实现我们现在有另一个规则:

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"
Run Code Online (Sandbox Code Playgroud)

更多更新:

ECMAscript 5引入了严格模式,该模式在未被调用为方法或通过调用或应用调用的函数中更改此含义,因此我们必须添加新规则:

7 - 在严格模式下,this不允许引用全局对象(浏览器中的窗口).因此,当一个函数将不会调用作为方法或this手动通过不绑定到任何东西callapplybindthis变为undefined:

"use strict";
function foo () {
    return this;
}
foo(); // returns undefined instead of the global object
Run Code Online (Sandbox Code Playgroud)

更多更新:

ECMAscript 6引入了箭头功能.箭头函数通过早期绑定来改变其行为方式.

8 - 在箭头函数中,this在声明函数时绑定.所以this在下面的代码中:

var x = () => {return this};
Run Code Online (Sandbox Code Playgroud)

表现得好像函数声明如下代码:

var x = function () {return this}.bind(this);
Run Code Online (Sandbox Code Playgroud)

请注意,由于this在声明函数时绑定了箭头函数,因此如果要使用继承,则不能使用箭头函数.那是因为this函数中的函数将始终指向父对象,并且永远不会指向子对象.这意味着使用箭头函数进行继承的唯一方法是覆盖父对象的所有箭头函数.

  • 修改后的答案,忘记了在函数之外使用`this`时的情况. (2认同)

Mar*_*eed 8

我想你可能会错过函数和对象文字之间的关键区别:

在调用函数之前,不会计算函数体.

立即评估对象文字的正文.

定义函数时,this不会绑定与您定义的函数相关的任何内容.但是在调用函数时,它被绑定到作为方法调用函数的对象.


lan*_*nzz 7

在Javascript中,只有函数调用才能建立新的this上下文.当你foo.bar()bar函数内调用时,this将被绑定foo; 当你打电话时foo(),里面this会受到约束window.对象文字构造函数不是方法调用,因此它不会this以任何方式影响; 它仍将引用它在对象文字之外引用的任何内容.


0x4*_*2D2 7

this.foo未定义,因为在所有示例中,this都是指全局window对象.此外,即使您尝试过obj1.foo,它仍将返回undefined,因为在评估整个表达式之前尚未创建该属性.试试这个:

var obj1 = {
    foo: new Date(),
    bar: function() {
        return new MyDate( this.foo ); // will work
    }
};
Run Code Online (Sandbox Code Playgroud)

它的工作原理是因为在您调用时obj1.bar(),该对象将在那时创建; 因为你在一个函数中,该this对象将引用当前对象.