欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript中標(biāo)識(shí)符提升問題

 更新時(shí)間:2015年06月11日 10:06:16   投稿:hebedich  
標(biāo)識(shí)符指的是javascript中定義的符號(hào),標(biāo)識(shí)符可以由任意順序的大小寫字母、數(shù)字、下劃線和美元符號(hào)組成,但標(biāo)識(shí)符不能以數(shù)字開頭,也不能是javascript中的保留關(guān)鍵字。并且要注意,javascript是嚴(yán)格區(qū)分大小寫的。

JS 存在變量提升,這個(gè)的設(shè)計(jì)其實(shí)是低劣的,或者是語言實(shí)現(xiàn)時(shí)的一個(gè)副作用。它允許變量不聲明就可以訪問,或聲明在后使用在前。新手對(duì)于此則很迷惑,甚至許多使用JS多年老手也比較迷惑。但在 ES6 加入 let/const 后,變量Hoisting 就不存在了。

一、 變量未聲明,直接使用

function test() {
  alert(notDefined);
}
test(); // ?

報(bào)錯(cuò)是自然的

二. 變量聲明在末尾

function test() {
  alert(declaredButNotAssigned); // undefined
  var declaredButNotAssigned;
}
test();

輸出 undefined, 結(jié)果比上例有所改善,沒有報(bào)錯(cuò),代碼可以運(yùn)行,但變量值可能不是程序員所期望的。

三、 變量聲明在末尾,同時(shí)給變量賦值

function test() {
  alert(declaredAndAssigned); // undefined
  var declaredAndAssigned = 1;
}
test();

結(jié)果和 二 相同, 很明顯,并不會(huì)因?yàn)橘x值了就輸出 1。

二、三 都發(fā)生了變量提升(Hoisting),簡(jiǎn)單定義

變量提升: 在指定作用域里,從代碼順序上看是變量先使用后聲明,但運(yùn)行時(shí)變量的 “可訪問性” 提升到當(dāng)前作用域的頂部,其值為 undefined ,沒有 “可用性”。

這里強(qiáng)調(diào) “代碼順序” 和 “運(yùn)行順序”,是因?yàn)槎鄶?shù)時(shí)候我們寫的代碼都是順序執(zhí)行的,即 “代碼順序” 和 “運(yùn)行順序” 是一致的。這也符合人的大腦的思維過程。比如有過 C語言 經(jīng)驗(yàn)的程序員

#include <stdio.h>
int main() {
  int x = 1;
  printf("%d, ", x); // 1
}

兩句代碼,先聲明整數(shù)型 x, 再輸出。代碼順序和運(yùn)行順序是一致的,即正常運(yùn)行。

如果順序反過來

#include <stdio.h>
int main() {
  printf("%d, ", x); // error
  int x = 1;
}

此時(shí),編譯都不能通過了。但JS里可以反過來寫,見二、三。

因此,有類 C語言 經(jīng)驗(yàn)的程序員,都很清楚變量需要 先聲明后使用,不然會(huì)報(bào)錯(cuò)。而到了JS里,有 變量提升 現(xiàn)象,可以 先使用后聲明,C 的經(jīng)驗(yàn)用到 JS 里迷惑便出現(xiàn)了。

四、 函數(shù)表達(dá)式也存在變量提升

function test() {
  alert(func); // undefined
  var func = function() {};
}
test();

但如果想使用這個(gè) func,則無可能

function test() {
  alert(func); // undefined
  func(); // 報(bào)異常
  var func = function() {};
}
test();

結(jié)果func 是 undefined,調(diào)用 func 則會(huì)報(bào)異常。 在上面的定義中提到了 可訪問性 和 可用性 對(duì)應(yīng)如下語句。

可訪問性:alert(func),輸出 undefined,可以運(yùn)行,可以訪問 func。

可用性:   func(), 報(bào)異常,不能正常調(diào)用 func,表示無可用性。

二、三、四 都是使用 var 聲明的變量,JS 里函數(shù)聲明也會(huì)存在提升,只是這個(gè) “變量” 比較特殊,它是一個(gè) function 類型(可以作為函數(shù)、方法或構(gòu)造器)。它的名字(標(biāo)識(shí)符)也會(huì)提升到當(dāng)前作用域的頂部。

五、函數(shù)聲明的名也會(huì)提升到當(dāng)前作用域頂部

function test() {
  alert(f1); // function
  f1(); // "called"
  function f1() {
    alert('called');
  }
}
test();

我們看到,聲明 f1 在代碼最末,f1 使用在前,alert(f1) 和 f1() 都正常執(zhí)行,表示 可訪問性 和 可用性 都有了。

前面說了,變量提升(Hoisting)沒什么用,屬于語言的低劣設(shè)計(jì),好的習(xí)慣還是 “先聲明后使用”。這個(gè)特性也會(huì)出現(xiàn)在不少大公司面試題里

題1:

// 寫出以下代碼的運(yùn)行結(jié)果
var a = 1;
function fn() {
  if (!a) {
    var a = 2;
  }
  alert(a); // ?
}
fn();

題2:

// 寫出以下代碼的運(yùn)行結(jié)果
var a = 1;
function fn() {
  a = 2;
  return;
  function a() {}
}
fn();
alert(a); // ?

但這一切隨著 ES6 的 let/const 到來結(jié)束了,ES里除全局變量外,其它都使用 let/const,var 替換成 let 后變量提升就不復(fù)存在了。

function test() {
  alert(declaredButNotAssigned1); // 報(bào)異常
  alert(declaredButNotAssigned2); // 報(bào)異常
  alert(func); // 報(bào)異常
 
  let declaredButNotAssigned1;
  let declaredButNotAssigned2 = true;
  let func = function() {};
}
test();

這強(qiáng)制程序員養(yǎng)成好的習(xí)慣,變量需要“先聲明再使用”,否則報(bào)錯(cuò)。

以下摘自MDN的關(guān)于let不在發(fā)生變量提升的描述

復(fù)制代碼 代碼如下:

In ECMAScript 6, let does not hoist the variable to the top of the block. If you reference a variable in a block before the let declaration for that variable is encountered, this results in a ReferenceError, because the variable is in a "temporal dead zone" from the start of the block until the declaration is processed.

用 let 聲明變量后,typeof 也不再安全

if (condition) {
  alert(typeof num); // Error!
  let num = 100;
}
 

以前可以用 typeof == 'undefined',來判斷是否引入了某lib,比如jQuery

// 判斷jQuery是否引入了
if (typeof $ !== 'undefined') {
  // do something
}...

jQuery沒有引入,$ 沒有聲明,這句也不會(huì)報(bào)錯(cuò)而影響到下面的代碼執(zhí)行,但如果是 let 聲明的就會(huì)報(bào)錯(cuò)了。

以上所述就是本文的全部?jī)?nèi)容了,希望大家能夠喜歡。

相關(guān)文章

最新評(píng)論