国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

Javascript中call和apply函數的比較和使用實例

2019-11-20 13:14:43
字體:
來源:轉載
供稿:網友

一些簡單的Javascript操作中較少會用到call和apply函數,在另外一些較大型的操作中,如web應用開發,js框架開發中可能會經常遇到這兩個函數。關于這兩個函數的解釋,網上的資料也很多,但是本人認為很多資料要么照本宣科,要么高度雷同,缺少接地氣的解釋。接下來我試圖用更加清晰簡單的思路來分析解釋這兩個函數。

復制代碼 代碼如下:

我們可以將call()和apply()看做是某個對象的方法,通過調用方法的實行來間接調用函數。call()和apply()的第一個實參是要調用函數的母對象,它是調用上下文,在函數體內通過this來獲得對它的引用。要想對對象o的方法來調用函數f(), 可以這樣使用call()和apply(): f.call(o) f.apply(o).[1]

先來分析一下call,這里有ECMAScript 3rd Edition對call函數的解釋[2]:當call方法被一個function對象調用時(func.call(0)),需要傳入一個必須的參數和若干個非必須的參數,它的執行過程是這樣的:
a, 如果調用call的對象是不可運行的,拋出一個TypeError錯誤。
b, 設置參數列表為空
c, 如果被調用的方法傳入不止一個參數,那么依次把arg1,arg2…插入到參數列表里
d, 返回調用call的函數結果,把調用函數(func)中的this用傳入的參數1替換,把傳入的參數列表當作這個函數的參數。
實際上,call函數是function對象的原型,也就是說,當調用call的函數必須也是個函數,當調用這個call時,把調用call的函數中的this用傳入的對象替換就行了。下面有個例子:

<script> function C1(){ this.name='張三'; this.age='24'; this.sayname=function(){  console.log("這里是C1類,我的名字是:"+this.name+"我的年齡是"+this.age); } } function C2(){ this.name='李四'; this.age='25'; } var c1=new C1(); var c2=new C2(); c1.sayname(); c1.sayname.call(c2);</script>

執行結果:
這里是C1類,我的名字是:張三我的年齡是24
這里是C1類,我的名字是:李四我的年齡是25
上面的代碼中,聲明了兩個類,C1和C2,C1有兩個屬性,一個方法,C2也有兩個和C1一樣的屬性,實例化之后,c1.sayname()打印出了實際屬性,c1.sayname.call(c2)卻打印除了c2的屬性,為什么為這樣?因為sayname()是個函數,并且函數體內有this,當call執行的之后,this就會被c2代替,所以,最終會打印出c2的屬性。
apply和call的區別就在于可選參數的傳遞,apply的可選參數全部存放在一個數組當中,當成一個參數竄入而call是分成多個參數傳入。
那么,apply和call函數有哪些應用呢?第一個是網絡上比較經典的求數字數組中的最大元素,直接用Math.max.apply(null,array)即可,另外一個是可以用apply和call實現繼承,如下:

<script>  function Human(name,sex){ this.name=name; this.sex=sex; this.walk=function(){  console.log('我在走路'); } } function Child(){ Human.call(this,"小明","男") this.paly=function(){  console.log('我很喜歡玩耍'); } this.intruduce=function(){  console.log('大家好,我是'+this.name); } } var jinp=new Human('Jack','男'); var xiaoping=new Child(); xiaoping.walk(); xiaoping.paly(); xiaoping.intruduce();</script>

執行結果:
我在走路
我很喜歡玩耍
大家好,我是小明
與call()和apply()相似的函數是bind(), 它是在ECMAScript 5中新增的方法,但在ECMAScript 3中可以輕易的模擬bind()。bind函數一樣也是Javascript中Function.prototype的方法,這個方法的主要內容是將函數綁定至某個對象。當函數f()上綁定bind()方法并傳入一個對象o作為參數,這個方法將返回一個新的函數當作o的方法來調用。傳入新函數的任何實參都將傳入原始函數。如下:

<script> function introduce(country,hobby){ return "大家好,我叫"+this.name+", 今年"+this.age+"歲, 來自"+country+", 喜歡"+hobby; } var xiaoming={name:"小明",age:20} var jieshao=introduce.bind(xiaoming); console.log(jieshao("中國","打球"));</script>

執行結果:
大家好,我叫小明, 今年20歲, 來自中國, 喜歡打球
上面的例子等效于:

<script> function introduce(country,hobby){ return "大家好,我叫"+this.name+", 今年"+this.age+"歲, 來自"+country+", 喜歡"+hobby; } var xiaoming={name:"小明",age:20} console.log(introduce.apply(xiaoming,["中國","打球"]));    //或者下面這個 console.log(introduce.call(xiaoming,"中國","打球"));</script>

需要注意的是:在ECMAScript 5的嚴格模式中,call()和apply()的第一個實參都會變成this的值,哪怕傳入的實參是原始值甚至是null或者undefined。在ECMAScript 3和非嚴格模式中,傳入的null和undefined都會被全局對戲那個代替,而其他原始值會被相應的包裝對象所替代。

參考資料

[1], Javascript權威指南第6版,189頁
[2], Function.prototype.call (thisArg [ , arg1 [ , arg2, … ] ] )
[3], Function.prototype.apply (thisArg, argArray)

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 商南县| 克拉玛依市| 茌平县| 绥江县| 库尔勒市| 望都县| 肥城市| 仪征市| 沙田区| 桦甸市| 屏南县| 朔州市| 哈密市| 浦江县| 蒙阴县| 讷河市| 北辰区| 庆阳市| 双峰县| 彰化市| 额济纳旗| 勐海县| 遂平县| 宁强县| 南宫市| 北安市| 黎川县| 独山县| 兴和县| 广丰县| 金华市| 慈溪市| 双柏县| 酉阳| 和平县| 平舆县| 苍山县| 淮滨县| 离岛区| 中卫市| 尼玛县|