function f(){
console.log('I am outside!');
}
(function (){
if (false){
function f(){
console.log('I am inside!');
}
}
f();
}())
看的是阮一峰老師的《ES6標(biāo)準(zhǔn)入門》塊級(jí)作用域部分,書上說會(huì)輸出‘I am outside!’
可是實(shí)際上瀏覽器報(bào)錯(cuò) test.html:25 Uncaught TypeError: f is not a function at test.html:25 at test.html:26
這張是原文,原文鏈接
這張是我之前寫的,跟原文是一樣的
這樣寫的話會(huì)報(bào)如下錯(cuò)
不知道是不是瀏覽器環(huán)境變量的原因,不是很懂。
但是如果 if 里面用函數(shù)表達(dá)式并且用let聲明的時(shí)候會(huì)有輸出值
從兩點(diǎn)出發(fā)給你解釋
1.首先要確定的是
if (false){
function f(){
console.log('I am inside!');
}
}
這段代碼怎么也不可能會(huì)執(zhí)行,因?yàn)閷懰懒?code>false
既然這段代碼不會(huì)執(zhí)行,那么在
(function (){
if (false){
function f(){
console.log('I am inside!');
}
}
f();
})()
這段代碼中要運(yùn)行f()
,需要一個(gè)條件。那就是那個(gè)if
語句里面的函數(shù)f()
沒有綁定到這整個(gè)自執(zhí)行函數(shù)的作用域中。這樣的話這里運(yùn)行的函數(shù)f()
就是外面的那個(gè)f()
了,就可以輸出I am outside
。
這就是es5
的運(yùn)行結(jié)果。
那么ES6
當(dāng)中的塊級(jí)作用域是,無論你聲明的變量或者函數(shù)執(zhí)不執(zhí)行,只要聲明了就會(huì)綁定到當(dāng)前作用域中,即使你的if
語句不執(zhí)行,但也不會(huì)外層的f()
函數(shù)影響到這個(gè)自執(zhí)行函數(shù)的作用域中。因此最終結(jié)果就是f is not a function
。
你要聲明 strict mode 才能觀察到該現(xiàn)象。
(function {
'use strict'
// ...
否則在 sloppy mode 下會(huì)相當(dāng)于這樣
(function {
var f // 所以后面不能調(diào)用 f()
if (false) {
let f = function f() {....}
... (如果有其它代碼的話)
f = f // 原來 function f(){...} 的位置
...
}
這是為了兼容 ES5 語法。
而對(duì)于 ES5 來說,這樣的寫法是不推薦的,因?yàn)橛泻芏鄮?bug 的實(shí)現(xiàn)。
NOTE?Several widely used implementations of ECMAScript are known to support the use of FunctionDeclaration as a Statement. However there are significant and irreconcilable variations among the implementations in the semantics applied .....
函數(shù)f
聲明在全局,所以任何地方均可以拿到
此處問題為變量聲明提前: 變量提前聲明卻未被初始化。
所以第二段代碼執(zhí)行過程為
(function (){
var f;
if (false){
f = function(){
console.log('I am inside!');
}
}
// f未賦值
f();
}())
可以console.log這個(gè)函數(shù),f
輸出為 undefined
變量在聲明前已經(jīng)可用了。將函數(shù)內(nèi)的變量聲明「提前」至函數(shù)體頂部,同時(shí)變量初始化留在原來的地方
又看了一下阮老師的博客,題主貼的這段代碼在 IE10 及以下是輸出 'I am inside!'
。
發(fā)現(xiàn)大家對(duì)這段代碼還是有很多疑問的,阮老師也做了說明,可以參考一下。
因?yàn)樵跒g覽器實(shí)現(xiàn)中實(shí)際運(yùn)行的是如下代碼
function f() { console.log('I am outside!'); }
(function () {
var f = undefined;
if (false) {
function f() { console.log('I am inside!'); }
}
f();
}());
// Uncaught TypeError: f is not a function
原文已經(jīng)說明了原因,繼續(xù)往下看就知道了。
這是個(gè)很有趣的例子,詳情可參考javascript的作用域鏈。當(dāng)你在閉包內(nèi)定義了一個(gè)f函數(shù),即使他并不可能倍執(zhí)行,但f在這里是作為全局變量,它覆蓋了之前f函數(shù)的定義,所以在你后面調(diào)用f()
的時(shí)候會(huì)顯示未定義,如果你把if那一段去掉就會(huì)有結(jié)果,或者把閉包內(nèi)的f函數(shù)用let
定義為一個(gè)局部變量
北大青鳥APTECH成立于1999年。依托北京大學(xué)優(yōu)質(zhì)雄厚的教育資源和背景,秉承“教育改變生活”的發(fā)展理念,致力于培養(yǎng)中國(guó)IT技能型緊缺人才,是大數(shù)據(jù)專業(yè)的國(guó)家
北大青鳥中博軟件學(xué)院創(chuàng)立于2003年,作為華東區(qū)著名互聯(lián)網(wǎng)學(xué)院和江蘇省首批服務(wù)外包人才培訓(xùn)基地,中博成功培育了近30000名軟件工程師走向高薪崗位,合作企業(yè)超4
中公教育集團(tuán)創(chuàng)建于1999年,經(jīng)過二十年潛心發(fā)展,已由一家北大畢業(yè)生自主創(chuàng)業(yè)的信息技術(shù)與教育服務(wù)機(jī)構(gòu),發(fā)展為教育服務(wù)業(yè)的綜合性企業(yè)集團(tuán),成為集合面授教學(xué)培訓(xùn)、網(wǎng)
達(dá)內(nèi)教育集團(tuán)成立于2002年,是一家由留學(xué)海歸創(chuàng)辦的高端職業(yè)教育培訓(xùn)機(jī)構(gòu),是中國(guó)一站式人才培養(yǎng)平臺(tái)、一站式人才輸送平臺(tái)。2014年4月3日在美國(guó)成功上市,融資1
曾工作于聯(lián)想擔(dān)任系統(tǒng)開發(fā)工程師,曾在博彥科技股份有限公司擔(dān)任項(xiàng)目經(jīng)理從事移動(dòng)互聯(lián)網(wǎng)管理及研發(fā)工作,曾創(chuàng)辦藍(lán)懿科技有限責(zé)任公司從事總經(jīng)理職務(wù)負(fù)責(zé)iOS教學(xué)及管理工作。
浪潮集團(tuán)項(xiàng)目經(jīng)理。精通Java與.NET 技術(shù), 熟練的跨平臺(tái)面向?qū)ο箝_發(fā)經(jīng)驗(yàn),技術(shù)功底深厚。 授課風(fēng)格 授課風(fēng)格清新自然、條理清晰、主次分明、重點(diǎn)難點(diǎn)突出、引人入勝。
精通HTML5和CSS3;Javascript及主流js庫(kù),具有快速界面開發(fā)的能力,對(duì)瀏覽器兼容性、前端性能優(yōu)化等有深入理解。精通網(wǎng)頁制作和網(wǎng)頁游戲開發(fā)。
具有10 年的Java 企業(yè)應(yīng)用開發(fā)經(jīng)驗(yàn)。曾經(jīng)歷任德國(guó)Software AG 技術(shù)顧問,美國(guó)Dachieve 系統(tǒng)架構(gòu)師,美國(guó)AngelEngineers Inc. 系統(tǒng)架構(gòu)師。