《你不知道的JavaScript》-- 精讀(四)

知識點

1.變量聲明和賦值的前後

a = 2;
var a;
console.log(a); // 2
複製代碼
console.log(a); // undefined
var a;
複製代碼

變量和函數在內的全部聲明都會在任何代碼被執行前首先被處理。bash

JavaScript會將var a = 2;當作兩個聲明: var a; 和 a = 2;第一個定義聲明是在編譯階段進行的。第二個賦值聲明會被留在原地執行階段。函數

因此上面的兩個代碼片斷會以以下形式進行處理:spa

var a;
a = 2;
console.log(a);
複製代碼
var a;
console.log(a);
複製代碼

這個過程就好像變量和函數聲明從它們在代碼中出現的位置被「移動」到了最上面。 這個過程就叫作提高。code

foo();
function foo(){
    console.log(a); // undefined
    var a = 2;
}
複製代碼

foo函數的聲明(這個例子還包括實際函數的隱含值)被提高了,所以第一行中的調用能夠正常執行。ip

每一個做用域都會進行提高操做。作用域

上面的代碼實際上會被理解爲下面的形式:string

function foo(){
    var a;
    console.log(a); // undefined
    a = 2;
}
foo();
複製代碼

函數聲明會被提高,可是函數表達式卻不會被提高。it

foo(); // 不是ReferenceError,而是TypeError!
var foo = function bar(){
    // ...
}
複製代碼

這段程序中的變量標識符foo被提高並分配給所在做用域,所以foo不會致使ReferenceError。可是foo此時並無賦值,foo()因爲對undefined值進行函數調用而致使非法操做,所以拋出TypeError異常。io

即便是具名的函數表達式,名稱標識符在賦值以前也沒法在所在做用域中使用。console

foo(); // TypeError
bar(); // ReferenceError
var foo = function bar(){
    // ...
}
複製代碼

上面的代碼片斷通過提高後,實際上會被理解爲如下形式:

var foo;
foo(); // TypeError
bar(); // ReferenceErro
foo = function(){
    var bar = ...self...
    // ...
}
複製代碼

2.函數優先

函數聲明和變量聲明都會被提高。可是有一個細節是,函數首先被提高,而後纔是變量。

foo(); // 1
var foo;
function foo(){
    console.log("1");
}
foo = function(){
    console.log(2);
}
複製代碼

這個代碼片斷會被引擎理解爲以下形式:

function foo(){
    console.log(1);
}
foo(); // 1
foo = function(){
    console.log(2);
}
複製代碼

var foo儘管出如今function foo()...的聲明以前,但它是重複的聲明(所以被忽略了),由於函數聲明會被提高到普通變量以前。

儘管重複的var聲明會被忽略掉,但出如今後面的函數聲明仍是能夠覆蓋前面的。

foo(); //3
function foo(){
    console.log(1)
}
var foo = function(){
    console.log(2)
}
function foo(){
    console.log(3)
}
複製代碼

總結

全部的聲明(變量和函數)都會被「移動」到各自做用域的最頂端,這個過程被稱爲提高。

巴拉巴拉

關於溝通

我買了一本《溝通的技術》,並無耐心看幾頁,一直在牀頭落灰,可能這是個人溝通能力一直沒有獲得提高的緣由。因此要在這裏立個flag,每週看一章,不能再少了,否則就接不上上下文了。

相關文章
相關標籤/搜索