Javascript中this对象详解

javascript this 基础 call apply

Redirected from https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/this

Introduction 导言

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

在大多数情况下,函数的调用方式决定了this的值。this不能在执行期间被赋值,在每次函数被调用时this的值也会不同。ES5增加了bind方法,可以在不对函数进行调用的情况下传入this值。

Global context 全局上下文

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

console.log(this.doucment === 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 函数上下文

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

Simple call 直接调用

function f1() {
        return this;
    }

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

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

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

f2() === undefined;  //return undefined

在严格模式下,this的值根据执行时的上下文,this所保存的值决定。若为定义,this仍是undefined, 它可能被设置为任何的值,比如null,42或者是 ” I’am not this “。

在第二个例子中,this的值应该是undefined。因为f2被调用时未基于任何对象(e.g.window.f2())。这个功能并未在所有第一次开始支持严格模式的浏览器中都得到广泛支持,在不支持的浏览器中,仍然返回window,比如chrome。

As an object method 作为对象方法

当一个函数作为一个对象的方法被调用,它的this会被设置为调用该方法的对象。
在下面的例子中,当o.f()被调用,function内部的this会绑定到这个object。

var o = {};
o.prop = 37;
o.f = function() {
    return this.prop;
    };
console.log(o.f()); //37

注意,如何调用或者在何处定义这个函数并不影响this的行为,在前一个例子中,我们在定义的object中为成员f添加了一个匿名函数,然而,我们能
更简便的先定义这些函数然后再将其附属到o.f上。这样做this的行为也是一致。

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

o.f = independent;

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

这个例子只有o对象中的f才会令这个函数被调用。

同样的,this绑定只会被最当前的引用所决定。在接下来的例子中,当我们调用这个function,把它当作o.b对象的g方法调用。在执行中,this会附属到o.b上。这个对象本身作为o的成员没有结果,其返回结果就是当前引用。
如下例:

o.b = {g: independent, prop:37}
console.log(o.b.g());    //返回37
…在原型链中

只要方法是定义在对象的原型链中上面的调用同样的仍然正确,如果方法在一个对象的原型链中,this对象指向调用这个方法的对象,就像这个方法存在于这个对象中一样。

var o = {
    f:function(){return this.a + this.b;}
}
var p = Object.create(o);
p.a = 1;
p.b = 5;
console.log(p.f());   //6

在此例中,p对象并没有它自己的实例f属性,它继承于原型链。但是没有关系f能在o对象中找到;查找以一个p.f的引用开始,因此这个function中的this取对象p的引用值。也就是说,当f函数作为p的对象被调用,它的this指向p。这是Javascript原型继承中非常有趣的特征。

…或者作为一个getter或者setter

当方法被getter或者setter调用同样的概念仍然成立,当对象的属性被set或者是gotten时,它的getter或者setter函数中的this对象会被绑定到当前对象。

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); //返回-7.86  1.414

As a Constructor作为构造器

当函数作为构造器(使用new关键词),它的this绑定为新构造的对象。
注意:当然默认的构造器返回的this对象为当前调用对象,它能被当前对象中return的新对象所取代(如果对象的返回值不是对象,那么this仍指向当前对象)。

/*注意中示例*/
var o = {
    a : 12,
    f : function(){
        return this.a;
    }
    };
var p = {
    a : 21,
    f : function(){
    return o.f();
    }
    };

console.log(p.f()); //返回12

构造器示例

/*
 * 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);   //返回37

 function C2(){
    this.a = 38;
    return {a:38};
}
o = new C2();
console.log(o.a);    //返回38

在上一个例子中(c2),因为有一个对象在构建中返回,所以this对象绑定到了返回的对象上。

call和apply

在function内部使用this关键词时,它的值可以在使用call或apply(所有的function对象都继承自Function.prototype)调用时绑定为该函数中传入的对象。

function add(c,d) {
    return this.a + this.b + c + d;
}
var o = {
    a : 2,
    b : 2
}
console.log(add.call(o,2,2)); //返回8

console.log(add.apply(o,[2,4])); //返回10

Bound functions 绑定函数

ECMAScript 5介绍 Function.prototype.bind.调用f.bind(someObject).创建一个新的function拥有相同的内容和作用域,比如f,但是this对象仍然出现在原来的function中,在新的function中他仍然永久的被绑定在第一个bind的参数(someObj)上,比如下面的g函数,无论这个function被调用了多少次。

function f(){
    return this.a;
}

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

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

As a DOM event handler 作为一个DOM事件处理程序

当一个function被用作为一个事件处理程序,它的this被设置为当前的元素(一些浏览器并不遵循这个规则而是动态的添加方法比如使用addEventListener)。

//当元素被调用,其被激活为蓝色
function bluify(e) {
    console.log(this === e.target);
    console.log(this === e.currentTarget);
    this.style.backgroundColor = "#A5D9F3";
}

//获得整个document的元素
var elements = document.getElementsByTagsName("*");

//当元素被点击时元素被调用
for(var i = 0; i < elements.length; i++) {
    elements[i].addEventListener('click',bluify,false);
}

In an in-line event handler 在行内的事件处理程序

当代码被行内事件处理程序调用,它的this就是当前元素:

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

以上警告为button。注意无论如何只有在存在外层代码才设置为这样:

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

在这个例子中,内部的function的this并未设置因此返回为window/global对象。

    原文作者:penouc
    原文地址: https://segmentfault.com/a/1190000000501212
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞