【笔记】探索js 的this 对象 (第一部分)

最近在看 你不知道的javascript 这本书,在第二部分看到了一个比较重要的知识点 那就是 this对象的全面认识,于是做一下笔记

博主本人在看这本书之前也一直以为 this 是指一切引用类型的本身 但直到最近才明确了 this 对象的见解 关于this 对象误解书上也作了一些解释 下面我来整理一下

先看下面的例子:

 function foo(num){
    console.log(num);
        this.count++;
 }

 foo.count = 0;for (var i = 0; i < 10; i++) {
    if (i > 5) {
    foo(i);
    }
}
console.log("函数被调用了多少次?" + foo.count); //0    

在js 里面 函数即对象 我们将foo 函数定义了a 属性,在循环调用 foo函数中 foo函数的a 属性自增1

但是为什么最后输出结果为0 ???

这就是我们对this 对象的第一个误解:this指向函数自身

实际上this.a 指向了 window对象,不相信??看看下面代码的变化吧

 function foo(num){
    console.log(num);
    this.count++;
 }

 foo.count = 0;
 window.count = 0; window.count 还没有被初始化
 for (var i = 0; i < 10; i++) {
    if (i > 5) {
       foo(i);
     }
 }
 console.log("函数被调用了多少次?" + foo.count); //0

 console.log("count 属性变成了 window属性了!!但window属性并没有初始化:" + window.count); //NaN

打开你的编译器试试便知晓~

函数的执行 this.count 并没有指向 foo函数的本身而是当 foo函数循环执行的时候为 window对象 添加 count属性 并且每次循环为这个属性自增1

但是因为 window对象中 并没有count 这个属性所以输出的只是 NaN 的结果

那么我们可以把window.count属性初始化一下

function foo(num){
    console.log(num);
    this.count++;
}

foo.count = 0;
window.count = 0; 

for (var i = 0; i < 10; i++) {
    if (i > 5) {
      foo(i);
    }
}

console.log("函数被调用了多少次?" + foo.count); //0


console.log("count 属性变成了 window属性了!!而且window属性得到了初始化:" + window.count);//调用次数为4

初始化之后我们就可以看到函数的正确调用次数结果了~

我们再看看第二个误区:

我们对this 对象的第二个误解:this对象指向函数的作用域

看看下面例子:

 window.a = "i'm window";

     function fun(){
       var a = "this is fun";
       this.bar();
     }

     function bar(){
       console.log(this.a);
     }

     fun();// i'm window
     bar.call(window);//上面的行为等价于这个

解释一下:

作者在书上的原意是 想把bar 的执行引用绑定在fun 函数中
但是因为 fun是在 window对象下执行的 所以this对象 指向的是 window对象
所以 this.bar() 变成了在window对象下执行函数 bar(),或直接等于在 window 对象下直接调用了 bar() 这个函数
此行为也等价于 bar.call(window)

当然要让bar 函数在fun 函数里面调用何必要花那么大的功夫

直接将bar()函数写在 fun中就可以了

另外声明一点就是:this 对象不指向函数的词法作用域(详情请看 你不知道的javascript 闭包和作用域的一章)

小结:

那么this 的对象指的是哪一个呢?

看了上面的两个例子,我们不难发现this 对象大多数都和 window对象有关系 那是为什么呢?

再举个例子:

function fun(){
    this.a = "i'm function fun";
    console.log(this.a);
}

fun();//i'm function fun

console.log(window.a);//i'm function fun

表面上看 在fun函数内部定义了 this.a 这一条语句就是给fun 函数添加了一个a 属性

但是当fun 函数执行的时候 实际上却将a 这个属性赋值给了 window对象
因此在下一句里面输出 window.a 的结果 和执行fun 函数的结果一样

归根结底就是因为 fun 函数在 window对象下调用了!

再看一个例子:

function foo(){
    console.log(this.a);
}

function fun(){
    this.a = "i'm function fun";
    console.log(this.a);
}

var obj = {
    a: "hello i'm a obj",
    foo: foo,
    fun: fun
}

obj.foo();//hello i'm a obj
obj.fun();//i'm function fun    

这里定义了一个对象字面量 obj
为obj 设置了一个属性 a,值为:"hello i'm a obj"
然后又定义了两个引用属性:foo 和 fun,他们分别引用 foo函数 和 fun函数

当通过obj 调用 foo函数的时候 输出结果是obj 的a属性值
但调用fun 函数的时候输出结果却是函数内部定义的 a属性值

为什么呢??不是说this 不指向函数本身吗???

-------分隔线-------

别混淆了

上面已经说过 函数里面通过this定义的属性并不是属于函数的作用域
即这个属性并不是函数本身的(虽说js 的函数也是对象 但不带这么玩)

实际上 fun 函数里面this.a 这个语句是为函数当前调用环境对象的属性赋值的语句
通俗的说:
如果,fun函数在 obj 里面调用 this.a 语句就为 obj 对象里面的a 属性赋值
如果,fun函数在 window 对象里面调用 this.a 语句就为 window对象里面的 a属性赋值
如果调用函数的环境下没有匹配的属性 就为其环境创建一个属性并赋值

所以我们得出总结:

 this 对象指向的是函数执行作用域的对象,即函数在哪里执行,this 对象就指向那里!

 如果上面的代码你觉得啰嗦,直接记住这一点就好

原文地址:https://www.cnblogs.com/stitchgogo/p/6587207.html