成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

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

darryrzhong / 1072人閱讀

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

this

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

this的指向

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

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

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

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

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

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

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

// 聲明obj對象
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ù)不作為對象的屬性被調(diào)用時,也就是以普通函數(shù)方式,this指向全局對象。在瀏覽器的JavaScript里,全局對象是window對象。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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 可以動態(tài)地改變傳入函數(shù)的this。

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

var B = {
    name: "ObjectB"
};

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

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

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

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

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

ECAMScript3給Function的原型定義了兩個方法,分別是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接受兩個參數(shù),第一個參數(shù)制定了函數(shù)體內(nèi)this對象的指向,第二個函數(shù)為一個帶下標(biāo)的集合,這個集合可以是數(shù)組,也可以是類數(shù)組。apply方法把這個集合中的元素作為參數(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ù)量不固定,第一個參數(shù)也是代表了函數(shù)體內(nèi)的this指向,從第二個參數(shù)開始往后,每個參數(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)用一個函數(shù)時,JavaScript的解釋器并不會計較形參和實參在數(shù)量、類型、以及順序上的區(qū)別,JavaScript的參數(shù)在內(nèi)部就是用一個數(shù)組來表示的。從這個意義上說,apply比call的使用率更高,我們不必關(guān)心具體有多少參數(shù)被傳入函數(shù),只要用apply一股腦地推過去就可以了。

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

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

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

改變this指向

Function.prototype.bind

借用其他對象的方法

1.改變this指向

call和apply最常見的用途是改變函數(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對象,輸出:nameWindow
getName.call(A);  // 改變了this的指向,指向了傳入的對象,輸出:nameA
getName.call(B);  // 改變了this的指向,指向了傳入的對象,輸出:nameB

2.Function.prototype.bind

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

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

var obj = {
 name: "objName"
};

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

func();

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

3.借用其他對象的方法

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

場景一:借用構(gòu)造函數(shù)
通過這種技術(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

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

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

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

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

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

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

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/86139.html

相關(guān)文章

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

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

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

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

    wenhai.he 評論0 收藏0
  • javascript對象不完全探索記錄02:瘋狂打call!給誰打call?打什么call

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

    Shimmer 評論0 收藏0
  • JavaScript設(shè)計模式開發(fā)實踐》讀書筆記

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

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

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

    suemi 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<