发表于: 2017-06-08 20:53:26

1 864


今天完成的事情:

【JS-4】JS中this的指向

小课堂【深圳第135期】

分享人:覃腾波

1.背景介绍

2.知识剖析

3.常见问题

4.解决方案

5.编码实战

6.扩展思考

7.参考文献

8.更多讨论

1.背景介绍

在面向对象的语言中(例如Java,C#等),this含义是明确且具体的,即指向当前对象。一般在编译期绑定。而在javascript中,this是动态绑定的,它可以是全局对象、当前对象或者任意对象,这完全取决于函数的调用方式。这就导致了this具备了多重含义,可以使得javascript更灵活的使用。但是,带来了灵活性的同时也会给我们初学者带来不少困惑。

2.知识剖析

全局环境中的this

console.log(this);

总结:在全局作用域中它的 this 执行当前的全局对象(浏览器端是 Window,node 中是 global)

例子1:

function a(){

        var user = "qintengbo";

        console.log(this.user); //undefined

        console.log(this); //Window

        }

        a();

this最终指向的是调用它的对象,这里的函数a实际是被Window对象所点出来的,下面的代码就可以证明。

function a(){

        var user = "qintengbo";

        console.log(this.user); //undefined

        console.log(this);  //Window

        }

        window.a();

和前面代码一样,其实alert也是window的一个属性,也是window点出来的。

例子2:

var o = {

            user:"qintengbo",

            fn:function() {

            console.log(this.user);  //qintengbo

          }

        }

        o.fn();

这里的this指向的是对象o,因为你调用这个fn是通过o.fn()执行的,那自然指向就是对象o。

this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象.

其实例子1和例子2说的并不够准确,下面这个例子就可以推翻上面的理论。

如果要彻底的搞懂this必须看接下来的几个例子。

例子3:

var o = {

            user:"qintengbo",

            fn:function() {

            console.log(this.user); //qintengbo

          }

        }

        window.o.fn();

这段代码和上面的那段代码几乎是一样的,但是这里的this为什么不是指向window,如果按照上面的理论,最终this指向的是调用它的对象。

var o = {

          a:10,

          b:{

            a:12,

            fn:function(){

              console.log(this.a); //12

             }

          }

        }

        o.b.fn();

这里同样也是对象o点出来的,但是同样this并没有执行它,那你肯定会说我一开始说的那些不就都是错误的吗?其实也不是,只是一开始说的不准确。

情况1:如果一个函数中有this,但是它没有被上一级的对象所调用,那么this指向的就是window,这里需要说明的是在js的严格版中this指向的不是window。

情况2:如果一个函数中有this,这个函数有被上一级的对象所调用,那么this指向的就是上一级的对象。

情况3:如果一个函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象。

证明情况3的说法:

var o = {

            a:10,

            b:{

            // a:12,

            fn:function(){

               console.log(this.a); //undefined

               }

            }

        }

        o.b.fn();

尽管对象b中没有属性a,这个this指向的也是对象b,因为this只会指向它的上一级对象,不管这个对象中有没有this要的东西。

特殊情况例子4:

var o = {

            a:10,

            b:{

            a:12,

            fn:function(){

                console.log(this.a); //undefined

                console.log(this); //window

               }

            }

        }

        var j = o.b.fn;

        j();

这里this指向的是window,是不是有些蒙了?

其实是因为你没有理解一句话,这句话同样至关重要:

this永远指向的是最后调用它的对象,也就是看它执行的时候是谁调用的。

严格模式 ‘use strict’下的this

'use strict';

                  function test() {

                  console.log(this);

                  };

                  

                  test();

                  

                  // undefined

原因:this 并不会指向全局,而是 undefined,这样的做法是为了消除 js 中一些不严谨的行为

jq中的this和$(this):

$("button").click(function(){

        console.log(this);

        console.log($(this));

        });

$(this)是jquery对象,能调用jquery的方法,例如click(), keyup()。

而this,则是html元素对象,能调用元素属性,例如this.id,this.value。

例如假设已经使得this和$(this)都指向了input对象了,若要获得input的值,可以this.value,但$(this)就得$(this).val()。

3、常见问题

var obj = {

                   name: 'qiutc',

                   foo: function() {

                     console.log(this);

                   },

                   foo2: function() {

                     console.log(this);

                     setTimeout(this.foo, 1000);

                   }

                 }

                 

                 obj.foo2();


现象:两次打印的this不一样

4、解决方案

可以这么这么解决:利用 闭包 的特性来处理

var obj = {

                      name: 'qiutc',

                      foo: function() {

                        console.log(this);

                      },

                      foo2: function() {

                        console.log(this);

                        var _this = this;

                        setTimeout(function() {

                          console.log(this);  // Window

                    

                          console.log(_this);  // Object {name: "qiutc"}

                        }, 1000);

                      }

                    }

                    

                    obj.foo2();

可以看到直接用 this 仍然是 Window;因为 foo2 中的 this 是指向 obj,我们可以先用一个变量 _this 来储存,然后在回调函数中使用 _this,就可以指向当前的这个对象了

执行这段代码我们会发现两次打印出来的 this 是不一样的:

第一次是 foo2 中直接打印 this,这里指向 obj 这个对象,我们毋庸置疑;<br>

但是在 setTimeout 中执行的 this.foo ,却指向了全局对象,这里不是把它当作函数的方法使用吗?这一点经常让很多初学者疑惑;<br>

其实,setTimeout 也只是一个函数而已,函数必然有可能需要参数,我们把 this.foo 当作一个参数传给 setTimeout 这个函数,就像它需要一个 fun 参数,在传入参数的时候,其实做了个这样的操作 fun = this.foo,看到没有,这里我们直接把 fun 指向 this.foo 的引用;执行的时候其实是执行了 fun() 所以已经和 obj 无关了,它是被当作普通函数直接调用的,因此 this 指向全局对象。<br>

这个问题是很多异步回调函数中普遍会碰到的;

5、编码实战

百度14年的笔试题:

var myObject = {  

                    foo:"bar",  

                    func: function() {  

                          var self = this;  

                          console.log("outer func: this.foo = " + this.foo);  

                          console.log("outer func: self.foo = " + self.foo);  

  

                         (function (){  

                             console.log("inner func: this.foo = " + this.foo);  

                             console.log("inner func: self.foo = " + self.foo);  

                         }());  

                    }  

               }  

               myObject.func(); 

这里分别会打印出什么?

6.扩展思考

问题:当this遇到return时会发生什么?

如果返回值是一个对象,那么this指向的就是那个返回的对象,如果返回值不是一个对象那么this还是指向函数的实例。

7.参考文献

参考一:http://www.cnblogs.com/pssp/p/5216085.html

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

8、更多讨论

如何解决this的指向问题?

call、apply、bing如何使用?

明天计划的事情:

收尾任务8,开始任务9。

遇到的问题:

暂无

收获:

this的指向、闭包的知识





返回列表 返回列表
评论

    分享到