摘要:具體可參考下面代碼定義到原型鏈上的方法這里沒有繼承父類中的方法張三張三太史公曰總結一下與兄弟倆的任務使用一個指定的值和若干個指定的參數值的前提下調用某個函數或方法。本篇人物小傳自此結束。
家族世系在JavaScript中,有這么倆貨,一個叫call,一個叫apply,它們倆工作幾乎一毛一樣,但是也有所區別,曾經對這個知識點非常困惑,看過幾篇博客也沒搞清楚這哥倆到底打算要干個啥,直到某天仔細研究過this關鍵詞的相關知識點后,才恍然大悟,
這篇文章主要就是為call和apply兄弟倆寫“人物傳記”,希望能幫助到其他對這個問題有困惑的童鞋。
在正式介紹這哥倆之前,首先我們得知道兄弟二人到底是誰家的熊孩子,所以有必要熟悉一下哥倆的“家族世系”,刨根問底,以便日后開心地與兄弟二人愉快地玩耍交朋友。
call和apply是被定義到Function.prototype上的兩個方法,也就是Function類型中的原生方法,早在ECMAScript標準的第一個版本中就已經被初步定義,歷史悠久,所以現代瀏覽器幾乎都支持,完全不必擔心兼容性。
call方法與apply方法要實現的功能幾乎一致,就是使用一個指定的this值和若干個指定的參數值的前提下調用某個函數或方法。 兩者只有一個區別,call方法接受的是若干個參數的列表,參數之間以逗號分隔 而apply方法接受的是一個包含多個參數的數組或者偽數組(比如arguments)。
思考以下代碼:
var objA = { x:"value is A", getX:function () { console.log(this.x); } }; var objB={ x:"value is B", getX:function () { console.log(this.x); } }; objA.getX(); //"value is A" objA.getX.call(objB);//"value is B",this被重新綁定到了objB上
上面的代碼很簡單,當objA.getX()被直接調用執行的時候,this理所應當地指向了objA對象,但是當objA.getX.call(objB)被調用執行時,objA.getX中的this被改變,指向了objB。此時因為沒有其他參數要傳入,所以本例中使用call和apply的輸出結果是沒有區別的。
他們區別在于傳遞參數的方式:
var objA = { x: "A", getX: function (val1, val2) { console.log(val1 + val2 + this.x); } }; var objB = { x: "B", getX: function (val1, val2) { console.log(val1 + val2 + this.x); } }; objA.getX.call(objB, "value", "is"); //"value is B" objA.getX.apply(objB, ["value","is"]); //"value is B"
PS:若想了解更多關于this關鍵詞的知識,請閱讀這篇文章
用作類的繼承call與apply方法使用的一個最常見的場景就是在js類的繼承中使用,廢話不多說,直接上代碼:
var Person = function (name, age) { this.name = name; this.age = age; this.sayAge = function () { console.log("Age:" + this.age); }; } var Worker = function (name, age, workerId) { this.workerId = workerId; Person.apply(this, arguments); //apply的第二個參數也可以是偽數組 this.showId = function () { console.log(this.workerId); } } var worker = new Worker("張三", 22, "521608"); worker.sayAge();
需要注意的一點是,使用call和apply方法不能繼承原型鏈,如果要實現原型鏈繼承,則需要混合使用子類原型對象指向父類的實例的方式實現繼承。具體可參考下面代碼
var Person = function (name,age) { this.name = name; this.age = age; this.sayAge = function () { console.log("Age:"+this.age); }; } //定義到原型鏈上的方法 Person.prototype.sayName = function () { console.log("Name:"+this.name); }; var Worker = function (name,age,workerId) { this.workerId= workerId; Person.apply(this,arguments);//這里沒有繼承父類prototype中的方法 } Worker.prototype = new Person(this.name,this.age); Worker.prototype.showId = function () { console.log("ID:",this.workerId); }; var worker = new Worker("張三",22,"521608"); worker.sayAge(); //"Age:22" worker.sayName();//"Name:張三" worker.showId();//"ID: 521608"太史公曰
總結一下call與apply
兄弟倆的任務:
使用一個指定的this值和若干個指定的參數值的前提下調用某個函數或方法。
區別:
call方法接受的是若干個參數的列表,參數之間以逗號分隔 而apply方法接受的是一個包含多個參數的數組或者偽數組(比如arguments)。
本篇人物小傳自此結束。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/90971.html
摘要:系統,扎實的語言基礎是一個優秀的前端工程師必須具備的。第一個參數為調用函數時的指向,隨后的參數則作為函數的參數并調用,也就是。和的區別只有一個,就是它只有兩個參數,而且第二個參數為調用函數時的參數構成的數組。 系統,扎實的 javascript 語言基礎是一個優秀的前端工程師必須具備的。在看了一些關于 call,apply,bind 的文章后,我還是打算寫下這篇總結,原因其實有好幾個。...
摘要:前言實踐系列主要是讓我們通過實踐去加深對一些原理的理解。求求三兄弟的作用都是為了改變函數運行時上下文指向而存在的。不會立即調用其他兩個會立即調用。如果有幫助到你請給我一個就算是對我的感謝啦 前言 [實踐系列] 主要是讓我們通過實踐去加深對一些原理的理解。 實踐系列-前端路由 實踐系列-Babel原理 實踐系列-Promises/A+規范 實踐系列-瀏覽器緩存機制 有興...
摘要:出現箭頭函數的時候,指向為定義時的上下文對象而非指向時,并且不能被改變首先我們先看一個例子由上面的例子我們可以看出來此時指針在用改變了之后指向的依然是全局對象非嚴格瀏覽器環境中是而非。 javascript基礎之this指針 越往后面學越發現基礎的重要性,所以打算重新過一遍基礎,之后出幾個vue和react的實戰教程。ok,嚴歸正傳。 首先什么是this this是執行上下文創建時確定...
摘要:他們的布爾值都是,說到布爾值為的,通常包括空字符串這五種常見的對象。各自都是孤家寡人,不用拖家帶口的,一人吃飽全家不餓。 舉個簡單的栗子: A和B兩個人肚子都很餓,要去吃飯。A已打電話到飯店預約位置,B則打算下班后考察下再做決定。對于飯店來說,A基本上就是他的客戶了,只不過還沒見到人來,定為null(畢竟交易還沒產生),而對飯店來說,B是誰啊,他們根本沒聽到過這個人,為undefine...
摘要:使用構造函數的原型繼承相比使用原型的原型繼承更加復雜,我們先看看使用原型的原型繼承上面的代碼很容易理解。相反的,使用構造函數的原型繼承像下面這樣當然,構造函數的方式更簡單。 五天之前我寫了一個關于ES6標準中Class的文章。在里面我介紹了如何用現有的Javascript來模擬類并且介紹了ES6中類的用法,其實它只是一個語法糖。感謝Om Shakar以及Javascript Room中...
閱讀 2831·2021-11-25 09:43
閱讀 982·2021-10-11 10:57
閱讀 2487·2020-12-03 17:20
閱讀 3731·2019-08-30 14:05
閱讀 2429·2019-08-29 14:00
閱讀 1997·2019-08-29 12:37
閱讀 1670·2019-08-26 11:34
閱讀 3212·2019-08-26 10:27