關於具名的IIFE內部對函數自身再賦值問題?

+function foo(){
foo=10;//我的問題代碼
console.log(foo);//方法自己
}();
console.log(typeof foo);//undefined 觀察是否全局污染

我想問 函數foo內部對foo再賦值的這個10去哪了,還有同名函數foo是如何阻止全局污染的,求解求擴展


1. 函數表達式與函數聲明不同,函數名只在該函數內部有效,並且此綁定是常量綁定。

2. 對於一個常量進行賦值,在 strict 模式下會報錯,非 strict 模式下靜默失敗。

3. IIFE中的函數是函數表達式,而不是函數聲明。


@賀師俊 這個問題上,賀老已經點到精髓了,想在賀老的基礎上說一下自己的理解

(function foo() {
foo = 10;
console.log(foo);
})();
console.log(typeof foo);

1. 為什麼console.log(typeof foo) 會返回undefined?

由於foo函數對象在定義的時候就被立即執行(IIFE)了,因此,

在strict mode下和non-strict mode下,console.log(foo)會報ReferenceError的錯誤,這類錯誤表明與作用域相關,且錯誤表明 foo is not defined。

// strict mode non-strict mode
(function foo() {
})();
console.log(foo); // ReferenceError: foo is not defined

但是,不管是在哪一種模式下,JavaScript中typeof關鍵字去檢測類型的時候,對於未定義的變數或者已經定義了,但未賦值的變數,都統一返回undefined

// strict mode
var lovely;
console.log(typeof lovely); // undefined
console.log(typeof peaceful); // undefined

// non-strict mode
var lovely;
console.log(typeof lovely); // undefined
console.log(typeof peaceful); // undefined

因此,foo函數對象在外部是無法獲取的,而使用typeof關鍵字返回undefined是由於typeof處理機制的問題

2. 為什麼 foo = 10 丟失了?

(function foo() {
foo = 10;
console.log(foo); //TypeError: Assignment to constant variable.
})();

把code 運行一次之後,在瀏覽器報出了TypeError類型的錯誤

這種錯誤是於JavaScript數據類型相關的,而賀老也說了

IIFE中的foo函數名相當於是使用const關鍵字定義的,因此沒有辦法對一個常量再賦值

在strict mode下,直接TypeErroe類型的錯誤,這類錯誤同數據類型相關

在non-strict mode下,會忽略對常量的賦值

實際上,有點類似於以下代碼,但不完全相同,因為使用const不管在什麼模式下,都會TypeError類型的錯誤

const foo = function () {
foo = 10;
console.log(foo);
};
(foo)(); //TypeError: Assignment to constant variable.

因此,在strict mode下,瀏覽器報錯;在non-strict mode下,忽略對foo = 10 的賦值 ,返回undefined

另外,最後想說的是,JavaScript將function關鍵字當作函數聲明的開始,而函數聲明後面不能跟圓括弧表示立即執行,如果帶上圓括弧,會報錯SyntaxError類型的錯誤,這種錯誤同JavaScript語法相關

所以將函數聲明包含在一定圓括弧中,表示它實際上是一個函數表達式,而隨後使用另一對圓括弧立即執行了這個函數表達式


在湯姆大叔的文章中 深入理解JavaScript系列(15):函數(Functions) - 湯姆大叔 - 博客園 也講到過這個問題。

關鍵就在於 specialObject.foo 的值是 DontDelete 和 ReadOnly 的,所以賦值的操作會失效。

我的理解的是,當遇到具名的函數表達式的時候,會創建一個輔助的特定對象,只存儲函數表達式的名稱,然後添加到函數的作用域鏈中,該值只讀,並且不可以被刪除,所以不能對該值進行操作。


推薦閱讀:

官網網站用什麼技術棧比較合理?
關於angular在指令中無法獲取子元素的問題?
jQuery 和 YUI (Yahoo User Interface) 各自的優缺點有哪些?具體的使用場景是怎樣的?
有一千本以上實體紙質編程書是什麼體驗?

TAG:Web開發 | JavaScript | JavaScript語言精粹 | 原生JavaScript | JavaScript引擎 |