学习javascript过程中遇到的that=this的调查解惑

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a5nan/article/details/80702889

最近写微信小程序就在学js,关于关键字this的指向不是很理解,于是在收集了一系列资料以后做了以下整理,便于自己加深理解。

首先是这个讲解的比较全:JavaScript中的对象查找 他说这么说的:

首先,this对象只会在一个函数中需要确定,如果是在全局域下,this永远为Global对象,在浏览器中通常就是window对象。而在javascript中,函数的调用一共有4种方式:

  • Function Invocation Pattern
诸如foo()的调用形式被称为Function Invocation Pattern,是函数最直接的使用形式,注意这里的foo是作为单独的变量出现,而不是属性。
在这种模式下,foo函数体中的this永远为Global对象,在浏览器中就是window对象。
  • Method Invocation Pattern
诸如foo.bar()的调用形式被称为Method Invocation Pattern,注意其特点是被调用的函数作为一个对象的属性出现,必然会有“.”或者“[]”这样的关键符号。
在这种模式下,bar函数体中的this永远为**“.”或“[”前的那个对象**,如上例中就一定是foo对象。
  • Constructor Pattern
new foo()这种形式的调用被称为Constructor Pattern,其关键字new就很能说明问题,非常容易识别。
在这种模式下,foo函数内部的this永远是new foo()返回的对象。
  • Apply Pattern
foo.call(thisObject)和foo.apply(thisObject)的形式被称为Apply Pattern,使用了内置的call和apply函数。
在这种模式下,call和apply的第一个参数就是foo函数体内的this,如果thisObject是null或undefined,那么会变成Global对象。

应用以上4种方式,确定一个函数是使用什么样的Pattern进行调用的,就能很容易确定this是什么。

这里说到了4种调用模式,能明确分类的情况下this的指向就一目了然,但是你可能会说光看文字还是有点不太理解,那好,下面又有个大神是这么解释的:this 的值到底是什么?一次说清楚

JS(ES5)里面有三种函数调用形式:
func(p1, p2) 
obj.child.method(p1, p2)
func.call(context, p1, p2) // 先不讲 apply
一般,初学者都知道前两种形式,而且认为前两种形式「优于」第三种形式。
从看到这篇文章起,你一定要记住,第三种调用形式,才是正常调用形式:

func.call(context, p1, p2)
其他两种都是语法糖,可以等价地变为 call 形式:
func(p1, p2) 等价于
func.call(undefined, p1, p2)
obj.child.method(p1, p2) 等价于
obj.child.method.call(obj.child, p1, p2)
请记下来。(我们称此代码为「转换代码」,方便下文引用)
至此我们的函数调用只有一种形式:

func.call(context, p1, p2)
这样,this 就好解释了
this,就是上面代码中的 context。就这么简单。
this 是你 call 一个函数时传的 context,由于你从来不用 call 形式的函数调用,所以你一直不知道。
先看 func(p1, p2) 中的 this 如何确定:
当你写下面代码时

function func(){
  console.log(this)
}
func()
等价于
function func(){
  console.log(this)
}
func.call(undefined) // 可以简写为 func.call()
按理说打印出来的 this 应该就是 undefined 了吧,但是浏览器里有一条规则:
如果你传的 context 就 null 或者 undefined,那么 window 对象就是默认的 context(严格模式下默认 context 是 undefined)
因此上面的打印结果是 window。
如果你希望这里的 this 不是 window,很简单:

func.call(obj) // 那么里面的 this 就是 obj 对象了
再看 obj.child.method(p1, p2) 的 this 如何确定
var obj = {
  foo: function(){
    console.log(this)
  }
}
obj.foo() 
按照「转换代码」,我们将 obj.foo() 转换为
obj.foo.call(obj)

好了,this 就是 obj。搞定。

以上的文字里面讲到了语法糖和函数转换,各种模式都可以转换成Apply Pattern,然后就很简单的取出第一个参数即可。但是他没有说到Constructor Pattern的这个模式,但这个好理解:“foo函数内部的this永远是new foo()返回的对象”,而且有new这个关键字在帮你区分。

更多的扩展那个大神也说到了:你怎么还没搞懂 this?

练习题:Javascript中this关键字详解

说了那么多,还没说为什么要用that=this。这么搞的目的就是在操作this的内容之前先把当前状态备份下来。







猜你喜欢

转载自blog.csdn.net/a5nan/article/details/80702889