最近在看 你不知道的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 对象就指向那里!
如果上面的代码你觉得啰嗦,直接记住这一点就好