成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

JavaScript設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐 | 02 - this、call和apply

darryrzhong / 1024人閱讀

摘要:構(gòu)造器的外表跟普通函數(shù)一樣,他們的區(qū)別在于被調(diào)用的方式。即,使用運(yùn)算符創(chuàng)建對(duì)象時(shí),就是將函數(shù)當(dāng)作構(gòu)造器調(diào)用。本節(jié)內(nèi)容為設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐第二章筆記。

this

JavaScript的this總是指向一個(gè)對(duì)象,至于指向哪個(gè)對(duì)象,是在運(yùn)行時(shí)基于函數(shù)的執(zhí)行環(huán)境的動(dòng)態(tài)綁定的,而非函數(shù)被聲明時(shí)的環(huán)境。

this的指向

this的指向大致可以分為以下4類:

作為對(duì)象的方法調(diào)用

作為普通函數(shù)調(diào)用

構(gòu)造器調(diào)用

Function.prototype.callFunction.prototype.apply調(diào)用

1.作為對(duì)象的方法調(diào)用

當(dāng)函數(shù)作為對(duì)象的方法被調(diào)用時(shí),this指向該對(duì)象:

// 聲明obj對(duì)象
var obj = {
    a: "a屬性的值",    // a 屬性
    getA: function(){  // getA()方法
        console.log(this === obj);  // 輸出:true
        console.log(this.a);  // 輸出: a屬性的值
    }
};

obj.getA();

2.作為普通函數(shù)調(diào)用

當(dāng)函數(shù)不作為對(duì)象的屬性被調(diào)用時(shí),也就是以普通函數(shù)方式,this指向全局對(duì)象。在瀏覽器的JavaScript里,全局對(duì)象是window對(duì)象。

window.name = "globalName";  // 聲明全局對(duì)象的name屬性

var getName = function(){  // 定義getName()函數(shù)
    return this.name;
};

// 調(diào)用函數(shù)
console.log(getName());  //輸出: globalName
window.name = "globalName";  // 聲明全局對(duì)象的name屬性

var myObject = {  // 聲明myObject對(duì)象
    name: "objectName";
    getName: function(){  // 定義getName()方法
        return this.name;
    }
}

var getName = myObject.getName;  // 將getName()方法賦給變量getName

console.log(getName());  // 輸出: globalName

3.構(gòu)造器調(diào)用

JavaScript沒(méi)有類,但可以從構(gòu)造器中創(chuàng)建對(duì)象,也提供了new運(yùn)算符用于調(diào)用構(gòu)造器。

大部分JavaScript函數(shù)都可以當(dāng)作構(gòu)造器使用。構(gòu)造器的外表跟普通函數(shù)一樣,他們的區(qū)別在于被調(diào)用的方式。即,使用new運(yùn)算符創(chuàng)建對(duì)象時(shí),就是將函數(shù)當(dāng)作構(gòu)造器調(diào)用。當(dāng)用new運(yùn)算符調(diào)用函數(shù)時(shí),該函數(shù)總會(huì)返回一個(gè)對(duì)象,此時(shí),構(gòu)造器里的this指向返回的這個(gè)對(duì)象。

var myClass = function(){
    this.name = "className";
};

var obj = new myClass();
console.log(obj.name);  // 輸出:seven

但,如果構(gòu)造器顯式地返回了一個(gè)object類型的對(duì)象,那么此函數(shù)將返回這個(gè)object類型的對(duì)象,而不是函數(shù)本身所定義的對(duì)象,例如:

var myClass = function(){
    this.name = "className";
    return {  //顯式地返回一個(gè)對(duì)象
        name: "anne"
    }
};

var obj = new myClass();
console.log(obj.name);  //  輸出:anne

而,如果構(gòu)造器不顯式地返回任何數(shù)據(jù),或返回一個(gè)非對(duì)象類型的數(shù)據(jù),就不會(huì)造成上述情形。

var myClass = function(){
    this.name = "className";
    return "anne";  // 返回string類型
};

var obj = new myClass();
console.log(obj.name);  //  輸出:className

4.Function.prototype.call 或 Function.prototype.apply調(diào)用

跟普通函數(shù)調(diào)用相比,用 Function.prototype.callFunction.prototype.apply 可以動(dòng)態(tài)地改變傳入函數(shù)的this。

var A = {
    name: "ObjectA",
    getName: function(){
        return this.name;
    }
};

var B = {
    name: "ObjectB"
};

console.log(A.getName()); // 作為對(duì)象的方法調(diào)用,輸出:ObjectA
console.log(A.getName.call(B)); // 輸出:ObjectB
丟失的this

我們經(jīng)常會(huì)因?yàn)閠his的指向與我們的期待不同,而出現(xiàn)undefined的情況,例如:

var obj = {
    name: "objName";
    getName: function(){
        return this.name;
    }
};

// 作為對(duì)象的方法調(diào)用,指向obj對(duì)象
console.log(obj.getName());   // 輸出:objName

// 作為普通函數(shù)調(diào)用,指向全局對(duì)象window,name屬性尚未定義
var getName2 = obj.getName;
console.log(getName2());  // 輸出:Lundefined
call 和 apply

ECAMScript3給Function的原型定義了兩個(gè)方法,分別是Function.prototype.call 或 Function.prototype.apply。在一些函數(shù)式風(fēng)格的代碼編寫中,call和apply方法尤為有用。

call和apply的區(qū)別

Function.prototype.call 或 Function.prototype.apply的作用一模一樣,區(qū)別僅在于傳入?yún)?shù)形式的不同。

apply接受兩個(gè)參數(shù),第一個(gè)參數(shù)制定了函數(shù)體內(nèi)this對(duì)象的指向,第二個(gè)函數(shù)為一個(gè)帶下標(biāo)的集合,這個(gè)集合可以是數(shù)組,也可以是類數(shù)組。apply方法把這個(gè)集合中的元素作為參數(shù)傳遞給被調(diào)用的函數(shù)。

var func = function(a, b, c){
  console.log([a, b, c]);  // 輸出:[1,2,3]
};

func.apply(null, [1, 2, 3]);

call傳入的參數(shù)數(shù)量不固定,第一個(gè)參數(shù)也是代表了函數(shù)體內(nèi)的this指向,從第二個(gè)參數(shù)開(kāi)始往后,每個(gè)參數(shù)依次被傳入函數(shù):

var func = function(a, b, c){
  console.log([a, b, c]);  // 輸出:[1,2,3]
};

func.call(null, 1, 2, 3);

當(dāng)調(diào)用一個(gè)函數(shù)時(shí),JavaScript的解釋器并不會(huì)計(jì)較形參和實(shí)參在數(shù)量、類型、以及順序上的區(qū)別,JavaScript的參數(shù)在內(nèi)部就是用一個(gè)數(shù)組來(lái)表示的。從這個(gè)意義上說(shuō),apply比call的使用率更高,我們不必關(guān)心具體有多少參數(shù)被傳入函數(shù),只要用apply一股腦地推過(guò)去就可以了。

當(dāng)使用call或apply的時(shí)候,如果我們傳入的第一個(gè)參數(shù)為null,函數(shù)體內(nèi)的this會(huì)指向默認(rèn)的宿主對(duì)象,在瀏覽器中則是window:

var func = function(a, b, c){
  console.log(this);
};

func.apply(null, [1, 2, 3]);  //輸出:window對(duì)象
func.call(null, 1, 2, 3);  //輸出:window對(duì)象
call和apply的用途

改變this指向

Function.prototype.bind

借用其他對(duì)象的方法

1.改變this指向

call和apply最常見(jiàn)的用途是改變函數(shù)內(nèi)部的this指向:

var A = {
  name: "nameA";
};

var B = {
  name: "nameB";
};

window.name = "nameWindow";

var getName = function(){
  conlole.log(this.name);
};

getName();  // 以普通函數(shù)調(diào)用,指向了window對(duì)象,輸出:nameWindow
getName.call(A);  // 改變了this的指向,指向了傳入的對(duì)象,輸出:nameA
getName.call(B);  // 改變了this的指向,指向了傳入的對(duì)象,輸出:nameB

2.Function.prototype.bind

大部分高級(jí)瀏覽器都實(shí)現(xiàn)了內(nèi)置的Function.prototype.bind,用來(lái)指定函數(shù)內(nèi)部的this指向。
若沒(méi)有原生的Function.prototype.bind實(shí)現(xiàn),可以通過(guò)模擬一個(gè):

Function.prototype.bind = function(context){
  var self = this;  // 保存原函數(shù)
  return function(){  // 返回一個(gè)新的函數(shù)
      return self.apply(context, arguments);  // 執(zhí)行新函數(shù)的時(shí)候,會(huì)把之前傳入的context當(dāng)作新函數(shù)體內(nèi)的this
  }
};

var obj = {
 name: "objName"
};

var func = function(){
  console.log(this.name);  // 輸出:objName
}.bind(obj);

func();

我們通過(guò)Function.prototype.bind來(lái)“包裝”func函數(shù),并且傳入一個(gè)對(duì)象context當(dāng)作參數(shù),這個(gè)context對(duì)象就是我們想要修正的this對(duì)象,即讓函數(shù)內(nèi)部的this指向這個(gè)對(duì)象。

3.借用其他對(duì)象的方法

我們知道,杜鵑即不會(huì)筑巢,也不會(huì)孵雛,而是把自己的蛋寄托給云雀等其他鳥(niǎo)類,讓它們代為孵化和養(yǎng)育。在JavaScript中也存在類似的借用現(xiàn)象。

場(chǎng)景一:借用構(gòu)造函數(shù)
通過(guò)這種技術(shù),能夠?qū)崿F(xiàn)一些類似繼承的效果:

var A = function(name){
 this.name = name;
};

var B = function(){  // 借用A的構(gòu)造函數(shù)
  A.apply(this, arguments); 
};

B.prototype.getName = function(){
  return this.name;
};

var b = new B("baby");
console.log(b.getName());  // 輸出:baby

場(chǎng)景二:類數(shù)組對(duì)象的操作
函數(shù)的參數(shù)列表arguments是一個(gè)類數(shù)組對(duì)象,雖然它也有下標(biāo),但它并非真正的數(shù)組,所以也不能像數(shù)組一樣,進(jìn)行排序操作或者往集合里添加一個(gè)新的元素。這時(shí),可以借用Array.prototype對(duì)象上的方法。

比如,想往arguments中添加一個(gè)新的元素,可以借用Array.prototype.push:

(function(){
  Array.prototype.push.call(arguments, 3);
  console.log(arguments); // 輸出:[1,2,3]
})(1, 2);

想把a(bǔ)rguments轉(zhuǎn)成真正的數(shù)組的時(shí)候,可以借用Array.prototype.slice方法;想截去arguments列表中的頭一個(gè)元素時(shí),可以借用Array.prototype.shift方法。

PS:本節(jié)內(nèi)容為《JavaScript設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐》第二章 筆記。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/86139.html

相關(guān)文章

  • JavaScript設(shè)計(jì)模式開(kāi)發(fā)實(shí)踐 - 觀察者模式

    摘要:發(fā)布者的狀態(tài)發(fā)生變化時(shí)就會(huì)通知所有的訂閱者,使得它們能夠自動(dòng)更新自己。觀察者模式的中心思想就是促進(jìn)松散耦合,一為時(shí)間上的解耦,二為對(duì)象之間的解耦。參考設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐第章發(fā)布訂閱模式設(shè)計(jì)模式第章第節(jié)觀察者模式 概述 觀察者模式又叫發(fā)布 - 訂閱模式(Publish/Subscribe),它定義了一種一對(duì)多的關(guān)系,讓多個(gè)觀察者對(duì)象同時(shí)監(jiān)聽(tīng)某一個(gè)目標(biāo)對(duì)象(為了方便理解,以下將觀察者對(duì)象叫...

    xiangzhihong 評(píng)論0 收藏0
  • 學(xué)習(xí)JavaScriptthis,call,apply

    摘要:在全局對(duì)象中調(diào)用,自然讀取的是全局對(duì)象的值構(gòu)造器調(diào)用說(shuō)明作為構(gòu)造器調(diào)用時(shí),指向返回的這個(gè)對(duì)象。最直觀的表現(xiàn)就是,去看一些優(yōu)秀框架的源代碼時(shí),不再是被繞的暈乎乎的。 學(xué)習(xí)起因: 在之前的JavaScript學(xué)習(xí)中,this,call,apply總是讓我感到迷惑,但是他們的運(yùn)用又非常的廣泛。遂專門花了一天,來(lái)弄懂JavaScript的this,call,apply。中途參考的書(shū)籍也很多,以...

    wenhai.he 評(píng)論0 收藏0
  • javascript對(duì)象不完全探索記錄02:瘋狂打call!給誰(shuí)打call?打什么call?

    摘要:注意該方法的作用和方法類似,只有一個(gè)區(qū)別,就是方法接受的是若干個(gè)參數(shù)的列表,而方法接受的是一個(gè)包含多個(gè)參數(shù)的數(shù)組。指定的參數(shù)列表。返回值返回值是你調(diào)用的方法的返回值,若該方法沒(méi)有返回值,則返回。 溫馨提示:作者的爬坑記錄,對(duì)你等大神完全沒(méi)有價(jià)值,別在我這浪費(fèi)生命溫馨提示-續(xù):打call原本是屬于我們偶像宅文化中的專業(yè)名詞,指的是飯們?cè)诳磍ive時(shí)在臺(tái)下配合愛(ài)豆演出的節(jié)奏喊口號(hào),舉例:超...

    Shimmer 評(píng)論0 收藏0
  • JavaScript設(shè)計(jì)模式開(kāi)發(fā)實(shí)踐》讀書(shū)筆記

    摘要:訂閱模式的一個(gè)典型的應(yīng)用就是后面會(huì)寫一篇相關(guān)的讀書(shū)筆記。享元模式享元模式的核心思想是對(duì)象復(fù)用,減少對(duì)象數(shù)量,減少內(nèi)存開(kāi)銷。適配器模式對(duì)目標(biāo)函數(shù)進(jìn)行數(shù)據(jù)參數(shù)轉(zhuǎn)化,使其符合目標(biāo)函數(shù)所需要的格式。 設(shè)計(jì)模式 單例模式 JS的單例模式有別于傳統(tǒng)面向?qū)ο笳Z(yǔ)言的單例模式,js作為一門無(wú)類的語(yǔ)言。使用全局變量的模式來(lái)實(shí)現(xiàn)單例模式思想。js里面的單例又分為普通單例和惰性單例,惰性單例指的是只有這個(gè)實(shí)例...

    Panda 評(píng)論0 收藏0
  • Javascript this 的一些學(xué)習(xí)總結(jié)02【轉(zhuǎn)自cnblogs的JKhuang】

    摘要:發(fā)生這種情況的條件是當(dāng)引用類型值的對(duì)象恰好為活躍對(duì)象。總結(jié)本文介紹中的使用,更重要的是幫助我們能更好地理解值在全局函數(shù)構(gòu)造函數(shù)以及一些特例的情況中值的變化。然而,由于對(duì)于來(lái)說(shuō)沒(méi)有任何意義,因此會(huì)隱式轉(zhuǎn)換為全局對(duì)象。 接上一篇Javascript this 的一些學(xué)習(xí)總結(jié)02【轉(zhuǎn)自cnblogs的JKhuang】 引用類型以及this的null值 對(duì)于前面提及的情形,還有例外的情況,當(dāng)調(diào)...

    suemi 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<