一. 作用域
所有編程語言都有一最基本的功能帆竹,就是能夠存儲(chǔ)變量當(dāng)中的值,并且能在之后對這個(gè)值進(jìn)行訪問或者修改。
那么就會(huì)有下面這么幾個(gè)問題:
1.這些變量存儲(chǔ)在什么地方孝偎??
2.程序需要訪問或者修改變量時(shí)如何找到它們凉敲?邪媳?
一門語言中會(huì)設(shè)計(jì)一套良好的規(guī)則來解決上述的問題捐顷,而這套規(guī)則就就是所謂的作用域。
二 . 詞法作用域與動(dòng)態(tài)作用域
作用域共有兩種主要的工作模型:
1.詞法作用域:大多數(shù)編程語言使用的模型雨效,作用域的規(guī)則是由你在寫代碼時(shí)將變量和塊作用域?qū)懺谀睦餂Q定的迅涮;
2.動(dòng)態(tài)作用域:仍有一部分編程語言在使用(bash,perl)徽龟,作用域是在代碼執(zhí)行過程中確認(rèn)的叮姑;
三. JavaScript的作用域規(guī)則
javascript的作用域規(guī)則屬于詞法作用域即靜態(tài)作用域。
代碼執(zhí)行前會(huì)進(jìn)行的編譯据悔,編譯器負(fù)責(zé)生成可執(zhí)行代碼传透,js引擎執(zhí)行時(shí),遇到變量時(shí)极颓,會(huì)通過查找變量來判斷他是否已聲明過朱盐。查找的過程由作用域進(jìn)行協(xié)助,但是js引擎執(zhí)行怎樣查找菠隆?
當(dāng)前作用域對變量的查找遵循以下兩個(gè)規(guī)則兵琳,首先提出兩個(gè)術(shù)語:
RHS:(retrueve his source value)右查詢,變量出現(xiàn)在賦值操作的右側(cè)骇径;
LHS:左查詢躯肌,變量出現(xiàn)在賦值操作的左側(cè);
注: 并不全是 "=賦值操作符的左側(cè)和右側(cè)";
// 如下面的代碼
function ?foo(a){
// 被調(diào)用時(shí)會(huì)有a = 2 ? 對a進(jìn)行的LHS
console.log(a); ?// console RHS ? 和 ?a RHS
}?
foo(2); ? // foo()進(jìn)行的是 RHS
作用域的嵌套
當(dāng)在當(dāng)前作用域查找不到該變量時(shí)破衔,會(huì)繼續(xù)向上當(dāng)前作用域的上一級作用域查找清女,當(dāng)?shù)诌_(dá)最外層的全局作用域時(shí),無論找到還是沒找到晰筛,查找過程都會(huì)停止嫡丙。
js中目前只有全局作用域和函數(shù)作用域,作用域的嵌套也只會(huì)出現(xiàn)這兩種的情況下读第,
注:es6中引入了塊級作用域迄沫。
最后,讓我們看一個(gè)《JavaScript權(quán)威指南》中的例子:
var scope="global scope";
function ?checkscope(){
var ?scope="local scope";
function ?f(){
return scope;
}
return ?f();
}
checkscope();
var ?scope="global scope";
function ?checkscope(){
var ?scope="local scope";
function ?f(){
return ?scope;
}
return ?f;
}
checkscope()();
猜猜兩段代碼各自的執(zhí)行結(jié)果是多少卦方?
這里直接告訴大家結(jié)果羊瘩,兩段代碼都會(huì)打印’local scope’。
引用權(quán)威指南的回答就是:
JavaScript函數(shù)的執(zhí)行用到了作用域鏈盼砍,這個(gè)作用域鏈?zhǔn)窃诤瘮?shù)定義的時(shí)候創(chuàng)建的尘吗。嵌套的函數(shù)f()定義在這個(gè)作用域鏈里,其中的變量scope一定是局部變量浇坐,不管何時(shí)何地執(zhí)行函數(shù)f()睬捶,這種綁定在執(zhí)行f()時(shí)依然有效。
但是在這里真正想讓大家思考的是近刘,兩段代碼執(zhí)行的結(jié)果一樣擒贸,但是兩段代碼究竟有哪些不同呢臀晃?