在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 問答/HTML/ 當函數(shù)賦值給相同名稱的變量的問題

當函數(shù)賦值給相同名稱的變量的問題

問題描述:
我有兩個js文件
我在第一個js文件中定義了一個這個函數(shù)

function formHeader (msg) {
   let formHeaderContent = `
   <caption>${msg}</caption>
   <tr>
   <th>商品</th>
   <th>地區(qū)</th>
   <th>1月</th>
   <th>2月</th>
   <th>3月</th>
   <th>4月</th>
   <th>5月</th>
   <th>6月</th>
   <th>7月</th>
   <th>8月</th>
   <th>9月</th>
   <th>10月</th>
   <th>11月</th>
   <th>12月</th>
   </tr>`;
   return formHeaderContent;
}

在第二個.js中

function renderForm(data, msg) {
    // 輸出表頭:商品、地區(qū)、1月、2月、…… 12月
    // 遍歷數(shù)據(jù) {
    //    輸出每一行的表格HTML內(nèi)容
    // }
    // 把生成的HTML內(nèi)容賦給table-wrapper

    const formHeader = formHeader(msg);
    ....
 }

寫了一個這個函數(shù),然后報錯說 Uncaught ReferenceError: formHeader is not defined
我是這么理解的:我這個函數(shù)是在另一個js文件的全局里聲明定義的,為什么在這里它會報錯undefined?我的理解是兩個.js都屬于一個全局環(huán)境,我在其中一個.js中生命函數(shù),另外一個.js也應該能進行調(diào)用才對,不知道哪里理解的有問題
它和這個函數(shù)又什么區(qū)別呢?

function abc(val) {
    return val;
}
var abc = abc('hello') // 這個就可以正常輸出
回答
編輯回答
巴扎嘿

const, let 暫時性死區(qū)TDZ

當程序的控制流程在新的作用域(module, function或block作用域)進行實例化時,在此作用域中的用let/const聲明的變量會先在作用域中被創(chuàng)建出來,但因此時還未進行詞法綁定,也就是對聲明語句進行求值運算,所以是不能被訪問的,訪問就會拋出錯誤。所以在這運行流程一進入作用域創(chuàng)建變量,到變量開始可被訪問之間的一段時間,就稱之為TDZ(暫時死區(qū))

clipboard.png

2018年8月27日 21:45
編輯回答
神經(jīng)質(zhì)

一點一點說:

第一,你的原話是這樣的: "我是這么理解的:我這個函數(shù)是在另一個js文件的全局里聲明定義的,為什么在這里它會報錯undefined?我的理解是兩個.js都屬于一個全局環(huán)境,我在其中一個.js中生命函數(shù),另外一個.js也應該能進行調(diào)用才對";
你的全局聲明引用是沒問題的,前提是引入順序正常。

下面說說為什么會報錯,錯誤發(fā)生在你的第二個函數(shù)里面

先詳細說明一下es6規(guī)定的let和const特性,
es6出的 let 和 const都存在一種特性,沒有之前var的變量聲明提升,而引入了一個綁定區(qū)域,也叫暫時性死區(qū)。

什么意思呢?就是說在未對這個變量聲明之前不可使用,哪怕上層作用域已經(jīng)聲明了這個變量,如下:

var tmp = 123;

if (true) {
  tmp = 'abc'; // ReferenceError
  let tmp;
}

當然你的 錯誤并不是 暫時性死區(qū) 引發(fā)的。
你這個屬于在 變量聲明完成之前使用變量錯誤,正在創(chuàng)建變量,還沒有創(chuàng)建完畢,

2018年8月3日 01:16
編輯回答
尕筱澄

你代碼是怎么寫的,是不是用了模塊化。 如果用了模塊化是不會生命到window上。 而是有自己的作用域。需要通過導入(require/import)來引入

如果排除使用了模塊化的情況,那就是順序問題了。 你要確保前面定義的函數(shù)先執(zhí)行

2017年12月15日 18:10
編輯回答
青瓷

這兩段代碼的區(qū)別就在于第一段創(chuàng)建了一個新的formHeader局部常量,第二段沒有。

我的理解是兩個.js都屬于一個全局環(huán)境,我在其中一個.js中生命函數(shù),另外一個.js也應該能進行調(diào)用才對

沒錯,這么寫是可以的:

function renderForm(data, msg) {
    const formHeaderValue = formHeader(msg);
}
為什么在這里它會報錯undefined?

新人最常見的錯誤,就是以為賦初值是先計算右邊,再創(chuàng)建變量,再賦值。但實際上,是先創(chuàng)建變量,再計算右邊,再賦值。程序看到const formHeader的時候,會立即記下formHeader是個局部變量,再去計算右邊的時候,formHeader已經(jīng)是局部的未初始化的值了,而不是外部的函數(shù)。

第二段因為一直在同一個作用域內(nèi),第二次var沒有創(chuàng)建新的變量,所以可以。


有評論在上面講“l(fā)et/const 變量只有定義被求值后才會初始化”。如果“初始化”是指“記為本地變量”,那么這個評論就是錯誤的。

考慮:

function foo() {} { };
(function () {
  debugger;
  const bar = foo();
  const foo = bar;
})()
  1. debugger可以看到兩個變量已經(jīng)在Local Scope創(chuàng)建出來了
    clipboard.png
  2. 程序會在第四行報錯,而不是調(diào)用外層的foo

可能有些同學對let/const產(chǎn)生了誤解,以為它們就不會變量提升了。事實上,JS引擎還是先掃描一次所有定義,生成Scope,然后再處理代碼邏輯。為了在效率和方便之間平衡,這么做是必須的。過于簡化地講,let/constvar唯一的差別就是把undefined換成了ReferenceError。所以我上面說,formHeader已經(jīng)是局部的未初始化的值了,就是指訪問的時候會根據(jù)用的關(guān)鍵詞返回該關(guān)鍵詞對應的未初始化值(varundefinedlet/constReferenceError)。

可能我沒有直接解釋ReferenceError的問題,但是我覺得“變量聲明的時機”才是更根本的問題,畢竟題主問題的標題是“當函數(shù)賦值給相同名稱的變量”,而且就算是老手也不一定能弄明白。樓上各位都直接解釋暫時性死區(qū),但是換成var之后,第一段代碼一樣不能運行,題主又會到SF上提修改后的問題。

下面的評論說“應該報的錯的是 formHeader is not a function.”,實際上如果把題主的const換成var,或者hack進瀏覽器內(nèi)核禁用TDZ,報的正好是這個錯誤。

2017年2月9日 11:41