摘要:在全局環(huán)境中調(diào)用函數(shù)是不會(huì)生成此屬性,因?yàn)椴环洗藢傩缘拇嬖谝饬x價(jià)值見上條。函數(shù)遞歸時(shí)用起來(lái)比用函數(shù)名調(diào)用函數(shù)更帶感方法這倆方法性質(zhì)一樣,只是用法稍有不同,因此放在一起來(lái)介紹。
javascript的Function中有不少不那么常用,又或者用了也是知其然而不知其所以然的屬性/方法,本文就來(lái)談?wù)勥@一系列屬性/方法:caller/callee/apply/call/bind。
caller屬性直接上DEMO比較好理解:
// caller demo { function callerDemo() { if (callerDemo.caller) { var a = callerDemo.caller.toString(); console.log(a); } else { console.log("this is a top function"); } } function handleCaller() { callerDemo(); } handleCaller(); //"function handleCaller() { callerDemo(); }" callerDemo(); //"this is a top function"
我們先來(lái)按照思路一步一步來(lái)看這段代碼:
首先我們看到定義了倆function:handleCaller和callerDemo,并且還可以看出handleCaller函數(shù)里是調(diào)用了callerDemo函數(shù)的。
在callerDemo函數(shù)里,我們看到了本文介紹的主角之一:caller屬性,并且可以看出這caller屬性是函數(shù)對(duì)象本身的一個(gè)成員屬性。
在callerDemo函數(shù)里,有一段判斷caller屬性是否存在的代碼,這段代碼有什么意義呢?這就要看最后的結(jié)果了:直接調(diào)用callerDemo()發(fā)現(xiàn)此時(shí)callerDemo.caller是為空的,而反觀通過(guò)調(diào)用handleCaller()并在其內(nèi)部調(diào)用callerDemo()則callerDemo.caller不為空。這說(shuō)明只有在函數(shù)里調(diào)用函數(shù),才會(huì)生成caller屬性,而直接在全局環(huán)境里調(diào)用函數(shù)則不會(huì)生成。
繼續(xù)看var a = callerDemo.caller.toString();console.log(a);,這里打印出來(lái)的居然是handleCaller整個(gè)函數(shù)體,這說(shuō)明,此時(shí)的callerDemo.caller實(shí)際上就是對(duì)于handleCaller這個(gè)函數(shù)對(duì)象的一個(gè)引用。
這么分析下來(lái),caller屬性就很容易明白了:
caller屬性是幫助我們?cè)诋?dāng)前函數(shù)里獲取調(diào)用當(dāng)前函數(shù)的某個(gè)未知函數(shù),之所以稱未知函數(shù),是因?yàn)槲覀冊(cè)趯懸粋€(gè)函數(shù)時(shí),很可能根本不知道哪個(gè)函數(shù)會(huì)調(diào)用到我們的這個(gè)函數(shù)。
在全局環(huán)境中調(diào)用函數(shù)是不會(huì)生成此caller屬性,因?yàn)椴环洗藢傩缘拇嬖谝饬x/價(jià)值(見上條)。
只有在當(dāng)前函數(shù)的內(nèi)部(上下文環(huán)境)才能調(diào)用當(dāng)前函數(shù)的caller屬性,不能從外部調(diào)用。
callee屬性還是先放代碼:
function calleeDemo() { console.log(arguments.callee); }
有了上文對(duì)caller屬性的認(rèn)知,callee屬性就很好理解了,它實(shí)際上就是對(duì)當(dāng)前函數(shù)對(duì)象的一個(gè)引用。有以下的點(diǎn)需要注意:
callee屬性隸屬于Function的一個(gè)隱藏對(duì)象——arguments中,這個(gè)arguments對(duì)象大家應(yīng)該不陌生,表示的就是當(dāng)前函數(shù)傳入的參數(shù),一般用于函數(shù)不限制參數(shù)數(shù)量的傳參。
與caller屬性一樣,也是要在當(dāng)前函數(shù)的內(nèi)部(上下文環(huán)境)才有效。
可配合caller屬性一起使用:arguments.callee.caller,這樣就可以完全忽略到具體的函數(shù)名了。
函數(shù)遞歸時(shí)用起來(lái)比用函數(shù)名調(diào)用函數(shù)更帶感!
apply/call方法這倆方法性質(zhì)一樣,只是用法稍有不同,因此放在一起來(lái)介紹。還記得我上一篇文章《javascript如何判斷變量的數(shù)據(jù)類型》中介紹的利用Object.prototype.toString.call來(lái)判斷數(shù)據(jù)類型的方法么:
function type(obj) { return Object.prototype.toString.call(obj).slice(8, -1); //換成用apply方法亦可 }
apply/call方法的意義在于借用其它對(duì)象的成員方法來(lái)對(duì)目標(biāo)對(duì)象執(zhí)行操作。
在借用的過(guò)程中,apply/call方法會(huì)改變被借用的成員方法的上下文環(huán)境:把this這一與上下文環(huán)境高度相關(guān)的變量指向目標(biāo)對(duì)象,而非原來(lái)的對(duì)象。看下面的這段代碼:
function Point(x, y){ this.x = x; this.y = y; } Point.prototype.move = function(x, y) { this.x += x; this.y += y; } var p = new Point(0,0); var circle = {x:1, y:1, r:1}; //只是一個(gè)普通的Object對(duì)象 p.move.call(circle, 2, 1); //借用了Point類對(duì)象中的move方法 //p.move.apply(circle, [2, 1]); //等價(jià)于p.move.call(circle, 2, 1);
這里的circle只是一個(gè)普通的Object對(duì)象,不含任何自定義的成員方法,但通過(guò)apply/call方法,可以借用Point類對(duì)象定義的move方法來(lái)幫助circle達(dá)到目的(本例其實(shí)是圓心在坐標(biāo)軸上的移動(dòng))。在借用Point類對(duì)象的move方法時(shí),move方法中的this就不再指向p,而是指向circle了,達(dá)到了上下文環(huán)境改變的效果。
另外,從代碼里也可以看出,call方法與apply方法的區(qū)別僅在于:call方法直接把需要傳入的參數(shù)列在目標(biāo)對(duì)象其后,而apply方法則以數(shù)組的形式整體傳入。
bind方法與apply/call方法也非常類似,相當(dāng)于稍微再封裝了一下,仍以上述DEMO作為案例:
function Point(x, y){ this.x = x; this.y = y; } Point.prototype.move = function(x, y) { this.x += x; this.y += y; } var p = new Point(0,0); var circle = {x:1, y:1, r:1}; // p.move.call(circle, 2, 1); // p.move.apply(circle, [2, 1]); var circleMove = p.move.bind(circle, 2, 1); //此時(shí)并不執(zhí)行move方法 circleMove(); //此時(shí)才執(zhí)行
從上面這段DEMO可以看出,bind方法其實(shí)是給apply/call方法緩了一下,也可以說(shuō)是封裝了一下方便后續(xù)調(diào)用,其實(shí)質(zhì)上相當(dāng)于下面的這段代碼:
function circleMove() { p.move.call(circle, 2, 1); } circleMove();bind方法兼容性適應(yīng)
bind方法,即Function.prototype.bind,屬于ECMAScript 5,IE從IE 10版本才開始支持,那怎么做兼容性適應(yīng)呢?
if(typeof Function.prototype.bind !== "function") { Function.prototype.bind = function() { var thatFunc = this; var args = []; for(var i = 0; i < arguments.length; i++) { args[i] = arguments[i]; } return function() { var context = args.shift(); thatFunc.apply(context, args); } } }
其思路是利用apply方法來(lái)封裝成bind方法。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/78508.html
嚴(yán)格模式 首先來(lái)了解一下嚴(yán)格模式是什么?嚴(yán)格模式是JavaScript中的一種限制性更強(qiáng)的變種方式,不是一個(gè)子集:它在語(yǔ)義上與正常代碼有明顯的差異,不支持嚴(yán)格模式的瀏覽器與支持嚴(yán)格模式的瀏覽器行為上也不一樣,所以不要在未經(jīng)嚴(yán)格模式特性測(cè)試情況下使用嚴(yán)格模式,嚴(yán)格模式可以與非嚴(yán)格模式共存,所以腳本可以逐漸的選擇性加入嚴(yán)格模式 嚴(yán)格模式的目的 首先,嚴(yán)格模式會(huì)將JavaScript陷阱直接變成明顯的錯(cuò)...
摘要:基本語(yǔ)法默認(rèn)值,將溢出的文本裁減掉將溢出的文本用省略號(hào)來(lái)表示設(shè)置一個(gè)字符串用來(lái)表示溢出的文本兼容性上,除了外,其余兩個(gè)屬性兼容到了,所以大可放心使用。 原文地址:https://www.xksblog.top/the-p... text-overflow是CSS3中的屬性,它規(guī)定了當(dāng)文本溢出其包含元素時(shí)以何種方式顯示。但在使用的時(shí)候,有時(shí)會(huì)發(fā)現(xiàn)這個(gè)text-overflow設(shè)置了屬性...
摘要:例如本地函數(shù)的局部變量和參數(shù)當(dāng)前嵌套調(diào)用鏈上的其他函數(shù)的變量和參數(shù)全局變量還有一些其他的,內(nèi)部的這些值稱為根。例如,如果局部變量中有對(duì)象,并且該對(duì)象具有引用另一個(gè)對(duì)象的屬性,則該對(duì)象被視為可達(dá)性,它引用的那些也是可以訪問的,詳細(xì)的例子如下。 最近看到一些面試的回顧,不少有被面試官問到談?wù)凧S 垃圾回收機(jī)制,說(shuō)實(shí)話,面試官會(huì)問這個(gè)問題,說(shuō)明他最近看到一些關(guān)于 JS 垃圾回收機(jī)制的相關(guān)的文...
摘要:在如今的前端框架界,三分天下的時(shí)代已經(jīng)到來(lái),而曾經(jīng)一統(tǒng)天下的局面已一去不復(fù)返。三分天下,前端雖亂,但美其名曰繁榮。那些小事俗話說(shuō)千里之堤毀于蟻穴,在開發(fā)中我們不能忙于進(jìn)度而忽視了細(xì)節(jié)。 前言 說(shuō)起React,那也是近一年多時(shí)間火起來(lái)的前端框架,其在Facebook的影響力和大力推廣下,已然成為目前前端界的中流砥柱。在如今的前端框架界,React、Vue、Angular三分天下的時(shí)代已經(jīng)...
摘要:一般情況下是全局對(duì)象。避免在頁(yè)面的主體布局中使用,要等其中的內(nèi)容完全下載之后才會(huì)顯示出來(lái),顯示布局慢。對(duì)普通的網(wǎng)站有一個(gè)統(tǒng)一的思路,就是盡量向前端優(yōu)化減少數(shù)據(jù)庫(kù)操作減少磁盤。 HTML面試題 1.XHTML和HTML有什么區(qū)別 HTML是一種基本的WEB網(wǎng)頁(yè)設(shè)計(jì)語(yǔ)言,XHTML是一個(gè)基于XML的置標(biāo)語(yǔ)言最主要的不同: XHTML 元素必須被正確地嵌套。 XHTML 元素必須被關(guān)閉。...
閱讀 2671·2023-04-25 18:10
閱讀 1606·2019-08-30 15:53
閱讀 2788·2019-08-30 13:10
閱讀 3216·2019-08-29 18:40
閱讀 1128·2019-08-23 18:31
閱讀 1201·2019-08-23 16:49
閱讀 3400·2019-08-23 16:07
閱讀 877·2019-08-23 15:27