人生自是有情癡,此恨不關風與月javascript
今天所寫的內容,是對以前的內容的總結和擴展。老實說,對於本身以前的一些杜撰和臆測,我並非很滿意。因此這篇博文,我但願能來點乾貨。java
在JavaScript中,咱們能夠用this來指代當前的對象。這種感受就像使用Java同樣。不過與Java不一樣的是,在Java中,this的指代老是很明顯的;然而在JavaScript中,this的指代在不一樣的調用方式下,其指代每每不一樣。我爲此分爲四類:數組
若是咱們定義如下函數:app
function f() { console.log(this); }
而後將其做爲普通對象調用,即f()
,此時this指代的是全局對象window。函數
若是咱們將f做爲一個對象的方法,也就是說做以下改造:this
var a = {}; a.f = f;
而後經過對象a調用方法f,即a.f()
,此時this指代的就是調用者a。prototype
若是咱們用new語句調用函數f,即new f()
, 則此時this指代的是新建的對象。code
除了上述幾種方式外,咱們還能夠任意指定this的指代,這就是call和apply發揮做用的地方了。call和apply是每一個函數對象都擁有的方法,其第一個參數就是要指定的this值,後面是函數正常的參數值。其細微的差異在於參見下面的示例:對象
function g(name, age) { this.name = name; this.age = age } var a = {}; g.call(a, 'xiaoming', 18); g.apply(a, ['xiaoming', 18]);
即call的非this參數只需在後面列出就能夠了,apply要把它們封裝到一個數組裏面去。ip
從某種程度上說,前面的三種函數調用形式都是call方式的一種語法糖:
f() === f.call(window)
a.f() === f.call(a)
new f() === var _a = {}; f.call(_a)
call有很強大的能力,咱們經常使用的函數借用就是利用call能夠動態指定this這一特性的。例如Array.prototype.slice.call(a)
能夠將看起來像數組的對象a轉化爲實際的數組對象。
var a={length:2,0:'first',1:'second'}; Array.prototype.slice.call(a);// ["first", "second"] var a={length:2}; Array.prototype.slice.call(a);// [undefined, undefined]