Kampfer的记事本

新blog:www.kampfer-lw.com

导航

关于this

Posted on 2010-08-05 11:23  Kamfper  阅读(215)  评论(0编辑  收藏  举报

      最近看了篇关于this和上下文环境的文章,觉得自己也有必要总结一下。 

       首先说明什么是上下文环境。JavaScript中的this关键字通常都会指向当前函数的拥有者,在JavaScript中通常把这个拥有者叫做执行上下文,函数的执行上下文由当前的执行环境来决定。另外就是要区别上下文环境和作用域:上下文环境是在执行时确定的,是可能改变的,而作用域是在定义时确定的,是不会变的。

      再来说明的就是this在运行环境下到底是如何来确定上下文的:

      在http://www.cnblogs.com/zhangle/archive/2010/07/01/1769435.html这篇bolg中,博主归纳了4点:

  • 如果当前执行的是一个对象的方法,则执行上下文就是这个方法所属的对象
  • 如果当前是一个创建一个对象的过程,则执行上下文就是这个正在被创建的对象
  • 如果一个方法在执行时没有明确的指定附属的对像,则这个方法的上下文是全局对象
  • 使用call和apply可以改变对象的执行上下文 

 

     与之相类似的我在《JavaScript语言精粹》4.3 调用 这一小节里也看到了作者Douglas Crockford关于this和上下文的更加专业的总结。书中Douglas说道:调用一个函数时,函数除了接收声明时定义的形式参数,还要接收两个附加的参数:this和arguments。而this的取值就取决于调用的模式。调用模式有四种,每种在初始化this关键字上是存在差异的。我惊奇的发现Douglas的这四种调用模式与上面提到的那位博主归纳的是极其相似的。这四种模式是:

  • 方法调用模式:当一个对象的方法被调用时,this将会被绑定到这个对象上。
  • 函数调用模式:当一个函数并非是一个对象的属性,那么它被调用时将会是这种调用模式。这时this被绑定到全局变量上。
  • 构造器调用模式:当一个函数前面加上new来调用时,将创建一个新的对象,这个对象将会被添加到函数prototype的后面,并且函数里的this会被绑定到新的对象实例上。
  • apply调用模式:它能改变this关键字的上下文。 

 接着我们通过代码来了解这四种调用模式:

 代码一:

//这是通过方法调用模式来调用函数,this被绑定到拥有该方法的对象上

//this.value就是对象myObject的属性value的值 

var myObject = {

    value:0,

    increment:function(inc){

        this.value+=typeof inc==="number"?inc:1;

    } 

};

myObject.increment(1);

alert(myObject.value);  //1 

myObject.increment(2);

alert(myObject.value);  //3 

 代码二:

//这是通过构造器调用模式。即在函数前面加上了关键字 new

var Quo function(string){
    
this.status string;

};

Quo.prototype.get_status=function{

    return this.status; 

};

//由于this是在运行时确定的,所以在此句this才初始化,由于函数前面有new,所以this被绑定到了myQuo对象上 

var myQuo = new Quo("confused");

alert(myQuo.get_status());     //confused

 代码三:

//这是函数调用模式,this直接被绑定到了全局对象上
var Quo = function(string){
    
this.status = string;
};
Quo(
"hi")
alert(Quo.status);     //undefined
alert(status);         //hi

 引用Douglas的说法,这是“语言设计上的一个错误”。这个错误导致对象方法的内部函数无法访问此对象的属性与方法,这很不好。但是有解决的办法。

代码四:

代码
//接代码一
//
解决办法:用that传递
myObject.double = function () {
    
var that=this;      //  这是关键
    var helper = function () {
        that.value 
= add (that.value,that.value);
    };
    help();
};
myObject.
double();
alert(myObkect.getValue());    
// 6

 关于apply和call就无需多言了……