摘要:剩下的兩個(gè),我們分別改變了他們的執(zhí)行環(huán)境,分別指向了和,于是結(jié)果就是顯示對(duì)象各自的值。如果你仍然對(duì)和沒(méi)有清晰的認(rèn)識(shí),可以試著這樣理解。
在Javascript中,每個(gè)函數(shù)都包含兩個(gè)非繼承而來(lái)的方法,call和apply。這兩個(gè)方法的用途都是在特定的作用域中調(diào)用函數(shù),實(shí)際上等于設(shè)置函數(shù)體內(nèi)的this對(duì)象的值。
摘自《JavaScript高級(jí)程序設(shè)計(jì)》
apply方法接收兩個(gè)參數(shù),第一個(gè)參數(shù)是在其中運(yùn)行函數(shù)的作用域,第二個(gè)是一個(gè)參數(shù)數(shù)組或者arguments對(duì)象。
call方法與apply方法作用相同,第一個(gè)參數(shù)也相同,區(qū)別在于,其余的參數(shù)需要逐個(gè)列出。
apply(thisArg, argArray); call(thisArg[,arg1,arg2…]);
是使用call還是apply要看具體的情況。如果你知道所有參數(shù)或者參數(shù)的數(shù)量不多,可以使用call;如果參數(shù)的數(shù)量不確定,或者數(shù)量很大,或者你收到的是一個(gè)數(shù)組或者是個(gè)arguments對(duì)象,則需要使用apply。
下面是使用apply的一些典型例子
// 獲得數(shù)組中最大的元素 var arr = [1, 8, 10, 3, 24, 89, 26]; var m = Math.max.apply(Math, arr); // m => 89 // 將類數(shù)組的對(duì)象轉(zhuǎn)為數(shù)組 var arr = Array.prototype.slice.call(arguments);
事實(shí)上,call和apply真正的用武之地在于,他們能夠擴(kuò)充函數(shù)賴以運(yùn)行的作用域。
我們?cè)賮?lái)看下面的例子
var name = "out" var o1 = { name: "hello" }; var o2 = { name: "world" }; function sayName() { alert(this.name); } sayName.call(this); // out sayName.call(window); // out sayName.call(o1); // hello sayName.call(o2); // world
前兩個(gè)輸出相同,因?yàn)樵谌肿饔糜?,this即為window(瀏覽器環(huán)境)。
剩下的兩個(gè),我們分別改變了他們的執(zhí)行環(huán)境,分別指向了o1和o2,于是結(jié)果就是顯示對(duì)象各自的name值。
那么,使用call和apply有什么好處呢?我們發(fā)現(xiàn),同樣的一個(gè)函數(shù),當(dāng)指定不同的執(zhí)行環(huán)境時(shí),會(huì)產(chǎn)生不同的結(jié)果,這么做的一個(gè)最大的好處就是解耦。
使用call和apply,函數(shù)和對(duì)象沒(méi)有強(qiáng)依賴關(guān)系,多個(gè)對(duì)象可以使用同一個(gè)函數(shù),避免了資源的浪費(fèi),同時(shí)對(duì)于模塊化編程也大有幫助。
如果你仍然對(duì)call和apply沒(méi)有清晰的認(rèn)識(shí),可以試著這樣理解。
我們把方法比作是工具,比如一把刀;而變量是具體的實(shí)物,比如一個(gè)蘋果。我們可以使用這把刀切很多不同的蘋果,在切蘋果的過(guò)程中,實(shí)際上就是改變了刀的作用對(duì)象---不同的蘋果。
在上面的例子
// 將類數(shù)組的對(duì)象轉(zhuǎn)為數(shù)組 var arr = Array.prototype.slice.call(arguments);
slice是一個(gè)方法,但是它是屬于Array對(duì)象prototype屬性所有的,在對(duì)arguments使用時(shí),我們可以理解為借用。
比如張三會(huì)砍樹,即張三有砍樹這個(gè)方法(至于張三有沒(méi)有樹無(wú)所謂),而李四有樹,但他卻不會(huì)砍,這時(shí)李四便可以借用張三砍樹的方法來(lái)砍自己的樹,寫成代碼就是
var zhangsan = { cut: function() { alert(this.tree); } }; var lisi = { tree: "楊樹" }; zhangsan.cut.call(lisi); // alert("楊樹")
還有一種情況是,李四自己也會(huì)砍樹,但是有一天他病了,砍不動(dòng)了,這時(shí)他也可以借用張三的砍樹方法砍自己的樹。在代碼中就是
String.prototype.toString = function() { return "shit"; // 所有的String的實(shí)例對(duì)象的toString方法都被污染了,只會(huì)輸出"shit" }; var str = "hello"; console.log(str.toString()); // "shit" // 這時(shí)候怎么辦呢? // 我們需要找一個(gè)沒(méi)被污染的toString方法借來(lái)用一用,比如Object(或者Array等除了String的都可以) console.log(Object.prototype.toString.call(str)); // 輸出正常的"[object String]"
到了這里,相信你對(duì)call和apply已經(jīng)有了一個(gè)比較形象的認(rèn)識(shí)了。以后再遇到類似的問(wèn)題時(shí),不妨想象成現(xiàn)實(shí)中的關(guān)系,可能困擾許久的問(wèn)題就豁然開朗了。
call和apply另外一個(gè)應(yīng)用就是函數(shù)的柯里化和反柯里化技術(shù),有興趣的可以看下面兩篇文章
Javascript中有趣的反柯里化技術(shù)
由JavaScript反柯里化所想到的
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/87568.html
摘要:理解文章中已經(jīng)比較全面的分析了在中的指向問(wèn)題,用一句話來(lái)總結(jié)就是的指向一定是在執(zhí)行時(shí)決定的,指向被調(diào)用函數(shù)的對(duì)象。與和直接執(zhí)行原函數(shù)不同的是,返回的是一個(gè)新函數(shù)。這個(gè)新函數(shù)包裹了原函數(shù),并且綁定了的指向?yàn)閭魅氲摹? 理解 JavaScript this 文章中已經(jīng)比較全面的分析了 this 在 JavaScript 中的指向問(wèn)題,用一句話來(lái)總結(jié)就是:this 的指向一定是在執(zhí)行時(shí)決定的,...
摘要:可能上面的例子不是很常見,但是我們經(jīng)常見到這樣的代碼你好美女你好美女方法是數(shù)組特有的方法,它是定義在構(gòu)造函數(shù)的原型中的方法,所以我們實(shí)例化的數(shù)組就都繼承了這個(gè)方法,但是字符串是沒(méi)有方法,但此處我們就借用了數(shù)組的方法來(lái)處理字符串。 ??在學(xué)習(xí)javascript的時(shí)候,對(duì)于call()和apply()的用法總是難以理解,相信很多小伙伴和我又一樣的想法?,F(xiàn)在和小伙伴們分享一下。 call ...
摘要:,,和都是用來(lái)改變函數(shù)執(zhí)行時(shí)的上下文也就是說(shuō)改變的指向問(wèn)題,是的方法,引入是因?yàn)闆](méi)有將設(shè)置成行參。一般都是庫(kù)里面用不推薦自己使用和。和唯一區(qū)別是參數(shù)不一樣,是的語(yǔ)法糖是返回一個(gè)新函數(shù)供以后調(diào)用,相比其他兩個(gè)比較常用。而和是立即調(diào)用。 apply(),call(),和bind()都是用來(lái)改變函數(shù)執(zhí)行時(shí)的上下文也就是說(shuō)改變this的指向問(wèn)題,是prototype的方法,引入是因?yàn)閖s沒(méi)有將...
摘要:輸出的作用與和一樣,都是可以改變函數(shù)運(yùn)行時(shí)上下文,區(qū)別是和在調(diào)用函數(shù)之后會(huì)立即執(zhí)行,而方法調(diào)用并改變函數(shù)運(yùn)行時(shí)上下文后,返回一個(gè)新的函數(shù),供我們需要時(shí)再調(diào)用。 前言 js中的call(), apply()和bind()是Function.prototype下的方法,都是用于改變函數(shù)運(yùn)行時(shí)上下文,最終的返回值是你調(diào)用的方法的返回值,若該方法沒(méi)有返回值,則返回undefined。這幾個(gè)方法...
摘要:在全局對(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。中途參考的書籍也很多,以...
閱讀 881·2021-11-22 09:34
閱讀 1017·2021-10-08 10:16
閱讀 1832·2021-07-25 21:42
閱讀 1799·2019-08-30 15:53
閱讀 3531·2019-08-30 13:08
閱讀 2190·2019-08-29 17:30
閱讀 3352·2019-08-29 17:22
閱讀 2184·2019-08-29 15:35