您的位置:首页 > Web前端 > JavaScript

js基础1-深入理解javascript之this

2015-06-27 10:08 871 查看
感谢出处:http://blog.csdn.net/mevicky/article/details/46659273

备份下:

深入理解javascript之this

2015-06-27 10:08
2706人阅读 评论(0)收藏举报


分类:

javascript(44)


版权声明:本文为博主原创文章,未经博主允许不得转载。

目录(?)[+]

javascript中的this含义非常丰富,它可以是全局对象,当前对象或者是任意对象,这都取决于函数的调用方式。函数有以下几种调用方式:作为对象方法调用、作为函数调用、作为构造函数调用、apply或call调用。

 

对象方法调用

 

作为对象方法调用的时候,this会被绑定到该对象。

[html]
view plain
copy

var point = {   
 x : 0,   
 y : 0,   
 moveTo : function(x, y) {   
     t
4000
his.x = this.x + x;   
     this.y = this.y + y;   
     }   
 };   
  
 point.moveTo(1, 1)//this 绑定到当前对象,即 point 对象  

[html]
view plain
copy

  

这里我想强调一点内容,就是this是在函数执行的时候去获取对应的值,而不是函数定义时。即使是对象方法调用,如果该方法的函数属性以函数名的形式传入别的作用域,也会改变this的指向。我举一个例子:

[html]
view plain
copy

var a = {  
    aa : 0,  
    bb : 0,  
    fun : function(x,y){  
        this.aa = this.aa + x;  
        this.bb = this.bb + y;  
    }  
};  
var aa = 1;  
var b = {  
    aa:0,  
    bb:0,  
    fun : function(){return this.aa;}  
}     
a.fun(3,2);  
document.write(a.aa);//3,this指向对象本身  
document.write(b.fun());//0,this指向对象本身  
(function(aa){//注意传入的是函数,而不是函数执行的结果  
    var c = aa();  
    document.write(c);//1 , 由于fun在该处执行,导致this不再指向对象本身,而是这里的window  
})(b.fun);    

这样就明白了吧。这是一个容易混淆的地方。

函数调用

函数也可以直接被调用,这个时候this被绑定到了全局对象。

[html]
view plain
copy

var x = 1;  
 function test(){  
   this.x = 0;  
 }  
 test();  
 alert(x); //0  

但这样就会出现一些问题,就是在函数内部定义的函数,其this也会指向全局,而和我们希望的恰恰相反。代码如下:

[html]
view plain
copy

var point = {   
 x : 0,   
 y : 0,   
 moveTo : function(x, y) {   
     // 内部函数  
     var moveX = function(x) {   
     this.x = x;//this 绑定到了全局  
    };   
    // 内部函数  
    var moveY = function(y) {   
    this.y = y;//this 绑定到了全局  
    };   
  
    moveX(x);   
    moveY(y);   
    }   
 };   
 point.moveTo(1, 1);   
 point.x; //==>0   
 point.y; //==>0   
 x; //==>1   
 y; //==>1  

我们会发现不但我们希望的移动呢效果没有完成,反而会多出两个全局变量。那么如何解决呢?只要要进入函数中的函数时将this保存到一个变量中,再运用该变量即可。代码如下:

[html]
view plain
copy

var point = {   
 x : 0,   
 y : 0,   
 moveTo : function(x, y) {   
      var that = this;   
     // 内部函数  
     var moveX = function(x) {   
     that.x = x;   
     };   
     // 内部函数  
     var moveY = function(y) {   
     that.y = y;   
     }   
     moveX(x);   
     moveY(y);   
     }   
 };   
 point.moveTo(1, 1);   
 point.x; //==>1   
 point.y; //==>1  

构造函数调用

 

在javascript中自己创建构造函数时可以利用this来指向新创建的对象上。这样就可以避免函数中的this指向全局了。

[html]
view plain
copy

var x = 2;  
 function test(){  
   this.x = 1;  
 }  
 var o = new test();  
 alert(x); //2  

apply或call调用

这两个方法可以切换函数执行的上下文环境,也就是改变this绑定的对象。apply和call比较类似,区别在于传入参数时一个要求是数组,一个要求是分开传入。所以我们以apply为例:

[html]
view plain
copy

<pre name="code" class="html">var name = "window";  
      
var someone = {  
    name: "Bob",  
    showName: function(){  
        alert(this.name);  
    }  
};  
  
var other = {  
    name: "Tom"  
};     
   
someone.showName();     //Bob  
someone.showName.apply();    //window  
someone.showName.apply(other);    //Tom  

可以看到,正常访问对象中方法时,this指向对象。使用了apply后,apply无参数时,this的当前对象是全局,apply有参数时,this的当前对象就是该参数。

箭头函数调用

这里需要补充一点内容,就是在下一代javascript标准ES6中的箭头函数的 this始终指向函数定义时的 this,而非执行时。我们通过一个例子来理解:

[html]
view plain
copy

var o = {  
    x : 1,  
    func : function() { console.log(this.x) },  
    test : function() {  
        setTimeout(function() {  
            this.func();  
        }, 100);  
    }  
};  
  
o.test(); // TypeError : this.func is not a function  

上面的代码会出现错误,因为this的指向从o变为了全局。我们需要修改上面的代码如下:

[html]
view plain
copy

var o = {  
    x : 1,  
    func : function() { console.log(this.x) },  
    test : function() {  
        var _this = this;  
        setTimeout(function() {  
            _this.func();   
        }, 100);  
    }  
};  
  
o.test();  

通过使用外部事先保存的this就行了。这里就可以利用到箭头函数了,我们刚才说过,箭头函数的 this始终指向函数定义时的 this,而非执行时。所以我们将上面的代码修改如下:

[html]
view plain
copy

var o = {  
    x : 1,  
    func : function() { console.log(this.x) },  
    test : function() {  
        setTimeout(() => { this.func() }, 100);  
    }  
};  
  
o.test();  

这回this就指向o了,我们还需要注意一点的就是这个this是不会改变指向对象的,我们知道call和apply可以改变this的指向,但是在箭头函数中是无效的。

[html]
view plain
copy

var x = 1,  
    o = {  
        x : 10,  
        test : () => this.x  
    };  
  
o.test(); // 1  
o.test.call(o); // 依然是1  

这样就可以明白各种情况下this绑定对象的区别了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: