+function foo(){ foo=10;//我的问题代码 console.log(foo);//方法自己 }(); console.log(typeof foo);//undefined 观察是否全局污染
我想問 函數foo內部對foo再賦值的這個10去哪了,還有同名函數foo是如何阻止全局污染的,求解求擴展
ringa_lee
題主能問這個,可以的.不過這題能透過自己實踐解決掉. . .
首先題主對於IIFE的寫法沒問題,IIFE的寫法好多,常見的就是@ewind說的這個和:
(function(){}())
還有不常見的:
!function(){ /* code */ }(); ~function(){ /* code */ }(); -function(){ /* code */ }(); +function(){ /* code */ }();
接著再說程式碼:在函數裡賦予目前函數名稱時:foo = 10; 無效. (贊同@ewind,這裡會忽略,應該有更合理的說法.)JS解析器會忽略掉它. 我在Chrome控制台執行的結果是:
foo = 10;
function foo(){ foo=10;//我的问题代码 console.log(foo);//方法自己 } undefined // 上面typeof foo的结果
這證明了上面我說的忽略. 接著因為IIFE模擬了區塊作用域,外部環境存取不了內部的變數.所以就是undefined.
@ewind說因為foo是匿名函數然後怎麼樣. 明顯概念搞混了. foo函數並不是匿名函數.
function [name]([param] [, param] [..., param]) { statements } name 函数名,可以省略。当省略函数名的时候,该函数就成为了匿名函数。
MDN
首先,貼出的程式碼是不完整的。完整版應該是這樣
(function foo(){ foo = 10 console.log(foo) // [Function: foo] })(); console.log(typeof foo) // undefined
這確實看起來比較反直覺,因為沒有採用 var 聲明的 foo 並沒有污染全域作用域。
但如果函數內宣告的變數名稱不是 foo,就很符合直覺了,如下:
var bar = 1; (function foo(){ bar = 10 })(); console.log(typeof foo) // undefined console.log(bar) // 10
所以為什麼函數內宣告的變數和函數名稱同名時,會發生問題呢?可以看這個範例:
(function foo(){ console.log(foo) // [Function: foo] console.log(arguments.callee) // [Function: foo] console.log(foo === arguments.callee) // true })();
在立即執行的函數帶有 foo 這一函數名後,調用時的 arguments.callee 其實就是對 foo 的引用了。比較二者可以發現此時 foo 就是函數物件。此時賦值運算並不能生效,遇到未加 var 宣告的 foo 變數時,解譯器查找到的也是這個函數對象,因此不會在全域作用域下產生污染。
題主能問這個,可以的.不過這題能透過自己實踐解決掉. . .
首先題主對於IIFE的寫法沒問題,IIFE的寫法好多,常見的就是@ewind說的這個和:
還有不常見的:
接著再說程式碼:
在函數裡賦予目前函數名稱時:
foo = 10;
無效. (贊同@ewind,這裡會忽略,應該有更合理的說法.)JS解析器會忽略掉它.我在Chrome控制台執行的結果是:
這證明了上面我說的忽略.
接著因為IIFE模擬了區塊作用域,外部環境存取不了內部的變數.所以就是undefined.
@ewind說因為foo是匿名函數然後怎麼樣.
明顯概念搞混了. foo函數並不是匿名函數.
MDN
首先,貼出的程式碼是不完整的。完整版應該是這樣
這確實看起來比較反直覺,因為沒有採用 var 聲明的 foo 並沒有污染全域作用域。
但如果函數內宣告的變數名稱不是 foo,就很符合直覺了,如下:
所以為什麼函數內宣告的變數和函數名稱同名時,會發生問題呢?可以看這個範例:
在立即執行的函數帶有 foo 這一函數名後,調用時的 arguments.callee 其實就是對 foo 的引用了。比較二者可以發現此時 foo 就是函數物件。此時賦值運算並不能生效,遇到未加 var 宣告的 foo 變數時,解譯器查找到的也是這個函數對象,因此不會在全域作用域下產生污染。