JavaScript 中this的指向

本文深入探讨JavaScript中的this关键字,解析其在不同上下文中的行为,包括作为对象方法、普通函数及构造函数调用的情况,同时介绍了ES6箭头函数中的this特性。

今天来聊聊JavaScript中的this,刚开始我]this的理解不深! 然后会看看各种技术文章,有时茅塞顿开,好像懂了了,使用中用迷糊了!

this

跟别的语言有很大的不同,JavaScript中的this总是指向一个对象,具体指向哪个对象是在运行时基于函数的执行环境动态绑定的,不是函数声明时的环境.

this的指向

不考虑with和eval.

  1. 作为对象的方法调用
  2. 作为普通函数调用
  3. 作为构造器调用
  4. Function.prototype.call 或Function.prototype.apply调用

情况一:作为对象方法的调用

当函数作为对象的方法调用,这时this指向这个对象。

var obj={
a:1,
getA:function(){
    console.log(this===obj);  //true
    console.log(this.a); //1
}
}
obj.getA();

复制代码
情况二:普通函数调用

这是函数的最通常用法,属于全局性调用,此时函数总是指向全局对象,在浏览器里,就是window。

window.name="globalName";
var getName=function(){
    return this.name;
}
console.log(getName()); //输出:globalName复制代码

有时候会有很多困扰比如在回调事件中有一个callBack方法,callBack被作为普通函数调用时,callBack内部的this是window,我们想要的其实是触发事件的元素,代码如下:

<html>
    <body>
        <div id="div1" > 我被点击了</div>
    </body>
    <script>
        window.id='window';
        document.getElementById("div1").onclick=function(){
            console.log(this.id); // div1;
            var callback=funciton(){
                console.log(this.id); //输出:// window
            }
            callback();
        }
    <script>
</html>

复制代码

解决办法就是利用闭包,

         window.id='window';
        document.getElementById("div1").onclick=function(){
            console.log(this.id); // div1;
            var self=this;
            var callback=funciton(){
                console.log(self.id); //输出:div1
            }
            callback();
        }复制代码

如果在es5的严格模式下(strict),this被规定不指向全局了,是undefined

function func(){
    "use strict"
    alert(this); //undefined
}复制代码

情况三 作为构造器调用

所谓构造函数,就是通过这个函数生成一个新对象(object)。这时,this就指这个新对象。

var MyClass=function(){
    this.name="seven";
}
var obj=new MyClass();
console.log(obj.name); //输出:seven


复制代码

  注意: 如果构造器返回了一个object类型的对象,那么new 操作符后返回的是这个对象,不是我们的this;
var MyClass=function(){
    this.name="seven";
    return {
     name:'小狗',
    }
}
var obj=new MyClass();
console.log(obj.name); //输出:'小狗'复制代码

情况四 apply,call调用

跟普通函数相比,使用call和apply可以动态的指定this指向

var obj1={
a:1,
getA:function(){
    console.log(this===obj1);
    console.log(this.a);
}
}
var obj2={
    a:'小狗'
}
console.log(obj1.getA()); //输出: ture ,1
console.log(obj1.getA.call(obj2)); //输出:false 小狗复制代码

记得看过一个面试题 "不用call和apply方法模拟实现ES5的bind方法",可以帮助我对this很好的理解.

丢失的this

var obj={
a:1,
getA:function(){
    return this.a;
}
}
console.log(obj.getA());//输出 1
var getB=obj.getA;
console.log(getB); //输出 undefined


复制代码

当调用obj.getA(),getA是作为obj的属性被调用的,根据 情况一作为对象方法的调用,此时的this 指向obj;

当var getB=obj.getA; 这个时候就相当于普通函数调用 好比 var getB=function(){};,所以this指向window

最后聊一聊箭头函数

ES6允许使用(=>)定义函数

var f = v => v;
复制代码

上面的箭头函数等同于:

var f = function(v) {
  return v;
};复制代码

使用注意点

箭头函数有几个使用注意点。

(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。

(2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。

(3)不可以使用arguments对象,该对象在函数体内不存在。

var handler = {
  id: '123456',
  getId:()=>{
    return this.id
    },
  init: function(type) {
     let callback=type => this.doSomething(type);
    callback();
  },

  doSomething: function(type) {
    console.log('Handling ' + type  + ' for ' + this.id);
  }
};

//注意这里与"情况一:作为对象方法的调用" 的区别点,有一些迷惑
handler.getId(); // 输出:undfined

getId()使用的是箭头函数,箭头函数里面是没有this的,所以里面的this来自外部代码块
handler这个代码块又不够成作用域(函数作用域和全局作用域),所以this指向window


handler.init(); //输出123456 

init不是箭头函数,根据 "情况一:作为对象方法的调用" init的this指向handler,
init是函数形成作用域,在函数作用中定义箭头函数callback,callback是箭头函数没有this,
所以找到外部代码块的init作用域的this;


用普通函数表示如下:

var handler = {
  id: '123456',
  init: function(type) {
    var self=this;
    var callback=function(){
        self.doSomething(type);
    }
    callback();
  },
  doSomething: function(type) {
    console.log('Handling ' + type  + ' for ' + this.id);
  }
};


复制代码

上面代码的init方法中,使用了箭头函数,这导致这个箭头函数里面的this,总是指向handler对象。否则,回调函数运行时,this.doSomething这一行会报错,因为此时this指向

window
对象。

this指向的固定化,并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,导致内部的this就是外层代码块的this。正是因为它没有this,所以也就不能用作构造函数。

这就是我对this的理解,希望读完这个,大家都能理解!

今天就写到这里


参考:http://www.ruanyifeng.com/blog/2010/04/using_this_keyword_in_javascript.html



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值