国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

談談javascript的Function中那些隱藏的屬性/方法:caller/callee/app

shery / 1725人閱讀

摘要:在全局環境中調用函數是不會生成此屬性,因為不符合此屬性的存在意義價值見上條。函數遞歸時用起來比用函數名調用函數更帶感方法這倆方法性質一樣,只是用法稍有不同,因此放在一起來介紹。

javascript的Function中有不少不那么常用,又或者用了也是知其然而不知其所以然的屬性/方法,本文就來談談這一系列屬性/方法: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"

我們先來按照思路一步一步來看這段代碼:

首先我們看到定義了倆function:handleCaller和callerDemo,并且還可以看出handleCaller函數里是調用了callerDemo函數的。

在callerDemo函數里,我們看到了本文介紹的主角之一:caller屬性,并且可以看出這caller屬性是函數對象本身的一個成員屬性。

在callerDemo函數里,有一段判斷caller屬性是否存在的代碼,這段代碼有什么意義呢?這就要看最后的結果了:直接調用callerDemo()發現此時callerDemo.caller是為空的,而反觀通過調用handleCaller()并在其內部調用callerDemo()則callerDemo.caller不為空。這說明只有在函數里調用函數,才會生成caller屬性,而直接在全局環境里調用函數則不會生成。

繼續看var a = callerDemo.caller.toString();console.log(a);,這里打印出來的居然是handleCaller整個函數體,這說明,此時的callerDemo.caller實際上就是對于handleCaller這個函數對象的一個引用。

這么分析下來,caller屬性就很容易明白了:

caller屬性是幫助我們在當前函數里獲取調用當前函數的某個未知函數,之所以稱未知函數,是因為我們在寫一個函數時,很可能根本不知道哪個函數會調用到我們的這個函數。

在全局環境中調用函數是不會生成此caller屬性,因為不符合此屬性的存在意義/價值(見上條)。

只有在當前函數的內部(上下文環境)才能調用當前函數的caller屬性,不能從外部調用。

callee屬性

還是先放代碼:

function calleeDemo() { 
    console.log(arguments.callee); 
} 

有了上文對caller屬性的認知,callee屬性就很好理解了,它實際上就是對當前函數對象的一個引用。有以下的點需要注意:

callee屬性隸屬于Function的一個隱藏對象——arguments中,這個arguments對象大家應該不陌生,表示的就是當前函數傳入的參數,一般用于函數不限制參數數量的傳參。

caller屬性一樣,也是要在當前函數的內部(上下文環境)才有效。

可配合caller屬性一起使用:arguments.callee.caller,這樣就可以完全忽略到具體的函數名了。

函數遞歸時用起來比用函數名調用函數更帶感!

apply/call方法

這倆方法性質一樣,只是用法稍有不同,因此放在一起來介紹。還記得我上一篇文章《javascript如何判斷變量的數據類型》中介紹的利用Object.prototype.toString.call來判斷數據類型的方法么:

function type(obj) {
  return Object.prototype.toString.call(obj).slice(8, -1);    //換成用apply方法亦可
}

apply/call方法的意義在于借用其它對象的成員方法來對目標對象執行操作。

借用的過程中,apply/call方法會改變被借用的成員方法的上下文環境:把this這一與上下文環境高度相關的變量指向目標對象,而非原來的對象。看下面的這段代碼:

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};    //只是一個普通的Object對象
p.move.call(circle, 2, 1);    //借用了Point類對象中的move方法
//p.move.apply(circle, [2, 1]);    //等價于p.move.call(circle, 2, 1);

這里的circle只是一個普通的Object對象,不含任何自定義的成員方法,但通過apply/call方法,可以借用Point類對象定義的move方法來幫助circle達到目的(本例其實是圓心在坐標軸上的移動)。在借用Point類對象的move方法時,move方法中的this就不再指向p,而是指向circle了,達到了上下文環境改變的效果。
另外,從代碼里也可以看出,call方法與apply方法的區別僅在于:call方法直接把需要傳入的參數列在目標對象其后,而apply方法則以數組的形式整體傳入。

bind方法

bind方法與apply/call方法也非常類似,相當于稍微再封裝了一下,仍以上述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);    //此時并不執行move方法
circleMove();    //此時才執行

從上面這段DEMO可以看出,bind方法其實是給apply/call方法緩了一下,也可以說是封裝了一下方便后續調用,其實質上相當于下面的這段代碼:

function circleMove() {
    p.move.call(circle, 2, 1);
}
circleMove();
bind方法兼容性適應

bind方法,即Function.prototype.bind,屬于ECMAScript 5,IE從IE 10版本才開始支持,那怎么做兼容性適應呢?

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方法來封裝成bind方法。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/78508.html

相關文章

  • 談談JavaScript嚴格模式你應該遵守那些

    嚴格模式 首先來了解一下嚴格模式是什么?嚴格模式是JavaScript中的一種限制性更強的變種方式,不是一個子集:它在語義上與正常代碼有明顯的差異,不支持嚴格模式的瀏覽器與支持嚴格模式的瀏覽器行為上也不一樣,所以不要在未經嚴格模式特性測試情況下使用嚴格模式,嚴格模式可以與非嚴格模式共存,所以腳本可以逐漸的選擇性加入嚴格模式 嚴格模式的目的 首先,嚴格模式會將JavaScript陷阱直接變成明顯的錯...

    MingjunYang 評論0 收藏0
  • 談談text-overflow那些坑和應對方法

    摘要:基本語法默認值,將溢出的文本裁減掉將溢出的文本用省略號來表示設置一個字符串用來表示溢出的文本兼容性上,除了外,其余兩個屬性兼容到了,所以大可放心使用。 原文地址:https://www.xksblog.top/the-p... text-overflow是CSS3中的屬性,它規定了當文本溢出其包含元素時以何種方式顯示。但在使用的時候,有時會發現這個text-overflow設置了屬性...

    nodejh 評論0 收藏0
  • 前端面試:談談 JS 垃圾回收機制

    摘要:例如本地函數的局部變量和參數當前嵌套調用鏈上的其他函數的變量和參數全局變量還有一些其他的,內部的這些值稱為根。例如,如果局部變量中有對象,并且該對象具有引用另一個對象的屬性,則該對象被視為可達性,它引用的那些也是可以訪問的,詳細的例子如下。 最近看到一些面試的回顧,不少有被面試官問到談談JS 垃圾回收機制,說實話,面試官會問這個問題,說明他最近看到一些關于 JS 垃圾回收機制的相關的文...

    孫淑建 評論0 收藏0
  • 談談React那些小事

    摘要:在如今的前端框架界,三分天下的時代已經到來,而曾經一統天下的局面已一去不復返。三分天下,前端雖亂,但美其名曰繁榮。那些小事俗話說千里之堤毀于蟻穴,在開發中我們不能忙于進度而忽視了細節。 前言 說起React,那也是近一年多時間火起來的前端框架,其在Facebook的影響力和大力推廣下,已然成為目前前端界的中流砥柱。在如今的前端框架界,React、Vue、Angular三分天下的時代已經...

    Berwin 評論0 收藏0
  • 前端面試大全

    摘要:一般情況下是全局對象。避免在頁面的主體布局中使用,要等其中的內容完全下載之后才會顯示出來,顯示布局慢。對普通的網站有一個統一的思路,就是盡量向前端優化減少數據庫操作減少磁盤。 HTML面試題 1.XHTML和HTML有什么區別 HTML是一種基本的WEB網頁設計語言,XHTML是一個基于XML的置標語言最主要的不同: XHTML 元素必須被正確地嵌套。 XHTML 元素必須被關閉。...

    dingda 評論0 收藏0

發表評論

0條評論

shery

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<