鍍金池/ 問答/HTML/ 學(xué)習(xí)ES6的時(shí)候看到一個(gè)函數(shù),為什么自己運(yùn)行的時(shí)候會(huì)報(bào)錯(cuò)

學(xué)習(xí)ES6的時(shí)候看到一個(gè)函數(shù),為什么自己運(yùn)行的時(shí)候會(huì)報(bào)錯(cuò)

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

回答
編輯回答
夏夕

clipboard.png

所以下方 f() 調(diào)用 它肯定報(bào)錯(cuò) 它不是一函數(shù)了 你卻調(diào)用它

2018年6月29日 19:50
編輯回答
柒槿年

clipboard.png
這張是原文,原文鏈接

這張是我之前寫的,跟原文是一樣的clipboard.png
這樣寫的話會(huì)報(bào)如下錯(cuò)
clipboard.png

不知道是不是瀏覽器環(huán)境變量的原因,不是很懂。
但是如果 if 里面用函數(shù)表達(dá)式并且用let聲明的時(shí)候會(huì)有輸出值
clipboard.png

2017年6月11日 09:34
編輯回答
舊時(shí)光

從兩點(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

2017年8月5日 20:03
編輯回答
獨(dú)特范

你可以把代碼使用babel在線轉(zhuǎn)義成es5,看下轉(zhuǎn)義出來的結(jié)果你就知道了

2018年1月20日 07:29
編輯回答
奧特蛋

你后面的那個(gè)括號(hào)是不是寫錯(cuò)位置了,是不是應(yīng)該是這樣:

function f(){
    console.log('I am outside!');
}

(function (){
    if (false){
        function f(){
            console.log('I am inside!');
        }
    }

    f();
})()    //注意這里
2017年6月24日 06:56
編輯回答
陌南塵

你要聲明 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)。

http://es5.github.io/#x12

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 .....

2017年1月20日 00:46
編輯回答
青黛色

函數(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í)變量初始化留在原來的地方

2018年7月20日 16:17
編輯回答
苦妄

又看了一下阮老師的博客,題主貼的這段代碼在 IE10 及以下是輸出 'I am inside!'

https://github.com/ruanyf/es6tutorial/search?q=%E5%9D%97%E7%BA%A7%E4%BD%9C%E7%94%A8%E5%9F%9F&type=Issues&utf8=%E2%9C%93

發(fā)現(xiàn)大家對(duì)這段代碼還是有很多疑問的,阮老師也做了說明,可以參考一下。

2018年8月12日 07:15
編輯回答
凝雅

因?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ù)往下看就知道了。

2017年9月3日 16:05
編輯回答
祉小皓

這是個(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è)局部變量

2017年8月23日 13:17