我的this见解
17 Nov 2016关于this
, 现在应该有很多文章提到了它,它在JavaScript里的作用特别明显,几乎一写到js,基本会用到this
了,尤其是面向对象的时候。
在我看来,this
往往和原型链、作用域扯上关系,又有所区别。
比方说作用域下访问变量这回事:
这段很简单的代码透露着作用域的信息,在JavaScript
里,并没有块作用域这个概念,有别于java
等语言(当然es6
开始就有了)。
上面代码里如果function
的var a = 2;
注释掉,那么里面访问a变量会是这么一个顺序,先看一下function
里面有没有声明变量a
,有就拿来,没有,那就往上一层看是否有a
,没有就继续往上,直到到了global
, 浏览器下是window
,示例代码就两层,所以会发现a=1
,这就是作用域的一个访问过程。
但是,对于this
,就不能这么搞了,应该有两个属性要特别注意,即 this
和arguments
,后者表示function
的参数对象(类数组,但具有一些其他方法);
this
的概念可以参考 MDN
文章里描述的this
有很多情况,但在实际应用中,其实我觉得可以理解为一种情况,即当你使用this
的时候,你只要知道这个this
是哪个对象调用它的,那它就代表哪个对象了~谁调用谁负责,找TA就对了~
上述例子,一般而言,但找不到代码的调用对象是谁时,一般是最上层,即浏览器的window
,or node
下的global
(后者我不熟)
一般来在浏览器下,直接var a = 1;
其实可以当做是window.a = 1;
,而在window
下访问this
,当然就是window
了,所以第一个输出是1;
而我们知道,一般的function
,其实它是window.b
,自然里面的this
指向的是window
了。
call
以及apply
方法,他们将function
绑定到某个对象上去使用,相当于这个对象拥有了这个方法,并且调用执行了。那么此时function
里面的this
就是指向绑定的对象咯,也就是示例里的c
.
es5
还有个bind
方法,可以将function
绑定到某个对象上作为一个新方法,差不多跟jquery
的proxy
方法一样,生成一个新的方法(带绑定对象的),此时新方法里的this
就指向了bind
的那个对象了。
怎么用?
只要弄清楚this
的调用对象,就很好办了。
我以往经常用到,也在各种js
代码里看到,比如说类数组 arguments
, 它不是数组,但它似数组,那我想用数组的api行不?
可以,如下:
这样就让类数组对象可以用上数组的slice
方法了.
还有更妙的,在我看jquery
源码的时候, 对promise
的链式一知半解。
表面上看Callbacks
的实现,add
方法属于self
,但实际上,通过promise[ tuple[1] ] = list.add;
已经将这个方法赋值到promise
那边了,当promise
在调用done
方法的时候,在add
方法这边返回的this
,指向的其实就是调用方(promise
),所以可以继续链式调用。
有了this
跟call
、bind
等方法,使得function
的自由度更广,我不需要考虑封装的时候把所有方法写死到一个类里,只要活用this
, 同样可以共享api~