mozilla

this

这篇翻译不完整。请帮忙从英语翻译这篇文章

Introduction 导言

A function's this keyword behaves a little differently in JavaScript compared to other languages. It also has some differences between strict mode and non-strict mode.

JavaScript函数中的this关键字的行为相比起其他语言有很多不同。在JavaScript的严格和非严格模式下也略有区别。

In most cases, the value of this is determined by how a function is called. It can't be set by assignment during execution, and it can be different each time the function is called. ES5 introduced the bind method to set the value of a function's this regardless of how it's called.

在绝大多数情况下,函数的调用方式决定了this的值。this不能在执行期间被赋值,在每次函数被调用时this的值也可能会不同。ES5引入了bind方法来设置函数的this值,而不用考虑函数如何被调用的。

Global context   全局上下文

In the global execution context (outside of any function), this refers to the global object, whether in strict mode or not.

在全局运行上下文中(在任何函数体外部),this 指代全局对象,无论是否在严格模式下。

console.log(this.document === document); // true

// In web browsers, the window object is also the global object:
console.log(this === window); // true

this.a = 37;
console.log(window.a); // 37

Function context 函数上下文

Inside a function, the value of this depends on how the function is called.

在函数内部,this的值取决于函数是如何调用的。

Simple call 直接调用

function f1(){
  return this;
}

f1() === window; // global object

In this case, the value of this is not set by the call. Since the code is not in strict mode, the value of this must always be an object so it defaults to the global object.

在这个例子中,this的值不是由函数调用设定。因为代码不运行在严格模式下,this的值总是一个对象且默认为全局对象。

function f2(){
  "use strict"; // see strict mode
  return this;
}

f2() === undefined;

In strict mode, the value of this remains at whatever it's set to when entering the execution context. If it's not defined, it remains undefined. It can also be set to any value, such as null or 42 or "I am not this".

在严格模式下,this的值根据运行时的上下文,this所保存的值决定。若没有定义,this将是undefined。同时它也能设置成任意值,比如null或者42或者“I am not this”。

Note: In the second example, this should be undefined, because f2 was called without providing any base (e.g. window.f2()). This feature wasn't implemented in some browsers when they first started to support strict mode. As a result, they incorrectly returned the window object.
在第二个例子中,this应该是undefined。因为f2被调用时未基于任何对象(e.g. window.f2( ))。这个功能并未在所有第一次开始支持严格模式的浏览器中都得到了广泛支持。因此有些浏览器返回了错误的结果 :window 对象。

As an object method 作为对象方法

When a function is called as a method of an object, its this is set to the object the method is called on.

In the following example, when o.f() is invoked, inside the function this is bound to the o object.

函数以对象里的方法的方式进行调用时,它们的this由调用该函数的对象进行设置。

下面的例子中,当o.f()被调用时,函数内的this即为o对象。

var o = {
  prop: 37,
  f: function() {
    return this.prop;
  }
};

console.log(o.f()); // logs 37

Note that this behavior is not at all affected by how or where the function was defined. In the previous example, we defined the function inline as the f member during the definition of o.  However, we could have just as easily defined the function first and later attached it to o.f. Doing so results in the same behavior:

注意,在何处或者如何定义调用函数完全不会影响到this的行为。在上一个例子中,我们在定义o的时候为其成员f定义了一个匿名函数。但是,我们也可以首先定义函数然后再将其附属到o.f。这样做this的行为也一致。

var o = {prop: 37};

function independent() {
  return this.prop;
}

o.f = independent;

console.log(o.f()); // logs 37

This demonstrates that it matters only that the function was invoked from the f member of o.

这说明this的值只与从对象o中调用的f函数有关系。

Similarly, the this binding is only affected by the most immediate member reference. In the following example, when we invoke the function, we call it as a method g of the object o.b. This time during execution, this inside the function will refer to o.b. The fact that the object is itself a member of o has no consequence; the most immediate reference is all that matters.

类似的,this的绑定只受最靠近的成员引用的影响。在下面的这个例子中,我们以对象o中的b对象中的g方法来调用independent方法。在这次执行期间,函数中的this将指向o.b。事实上,这与对象本身的成员没有多大关系,最靠近的引用才是最重要的。

在这个例子中

o.b = {g: independent, prop: 42};
console.log(o.b.g()); // logs 42

... on the prototype chain 原型链中的this

The same notion holds true for methods defined somewhere on the object's prototype chain. If the method is on an object's prototype chain, this refers to the object the method was called on, as if the method was on the object.

相同的概念在定义在原型链中的方法也是一致的。如果该方法存在于一个对象的原型链上,那么this指向的是调用这个方法的对象,表现得好像是这个方法就存在于这个对象上一样。

var o = {f:function(){ return this.a + this.b; }};
var p = Object.create(o);
p.a = 1;
p.b = 4;

console.log(p.f()); // 5

In this example, the object assigned to the variable p doesn't have its own f property, it inherits it from its prototype. But it doesn't matter that the lookup for f eventually finds a member with that name on o; the lookup began as a reference to p.f, so this inside the function takes the value of the object referred to as p. That is, since f is called as a method of p, its this refers to p. This is an interesting feature of JavaScript's prototype inheritance.

在这个例子中,对象p没有属于它自己的f属性,它的f属性继承自它的原型。但是这对于最终在o中找到f属性的查找过程来说没有关系;查找过程首先从p.f的引用开始,所以函数中的this指向p。也就是说,因为f是作为p的方法调用的,所以它的this指向了p。这是JavaScript的原型继承中的一个有趣的特性。

... or as a getter or setter

Again, the same notion holds true when a function is invoked from a getter or a setter. A function used as getter or setter has its this bound to the object from which the property is being set or gotten.

function modulus(){
  return Math.sqrt(this.re * this.re + this.im * this.im);
}

var o = {
  re: 1,
  im: -1,
  get phase(){
    return Math.atan2(this.im, this.re);
  }
};

Object.defineProperty(o, 'modulus', {get: modulus, enumerable:true, configurable:true});

console.log(o.phase, o.modulus); // logs -0.78 1.4142

As a constructor 构造函数中的this

When a function is used as a constructor (with the new keyword), its this is bound to new object being constructed.

当一个函数被作为一个构造函数来使用(使用new关键字),它的this与即将被创建的新对象绑定。

Note: while the default for a constructor is to return the object referenced by this, it can instead return some other object (if the return value  isn't an object, then the this object is returned).

注意:当构造器返回的默认值是一个this引用的对象时,可以手动设置返回其他的对象,如果返回值不是一个对象,返回this。

/*
 * Constructors work like this:
 *
 * function MyConstructor(){
 *   // Actual function body code goes here.  Create properties on |this| as
 *   // desired by assigning to them.  E.g.,
 *   this.fum = "nom";
 *   // et cetera...
 *
 *   // If the function has a return statement that returns an object, that
 *   // object will be the result of the |new| expression.  Otherwise, the
 *   // result of the expression is the object currently bound to |this|
 *   // (i.e., the common case most usually seen).
 * }
 */

function C(){
  this.a = 37;
}

var o = new C();
console.log(o.a); // logs 37


function C2(){
  this.a = 37;
  return {a:38};
}

o = new C2();
console.log(o.a); // logs 38

In the last example (C2), because an object was returned during construction, the new object that this was bound to simply gets discarded. (This essentially makes the statement "this.a = 37;" dead code. It's not exactly dead, because it gets executed, but it can be eliminated with no outside effects.)

在最后的例子中(C2),因为在调用构造函数的过程总,手动的设置了返回对象,与this绑定的默认对象被取消(本质上这使得语句“this.a = 37”成了“僵尸”代码,实际上并不是真正的“僵尸”,这条语句执行了但是对于外部没有任何影响可以忽略它)。

call and apply

Where a function uses the this keyword in its body, its value can be bound to a particular object in the call using the call or apply methods that all functions inherit from Function.prototype.

当一个函数的函数体中使用了this关键字时,通过所有函数都从Function对象的原型中继承的call()方法和apply()方法调用时,它的值可以绑定到一个指定的对象上。

function add(c, d){
  return this.a + this.b + c + d;
}

var o = {a:1, b:3};

// The first parameter is the object to use as 'this', subsequent parameters are passed as 
// arguments in the function call
add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16

// The first parameter is the object to use as 'this', the second is an array whose
// members are used as the arguments in the function call
add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34

Bound functions 绑定函数

ECMAScript 5 introduced Function.prototype.bind. Calling f.bind(someObject) creates a new function with the same body and scope as f, but where this occurs in the original function, in the new function it is permanently bound to the first argument of bind, regardless of how the function is being used.

ECMAScript 5 引入了 Function.prototype.bind。调用f.bind(someObject)会创建一个与f具有相同函数体和作用域的函数,但是在这个新函数中,this将永久地被绑定到了bind的第一个参数,无论这个函数是如何被调用的。

function f(){
  return this.a;
}

var g = f.bind({a:"azerty"});
console.log(g()); // azerty

var o = {a:37, f:f, g:g};
console.log(o.f(), o.g()); // 37, azerty

As a DOM event handler 作为DOM事件处理函数

When a function is used as an event handler, its this is set to the element the event fired from (some browsers do not follow this convention for listeners added dynamically with methods other than addEventListener).

当函数被用作事件处理函数时,它的this指向触发事件的元素(一些浏览器在动态添加监听器时不遵守这个约定,除非使用addEventListener 这句不太确定翻译的是否正确)。

// When called as a listener, turns the related element blue
// 被调用时,将关联的元素变成蓝色
function bluify(e){
  console.log(this === e.currentTarget); // Always true
  console.log(this === e.target);        // true when currentTarget and target are the same object
  this.style.backgroundColor = '#A5D9F3';
}

// Get a list of every element in the document
// 获取文档中的所有元素的列表
var elements = document.getElementsByTagName('*');

// Add bluify as a click listener so when the element is clicked on,
// it turns blue
// 将bluify作为元素的点击监听函数,当元素被点击时,就会变成蓝色
for(var i=0 ; i<elements.length ; i++){
  elements[i].addEventListener('click', bluify, false);
}

In an in–line event handler 作为内联事件处理函数

When code is called from an in–line handler, its this is set to the DOM element on which the listener is placed:

当代码被内联处理函数调用时,它的this指向监听器所在的DOM元素。
 

<button onclick="alert(this.tagName.toLowerCase());">Show this</button>

The above alert shows button. Note however that only the outer code has its this set this way:

上面的alert会显示button。注意只有外层代码中的this是这样设置的:

<button onclick="alert((function(){return this}}()));">Show inner this</button>

In this case, the inner function's this isn't set so it returns the global/window object (i.e. the default object in non–strict mode where this isn't set by the call).

在这种情况下,内部函数的this没有设置,所以它指向global/window对象(即非严格模式下this没有被call设置时指向的默认对象)。

文档标签和贡献者

向此页面作出贡献: teoli, zhanglun, DaoG, JinZheng, jaka, haodut, floraLam
最后编辑者: floraLam,
隐藏侧边栏