JavaScript設計模式與開發實踐---讀書筆記(2) this、call和apply

來源:互聯網
上載者:User

標籤:

this、call和apply

this的指向:

this總是指向一個對象,而具體指向哪個對象是在運行時基於函數的執行環境動態綁定的,而非函數被聲明時的環境。

1.作為對象的方法被調用

當函數作為對象的方法被調用時,this指向該對象

2.作為普通函數調用

此時的this總是指向全域對象。在瀏覽器的JavaScript裡,這個全域對象是window對象。

有時候,我們希望div節時間點事件函數內部的this指向該div節點,可以用一個變數儲存div節點的引用:

var that = this;

在ES5的strict 模式下,這種情況下的this已被規定為不會指向全域對象,而是undefined

3.構造器調用

構造器的外表跟普通函數一模一樣,它們的區別在於被調用的方式。當用new運算子調用運算子時,該函數總會返回一個對象,通常情況下,構造器裡的this就指向返回的這個對象。

注意:使用new調用構造器時,還要注意一個問題,如果構造器顯式地返回了一個object類型的對象,那麼此次運算結果最終會返回這個對象,而不是我們之前期待的this。

4.Function.prototype.call或Function.prototype.apply調用

用Function.prototype.call或Function.prototype.apply可以動態改變傳入函數的this。

丟失的this

 

call和apply

Function.prototype.call或Function.prototype.apply都是非常常用的方法。它們的作用一模一樣,區別僅在於傳入參數形式的不同。

apply接受兩個參數,第一個參數指定了函數體內this對象的指向,第二個參數為一個帶下標的集合,這個集合可以為數組,也可以為類數組,apply方法把這個集合中的元素作為參數傳遞給被調用的函數:

var func = function(a,b,c){    alert([a,b,c]);  //輸出[1,2,3]};func.apply(null,[1,2,3]);

 

call傳入的參數數量不固定,跟apply相同的是,第一個參數也是代表函數體內的this指向,從第二個參數開始往後,每個參數被依次傳入參數:

 

var func = function(a,b,c){    alert([a,b,c]);  //輸出[1,2,3]};func.call(null,1,2,3);

JavaScript的參數在內部就是用一個數組來表示的。從這個意義上來說,apply比call的使用率更高,我們不必關心具體有多少參數被傳入參數,只有用apply一股腦地推過去就可以了。

call是封裝在apply上面的一顆文法糖,明確知道函數接受多少個參數,也可以用call來傳送參數。

當使用call或者apply的時候,如果我們傳入的第一個參數為null,函數體內的this會指向預設的宿主對象,在瀏覽器中則是window,

但如果是在strict 模式下,函數體內的this還是為null。

 

call和apply的用途:

1.改變this的指向

最常見的用途是改變函數內部的this指向。

2.Function.prototype.bind

Function.prototype.bind,用來指定函數內的this指向

類比bind實現:

Function.prototype.bind = function(context){    var self = this;//儲存原函數    return function(){//返回一個新的函數        return self.apply(context,arguments);//執行新的函數的時候,會把之前傳入的context當作新函數體內的this    }};var obj = {    name:‘sven‘};var func = function(){    alert(this.name);//輸出:sven}.bind(obj);func();

複雜版:

Function。prototype.bind = function(){    var self = this,//儲存原函數          context = [].shift.call(arguements),//需要綁定的上下文          args = [].slice.call(arguements);//剩餘的參數轉成數組    return function(){       return self.apply(context,[].concat.call(args,[].slice.call(arguements)));     //執行新的函數的時候,會把之前傳入的context當作新函數體內的this    //並且組合兩次分別傳入的參數,作為新函數的參數    }};var obj = {    name:‘sven‘};var func= function(a,b,c,d){    alert(this.name);//輸出:sven    alert([a,b,c,d]);//輸出:[1,2,3,4]}.bind(obj,1,2);func(3,4);

3.借用其他對象的方法
借用方法的第一種情境是"借用建構函式",通過這種技術,可以實現一些類似繼承的效果。

借用方法的第二種運用情境跟我們的關係更加密切。

函數的參數列表arguments是一個類數組對象,雖然它也有"下標",但它並非真正的數組,所以不能像數組一樣,進行排序操作或者往集合裡添加一個新的元素。這種情況下,我們常常會借用Array.prototype對象上的方法。如Array.prototype.push,Array.prototype.slice,Array.prototype.shift等。

JavaScript設計模式與開發實踐---讀書筆記(2) this、call和apply

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.