理解與使用js中的apply()和call()

開(kāi)始看到JavaScript中的apply和call函數(shù)靶溜,非常不解绑谣。也看過(guò)幾篇文章但是一到實(shí)踐用到的時(shí)候又遺忘了。本文結(jié)合實(shí)例搏予,當(dāng)做筆記記錄一下該問(wèn)題與大家分享。

apply:方法能劫持另外一個(gè)對(duì)象的方法葫哗,繼承另外一個(gè)對(duì)象的屬性.(具體是什么意思呢缔刹?我們看看下面的例子就知道啦)

1.apply()和call()基本認(rèn)識(shí)


apply()在w3c手冊(cè)是這樣描述的:

方法重用

通過(guò) apply() 方法,您能夠編寫(xiě)用于不同對(duì)象的方法劣针。

call() 和 apply() 之間的區(qū)別

不同之處是:

call() 方法分別接受參數(shù)校镐。

apply() 方法接受數(shù)組形式的參數(shù)。

如果要使用數(shù)組而不是參數(shù)列表捺典,則 apply() 方法非常方便鸟廓。

簡(jiǎn)單的來(lái)說(shuō),call()apply()的一顆語(yǔ)法糖襟己,作用和 apply() 一樣引谜,同樣可實(shí)現(xiàn)繼承,唯一的區(qū)別就在于call()接收的是參數(shù)列表擎浴,而apply()則接收參數(shù)數(shù)組员咽。

一個(gè)簡(jiǎn)單的實(shí)例,希望大家也可以理解數(shù)據(jù)的關(guān)系贮预,文末還有一個(gè)小問(wèn)題贝室,知道答案的話也就基本理解了apply啦契讲。

2.apply()和call()使用


使用 apply, 你可以繼承其他對(duì)象的方法:

var max = Math.max.apply(null, [1, 2, 3, 4, 5]);
console.log(max); // 輸出5

注意這里apply()的第一個(gè)參數(shù)是null滑频,在非嚴(yán)格模式下捡偏,第一個(gè)參數(shù)為null或者undefined時(shí)會(huì)自動(dòng)替換為指向全局對(duì)象,apply()的第二個(gè)參數(shù)為數(shù)組或類數(shù)組峡迷。

使用call:

var max = Math.max.call(null, 1, 2, 3, 4, 5);
console.log(max); // 輸出5

來(lái)看w3c上的示例:

var person = {
  fullName: function(city, country) {
    return this.firstName + " " + this.lastName + "," + city + "," + country;
  }
}
var person1 = {
  firstName:"John",
  lastName: "Doe"
}
person.fullName.apply(person1, ["Oslo", "Norway"]);
// person.fullName.call(person1, "Oslo", "Norway"); // call

以上代碼的結(jié)果是

image.png
银伟。我們發(fā)現(xiàn) 對(duì)象_person1 _傳遞到了 _person _fullName 方法內(nèi),結(jié)果能說(shuō)明:apply()方法能劫持另外一個(gè)對(duì)象的方法绘搞,繼承另外一個(gè)對(duì)象的屬性.

再看兩個(gè)小例子:

(本例子在vue項(xiàng)目中實(shí)現(xiàn))
例1:


test.vue 頁(yè)面上寫(xiě)一個(gè)按鈕 按鈕點(diǎn)擊觸發(fā) btnclick()彤避,我們可以看到在方法內(nèi)有一個(gè)person類,有一個(gè)student類看杭。對(duì)比控制臺(tái)輸出忠藤,我們可以發(fā)現(xiàn)挟伙。

最后一行''444444'輸出的this楼雹,是vue對(duì)象〖饫可以理解

student內(nèi)的this贮缅,是當(dāng)前student對(duì)象。也可以理解

person內(nèi)的this介却,就是student對(duì)象谴供。 為什么?

原因是因?yàn)樵趕tudent內(nèi)apply的使用Person.apply(this,arguments)齿坷。此時(shí)person.apply把student內(nèi)當(dāng)前對(duì)象劫持并繼承該對(duì)象

apply:方法能劫持另外一個(gè)對(duì)象的方法桂肌,繼承另外一個(gè)對(duì)象的屬性.

btnclick () {
  function Person (name, age) {
    console.log(name, age, '1111111111111') // 控制臺(tái)輸出 jack 24 1111111111111
    console.log(this, '33333333333') // 控制臺(tái)輸出 Student {} "33333333333"
    this.name = name
    this.age = age
  }
  function Student (name, age, grade)  
  {  
    Person.apply(this,arguments)
    console.log(this) // 控制臺(tái)輸出 Student {name: "jack", age: 24}
    console.log(arguments) // 控制臺(tái)輸出 Arguments(3) ["jack", 24, "2年"]
    this.grade = grade;  
  }
  const stu = new Student("jack", 24, "2年")
  console.log(stu, '2222222222') // 控制臺(tái)輸出 Student {name: "jack", age: 24, grade: "2年"} "2222222222"
  console.log(this, '4444444444') // 控制臺(tái)輸出 VueComponent {_uid: 9, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …} "4444444444"
}

?
image

例2:


test.vue 頁(yè)面上寫(xiě)一個(gè)按鈕 按鈕點(diǎn)擊觸發(fā) btnclick2(),我們可以看到在方法內(nèi)只有一個(gè)person類永淌。對(duì)比控制臺(tái)輸出崎场,我們可以發(fā)現(xiàn)。

person內(nèi)的this輸出為當(dāng)前vue對(duì)象遂蛀,與上面對(duì)比的不同之處在于谭跨,例1中的person.apply()是在student內(nèi)使用的,而當(dāng)前例子的person.apply()是在點(diǎn)擊按鈕方法內(nèi)直接觸發(fā)的李滴,所以對(duì)象this也就變成了當(dāng)前對(duì)象this螃宙,即vue實(shí)例。

btnclick2 () {
  function Person (name, age) {
    console.log(name, age, '1111111111111') // 控制臺(tái)輸出 jack 18 1111111111111
    console.log(this, '33333333333')  // VueComponent {_uid: 9, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …} "33333333333"
    this.name = name
    this.age = age
  }
  const params = ["jack", 18]
  Person.apply(this,params)
  console.log(this) // VueComponent {_uid: 9, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …}
}

?
image

補(bǔ)充:


整文件代碼如下所坯,可以看到頁(yè)面還會(huì)輸出name,age,grade谆扎。

    <template>
        <div class="hello">
            <div>
                <button @click="btnclick()">觸發(fā)函數(shù)</button>
                <button @click="btnclick2()">觸發(fā)函數(shù)2</button>
            </div>
            <div>{{ name }}</div>
            <div>{{ age }}</div>
            <div>{{ grade }}</div>
        </div>
    </template>
    <script>
    export default {
    name: 'HelloWorld',
    props: {
        msg: String
    },
    data () {
        return {
            name: '',
            age: '',
            grade: ''
        }
    },
    methods: {
        btnclick () {
        function Person (name, age) {
            console.log(name, age, '1111111111111')
            console.log(this, '33333333333')
            this.name = name
            this.age = age
        }
        function Student (name, age, grade)  
          {  
            Person.apply(this,arguments)
            console.log(this)
            console.log(arguments)
            this.grade = grade;  
          }
          const stu = new Student("jack", 24, "2年")
          console.log(stu, '2222222222')
          console.log(this, '4444444444')
        },
        btnclick2 () {
          function Person (name, age) {
            console.log(name, age, '1111111111111')
            console.log(this, '33333333333')
            this.name = name
            this.age = age
          }
          const params = ["jack", 18]
          Person.apply(this,params)
          console.log(this)
        }
      }
    }
    </script>

    <style scoped>

    </style>

問(wèn):為什么點(diǎn)擊第一個(gè)按鈕時(shí),頁(yè)面無(wú)變化芹助。點(diǎn)擊第二個(gè)按鈕時(shí)堂湖,頁(yè)面顯示name籍凝,age?

image

如何選用:

  • 如果不需要關(guān)心具體有多少參數(shù)被傳入函數(shù)苗缩,選用apply()
  • 如果確定函數(shù)可接收多少個(gè)參數(shù)饵蒂,并且想一目了然表達(dá)形參和實(shí)參的對(duì)應(yīng)關(guān)系,用call()

總結(jié)

  • call()apply()都是用來(lái)改變函數(shù)執(zhí)行時(shí)的上下文酱讶,可借助它們實(shí)現(xiàn)繼承退盯;
  • call()apply()唯一區(qū)別是參數(shù)不一樣,call()是apply()的語(yǔ)法糖

這兩個(gè)方法很好地體現(xiàn)了js函數(shù)式語(yǔ)言特性泻肯,在js中幾乎每一次編寫(xiě)函數(shù)式語(yǔ)言風(fēng)格的代碼渊迁,都離不開(kāi)call和apply,能夠熟練運(yùn)用它們灶挟,是真正成為一名jser程序員的重要一步琉朽。

本文在本人原始地址: 超人思否

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市稚铣,隨后出現(xiàn)的幾起案子箱叁,更是在濱河造成了極大的恐慌,老刑警劉巖惕医,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件耕漱,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡抬伺,警方通過(guò)查閱死者的電腦和手機(jī)螟够,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)峡钓,“玉大人妓笙,你說(shuō)我怎么就攤上這事∧苎遥” “怎么了寞宫?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)捧灰。 經(jīng)常有香客問(wèn)我淆九,道長(zhǎng),這世上最難降的妖魔是什么毛俏? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任炭庙,我火速辦了婚禮,結(jié)果婚禮上煌寇,老公的妹妹穿的比我還像新娘焕蹄。我一直安慰自己,他們只是感情好阀溶,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布腻脏。 她就那樣靜靜地躺著鸦泳,像睡著了一般。 火紅的嫁衣襯著肌膚如雪永品。 梳的紋絲不亂的頭發(fā)上做鹰,一...
    開(kāi)封第一講書(shū)人閱讀 51,125評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音鼎姐,去河邊找鬼钾麸。 笑死,一個(gè)胖子當(dāng)著我的面吹牛炕桨,可吹牛的內(nèi)容都是我干的饭尝。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼献宫,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼钥平!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起姊途,我...
    開(kāi)封第一講書(shū)人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤涉瘾,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后吭净,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體睡汹,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年寂殉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片原在。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡友扰,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出庶柿,到底是詐尸還是另有隱情村怪,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布浮庐,位于F島的核電站甚负,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏审残。R本人自食惡果不足惜梭域,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望搅轿。 院中可真熱鬧病涨,春花似錦、人聲如沸璧坟。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至幻工,卻和暖如春励两,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背囊颅。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工伐蒋, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人迁酸。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓先鱼,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親奸鬓。 傳聞我的和親對(duì)象是個(gè)殘疾皇子焙畔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353