Javascript 中的this介绍

在javascript中的构造函数创建对象时,常常使用this,但是this到底是什么,其实有一遍英文的文章 介绍的很详细:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
这里我把它翻译出来,自己也深刻的理解和体会一下。原文翻译如下:

Javascript中this关键字的行为与其他的语言表现的非常不一样 (比如说C++的this指针一般都是指向当前对象的),而且在严格模式和非严格模式上也还不一样。

在大多数的情况下,this的值是由函数如何调用来决定的,其不能再执行的过程中赋值,而且可能在同一个函数执行的过程中也不一样。ES5中介绍了bind的方法来设置this的值。

了解具体的this指针,分为下面两种情况

Global context (全局环境)

在全局的执行环境中(函数外),不论是严格模式还是非严格模式,this 表示的全局对象, 实例代码如下:

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

// 在浏览器中,window object就是一个全局的对象
console.log(this === window); // true

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

Function context (函数环境)

在函数环境中,this代表的值取决于函数是如何被调用的。

  • 简单函数调用
function f1(){
  return this;
}

f1() === window; // 全局对象

在严格模式下,this的值默认为undefined,this是在进入执行环境中被设置的,其可以被设置成任何值,如null,或者42,等。

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

f2() === undefined;
  • 作为对象方法
    当函数作为对象方法被调用时,this就被设置成调用方法的对象。在下面的例子中,当o.f()调用时,this是绑定到o对象上的。
var o = {
  prop: 37,
  f: function() {
    return this.prop;
  }
};

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

值得注意的是,this的值不会受函数在哪里定义影响,在上面的例子中,函数f是在定义o的时候内联进去的,我们还可以在稍后给制定,如下的代码,执行也是一样的。

var o = {prop: 37};

function independent() {
  return this.prop;
}

o.f = independent;

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

这也验证了this仅仅取决于f函数是作为对象o的成员函数调用的。
还有,this仅仅取决于最后离调用函数最近的类,在下面的例子中,函数中的this是o.b对象

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

1) this在对象原型链
如果方法是在对象的原型链上,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

在上面的例子中,p对象没有f属性,其是从原型中继承过来的,但是这不妨碍this被赋值成p对象,并且在f函数中用this对象查看a与b。

2) this 在get和set属性方法中
在get和set方法中依然用相同的表现。

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
  • 构造函数
    当函数作为构造函数(用this关键字),this就是新创建的对象。
    注意:虽然this默认是构造函数的返回的对象,但是,其可以被修改成其他的对象(当返回值不是object)具体的例子代码如下:
/*
 * 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上增加属性,方法等。 
 *   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).
     // 如何函数有return语句返回一个对象,这个对象就是new 表达式
     // 的值,否则,其返回的就是绑定了this指针的object
 * }
 */

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

在C2的例子中,因为有一个新对象返回,这个this绑定的新的object其实是被丢球了没有用。其实导致this.a = 37是一段code执行了,但是没有任何效果。
在执行了

  • call and apply (call函数和apply函数)
    当使用call和apply执行的时候,this就是调用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
// this代表的这个对象就是o.
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
// this代表的这个对象就是o.
add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34

注意的是,如果call和apply的第一个参数不是一个对象,其也会调用toObject方法来调用这个对象。如下面的例子,会将7先转成Number对象。

function bar() {
  console.log(Object.prototype.toString.call(this));
}

bar.call(7); // [object Number]
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
  • DOM 事件回调函数
    当函数被用作时间回调是,其this就是发送时间的对象。例如下面的代码:
// When called as a listener, turns the related element blue
function bluify(e){
  // Always true
  console.log(this === e.currentTarget); 
  // true when currentTarget and target are the same object
  console.log(this === e.target);
  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
for(var i=0 ; i<elements.length ; i++){
  elements[i].addEventListener('click', bluify, false);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值