一. 全域性變數和區域性變數分析
在函式外部由var定義的變數稱為全域性變數,變數的作用範圍是整個程式,只有當程式執行完後(在瀏覽器中一般指關掉這個頁面)才會釋放其記憶體空間。
不用var宣告的變數稱為隱式全域性變數,注意在函式內部不用var定義的變數也是隱式全域性變數。
注意用var宣告的變數(無論是全域性變數還是區域性變數)是不能用delete刪除的,因為var定義的變數是不可配置的。但是隱式全域性變數是可以利用delete刪除的,因為它是可配置的。
functionf(
)console.
log(x)
;//會報錯,x沒有被定義
在函式內部定義的變數稱為區域性變數, 變數的作用範圍只在定義的這個函式內部,像上面的第乙個程式,在函式內部定義了x,但是函式外部在程式臺輸出x時會報錯,提示x沒有被定義。delete運算子同樣也不能刪除var 定義的區域性變數,因為var定義的變數是不可配置的。functionf(
)console.
log(x)
;//輸出1
全域性變數和區域性變數是允許同名的,但是在函式內部區域性變數會覆蓋全域性變數,如下例所示:
二. 從兩個角度去理解變數作用域var x =
100;
//定義全域性變數x並初始化為100
functionf(
)console.
log(x)
;//輸出100
第一種是直觀地通過變數定義所在的位置去理解變數作用域,變數定義在函式外部那麼變數的作用域就是整個程式,變數定義在函式內部,那麼變數作用域就是這個函式的內部。
我們知道當var 宣告乙個全域性變數時,實際上是定義了全域性變數的乙個屬性。js全域性變數是全域性物件的屬性,這是在es規範中強制規定的。對於區域性變數則沒有此規定,但是我們可以推斷出,區域性變數是跟函式呼叫相關的某個物件的屬性,比如定義乙個函式f它有乙個區域性變數x,這個區域性變數x就和函式(物件,js中函式也是物件)f1有關,它是物件f1的乙個屬性。
如果將乙個區域性變數看成是某個物件的屬性的話,我們就可以換乙個角度來理解變數作用域每一段js**都有乙個與之相關聯的作用域鏈,作用域鏈就是乙個物件列表或鍊錶。這組物件定義了這段**作用域中的變數。以上面這段程式為例,下面是作用域鏈:var x =10;
//定義乙個全域性變數並初始化為10
functionf(
)var f1 = f;
//將函式f的引用賦給f1,此時f1和f同時引用這個函式。f1(
);//呼叫上面那個函式
console.
log(f)
;//訪問這個函式的內容
console.
log(f1)
;//訪問這個函式的內容
console.
log(
typeof
(f))
;//function型別
console.
log(
typeof
(f1));
//function型別
js引擎解析識別符號的過程:
當js在函式內部需要查詢變數x的時候會先從物件鍊錶中的第乙個物件開始查詢,如果這個物件有乙個名為x的屬性,那麼則會直接使用這個屬性的值,如果沒有這個屬性,那麼js會接著查詢物件鍊錶中的下乙個物件。以此類推,如果作用域鏈上沒有任何乙個物件含有屬性x,那麼js認為這段**的作用域鏈上不存在x,並最終丟擲乙個引用錯誤異常。
在此程式中,要查詢變數x,在作用域鍊錶上第乙個物件中就能夠查詢到,並將其返回。
下面介紹一下不同位置**的作用域鏈:
三. 關於浮點數值計算產生捨入誤差的問題分析
四. 理解js預解析var x =
0.1;
var y =
0.2;
if(x+y==
0.3)
首先預解析階段遇到 var a = 1;宣告變數aconsole.
log(a)
;var a =1;
console.
log(a)
;functiona(
)var a =3;
console.
log(a)
;functiona(
) console.
log(a);a();
然後遇到第乙個函式a宣告,這時由於和變數a重名,故將變數a替代,此時a表示乙個函式
然後遇到var a = 3;變數a幹不過函式a,a代表的還是乙個函式
最後又遇到第二個函式a宣告,後面函式a宣告替換前面的,a還是代表乙個函式但是函式體內容發生了變化 故:
console.
log(a)
;//輸出函式a,函式體內容是第二個函式宣告
var a =1;
//經過賦值之後,函式a變為了變數a,並且值為1
console.
log(a)
;//1
functiona(
)var a =3;
//變數a變為3
console.
log(a)
;//3
functiona(
) console.
log(a)
;//3a(
);//a現在是乙個變數,當然會報錯
主要想說明的一點就是function fn(a) 就相當於function fn(var a),因此預解析階段是有對這個函式內部的a的預解析的,因此在函式內部輸出的a為undefined而沒有報錯。var a =1;
function
fn(a)fn(
):console.
log(a)
;
將上面的例子稍微改動一下
將a當作實參傳遞進去之後,區域性變數a的值變為1,再函式內部將a變為2,但是在外部輸出時輸出的是全域性作用域下的a,因此還是1.var a =1;
function
fn(a)
fn(a)
://將a的值傳遞進去
console.
log(a)
;
注意在函式內部a=2;當沒有變數a的宣告時,那麼a=2生成的是全域性作用域下的a,但是當函式內部有區域性作用域下的a時,a=2僅僅就是賦值的作用
更新中…
本人是個小白,如有錯誤歡迎指正…
JS變數型別
typeof 判斷當前變數的型別 1 number 數字型別 注意 1.整數 小數 infinity 無窮大 number 0 number nan number eg var num 20 console.log typeof num 變數的重新賦值 num 3.14 console.log nu...
變數知識總結
顧名思義,變數就是在程式執行中數值可以改變的量,和上期常量一樣,變數也需要有個名字作為標識,我們這次主要概括變數識別符號的命名規則。1.整型變數 只能存放整型數值 要知道,資料在記憶體中是以二進位制形式 機器數 存放的,這就涉及到了我們常見的原碼,反碼和補碼問題了。在這裡引用一位大神對其的解釋 整型...
js的值型別
1.原始值 原始值型別分為五類 number,boolean,string,undefined,null,var a 123 var 123.2 都是定義number型別該型別可以定義為小數 var a abc var abc 都是定義string型別,定義string類可用 也可用 但var c ...