js中的this,arguments, callee, caller

一張圖,先捋一捋邏輯
在這裏插入圖片描述

arguments

在函數內部,有兩個特殊的對象:arguments 和 this。arguments是一個類數組對象,包含着傳入函數中的所有參數。在函數體內可以通過arguments對象來訪問這個參數數組,從而獲取傳遞給函數的每一個參數。
arguments對象只是與數組類似(它不是Array的實例)。可以使用方括號語法訪問它的每個元素。

arguments[0]

沒有傳遞值的命名參數將自動被賦予 undefined 值。這就跟定義了變量但又沒有初始化一樣。

arguments.callee

這個arguments對象還有一個明教callee的屬性,該屬性是一個指針,指向擁有這個arguments對象的函數。

一個使用arguments.callee的例子。

function factorial(num){ 
    if (num <=1) { 
        return 1; 
    } else { 
        return num * factorial(num-1) 
    } 
}

定義階乘函數一般都要用到遞歸算法;,在函數有名字,而且名字以後也不會變的情況下,這樣定義沒有問題。但問題是這個函數的執行與函數名 factorial耦合在了一起。爲了消除這種緊密耦合的現象,可以像下面這樣使用 arguments.callee。

function factorial(num){ 
    if (num <=1) { 
        return 1; 
    } else { 
        return num * arguments.callee(num-1) 
    } 
}

在這個重寫後的 factorial()函數的函數體內,沒有再引用函數名factorial。這樣,無論引用函數時使用的是什麼名字,都可以保證正常完成遞歸調用。

caller

ECMAScript 5 也規範化了另一個函數對象的屬性:caller。除了 Opera 的早期版本不支持,其他瀏覽器都支持這個ECMAScript3並沒有定義的屬性。這個屬性中保存着調用當前函數的函數的引用,如果是在全局作用域中調用當前函數,它的值爲 null

function outer(){ 
    inner();  
} 
 
function inner(){ 
    alert(inner.caller); 
} 
 
outer();

上面代碼會導致警告框中顯示 outer()函數的源代碼。因爲 outer()調用了 inter(),所以 inner.caller 就指向 outer()。爲了降低耦合度,也可以通過 arguments.callee.caller 來訪問相同的信息

function outer(){ 
    inner(); 
} 
 
function inner(){ 
    alert(arguments.callee.caller); 
}  
 
outer();

IE、Firefox、Chrome 和 Safari 的所有版本以及 Opera 9.6 都支持 caller 屬性。

當函數在嚴格模式下運行時,訪問 arguments.callee 會導致錯誤。ECMAScript 5 還定義了 arguments.caller 屬性,但在嚴格模式下訪問它也會導致錯誤,而在非嚴格模式下這個屬性始終是 undefined。定義這個屬性是爲了分清 arguments.caller 和函數的 caller 屬性。以上變化都是爲 了加強這門語言的安全性,這樣第三方代碼就不能在相同的環境裏窺視其他代碼了。 嚴格模式還有一個限制:不能爲函數的 caller 屬性賦值,否則會導致錯誤。

老生常談this的問題

  • 全局代碼中的this指向 window
  • 單純的函數調用,this指向全局對象,window
  • 作爲對象的方法被調用時候指向調用調用他的對象。
  • new 聲明構造函數的時候,this指向這個新創建的對象。
  • 在內部函數中,仍然指向全局對象winodw
  • 可以用call,apply,bind改變this的指向。

new操作符幹了什麼?

  1. 創建一個新對象;[var o = {};]
  2. 將構造函數的作用域賦給新對象(因此this指向了這個新對象)
  3. 執行構造函數中的代碼(爲這個新對象添加屬性);
  4. 返回新對象。

留下箭頭函數的問題。

此文結合上面腦圖看效果更佳。

發佈了38 篇原創文章 · 獲贊 39 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章