你不知道的JavaScript笔记之关于this

来源:互联网 发布:上海首届网络文化节 编辑:程序博客网 时间:2024/06/13 23:09

    • 关于this
      • 为什么要用this
      • this的误解
        • 指向自身
      • this的作用域

关于this

this 关键字在JavaScript中也算是相当复杂的了,它被定义在所有的函数的作用于中。
之前用this总是模棱两可,能用对,但是有时候真正解释的时候,说着说着自己都被绕迷糊了。请各路大神给以指点,有出入的地方给以纠正~

为什么要用this

我们在知道怎么做之前,我们需要先明白为什么
不要老是看别人用的this怎么用的,要先明白别人为什么要用它!!

首先看一段用this的代码,然后分析为什么用它:

           function transform(){               return this.name.toUpperCase();           }           function statement(){           var myState = "Hello, I'm  "+transform.call(this);           console.log(myState);           }         var me = {             name:"Pakar"         };         var you = {             name:"Lucy"         };         transform.call(me);//PAKAR         transform.call(you);//LUCY         statement.call(me);//Hello,I'm PAKAR         statement.call(you);//Hello,I'm LUCY

这段代码使用this来实现的,下面我们不使用this,通过给它传递参数(一个上下文对象)来实现一下:

         function transform(context){               return context.name.toUpperCase();           }           function statement(context){           var myState = "Hello, I'm  "+transform(context);           console.log(myState);           }         var me = {             name:"Pakar"         };         var you = {             name:"Lucy"         };         transform(me);//PAKAR         transform(you);//LUCY         statement(me);//Hello,I'm PAKAR         statement(you);//Hello,I'm LUCY*/

通过上面两端代码的对比,想必你也发现了,在不使用this的情况下,我们显式的传递了一个context。然而,使用this这样隐式的传递一个对象的引用,是不是很简洁又容易复用呀~

再补一个例子

          //为对象中的方法指定一个 this        var obj = {          name: 'Pakar',          foo: function () {            console.log(this);          }        }        var obj2 = {          name: 'Lucy'        };        obj.foo.call(obj2);// Object {name: "Lucy"}

显式传递:

        var obj = {          name: 'Pakar',          foo: function (context) {            console.log(context);          }        }        var obj2 = {          name: 'Lucy'        };        obj.foo(obj2);

如果你一直用显式的方式传递的话,你会发现代码越来越混乱,使用this就好多啦。同时也能够自动引用。

this的误解

有时候我们太在意这个单词的字面意思,就会造成一些误解。
一般有两种错误的误解:
* 指向自身
* this指向函数的作用域(有点复杂,有些情况正确,其他情况却是错误)

这是两个很常见的误解

指向自身

先看一个例子:

       function foo(num){         console.log("foo: "+num);         this.count++;          }          foo.count = 0;          var i;          for(i=0;i<10;i++){          if(i>5){              foo(i);          }          }       /*         foo: 6         foo: 7         foo: 8         foo: 9       */        //window   i foo         //foo    num 当执行到foo.count=0时候,向函数对象添加一个属性count          console.log(foo.count); //0          console.log(count);//NaN

这里我们会发现foo{…}执行了4次,foo.count仍然是0,要是还说this是指向自身的话,应该就是错误了吧,这就是this的误解之一,并不是都指向自身。

分析代码:
执行到foo.count=0时候,向函数对象添加一个属性count。函数内部的this.count并不是指向那个函数的this。那这个函数里面的count是哪个count呢?我们在window下面输出的值是NaN,可以看出,这个count是全局变量count。这是怎么造成的呢?

这造成的真正原因就是JS词法作用域

词法作用域,也可以说代码作用域,代码在编写时候体现出来的作用范围,代码一写好,你不用执行,作用范围就已经确定好了,这就是词法作用域
整个代码只有函数可以限定作用域

所以在foo函数里面,并没有count,所以就会像它的父级函数找,在非严格模式下window会声明这个count,这个时候count为undefined,所以++会返回NaN;

this的作用域

有时候误解this指向函数的作用域,某种情况下它正确,其他情况却错误。
this在任何情况下都不指向函数的词法作用域。作用域和对象确实挺像。

     function foo(){             var a = 2;             this.bar();         }         function bar(){             console.log(this.a);//undefined         }         foo();

这里想用this来引用函数的词法作用域,想引用foo的词法作用域,然后在bar里面操作foo作用域里面的a。刚才也说了this不指向函数的词法作用域,所以this也不可能在词法作用域中找到什么。

总结:
学习this首先要明白this既不指向函数自身也不指向函数的词法作用域。它在运行时进行绑定,不要想着在编写时,当然它的绑定和函数声明位置没什么关系!

this在函数被调用时发生绑定,它指向什么完全取决于函数在哪里被调用。

1 0