JS中this指向简析

this关键字是JavaScript中最复杂的机制之一。它被自动定义在所有函数的作用域中,即使是非常有经验的JavaScript开发者也很难说清楚它到底指向什么。
其实只需要记住一点:this的指向在函数定义的时候是无法确定的,只有在函数执行的时候才能确定this到底指向谁,谁调用它就指向谁!

人们很容易把this理解成指向函数本身,这个推断其实从英语的语法角度来讲是没问题的。我们先来分析一下以下这个例子:

    function count(num){//创建了函数count
        console.log('count:'+num);
        //这里记录这个函数的调用次数
        this.number++;
    }
    count.number=0;
    for(var i=0;i<5;i++){
        if(i>1){
            count(i);
        }
    }
    //运行结果:
    //count:2
    //count:3
    //count:4
    console.log(count.number);// 0 -- 为什么!

这里的console.log语句确实产生了3条输出,证明count确实被调用了3次,但是为什么count.number还是0?这个例子证明了显然从字面意思理解this是错误的!其实这里是这样的:

function count(num){
        console.log('count:'+num);
        this.number++;//此时this指向全局
    }
count.number=0;//创建了一个全局对象
for(var i=0;i<5;i++){
        if(i>1){
            count(i);//这里调用了count!这是在全局环境下!
        }
    }

哦!原来是这么回事!在for循环里面我调用了count函数,这时候是在全局环境里面!所以this就给我指向全局去了,并没有指向count函数本身!并且count函数对象里并没有number这个属性!

有的同学可能会问了:既然count.number是创建的全局对象,并且我这里函数调用的this指向的是全局,那为什么count.number还是0?
这个问题很简单,把在count函数里面把this打印出来就知道为什么了:
此时this指向打印的结果
在函数count内的this指向的是全局,而this.number++;指的含义是:window.number,而window对象下并没有number这个属性!

想要解决以上问题,很简单的一个方法,就是使用count标识符替代this来引用函数对象,但是这种方法回避了this的问题

    function count(num){
        console.log('count:'+num);
        count.number++;//count代替this
    }
    count.number=0;
    for(var i=0;i<5;i++){
        if(i>1){
            count(i);
        }
    }
    console.log(count.number);//3 -- 函数执行了3次,正确打印了3!

另一种方法强制this指向count函数对象:

    function count(num){
        console.log('count:'+num);
        this.number++;
    }
    count.number=0;
    for(var i=0;i<5;i++){
        if(i>1){
            //使用call可以确保this指向函数count本身
            count.call(count,i);
        }
    }
    console.log(count.number);//3 -- 正确打印了3!

一个例子并不能完全说明谁调用就指向谁的问题,我们再来一个例子
    function foo(){
        console.log(this.a);
    }
    var obj={
            a:4,
            faz:foo
    };
    obj.faz();//4 -- 通过对obj引用的方式调用foo,此时this绑定在obj对象,这叫做隐式绑定

这里是通过将foo函数赋值給obj中的一个对象,再调用这个对象,因此可以说函数被调用时obj对象“拥有”或者“包含”它,此时的this指向就被绑定到了obj对象!当foo被调用时,它的前面加上了对obj的引用,此时隐式绑定规则会把函数调用中的this绑定到这个对象

从上面两个例子可以印证我们文章开头的主旨:this的指向在函数定义的时候是无法确定的,只有在函数执行的时候才能确定this到底指向谁,谁调用它就指向谁!

猜你喜欢

转载自blog.csdn.net/qq_30455841/article/details/79859777
今日推荐