一、作用域概念-預(yù)解析規(guī)則、表達(dá)式
作用域:
域:空間甚淡,范圍,區(qū)域……
作用:讀捅厂,寫
瀏覽器——JS解析器:
<script>
alert(a);
var a=1;
function fn1(){alert(2);}
</script>
在瀏覽器專門用來讀取JS的贯卦,我們稱之為"JS解析器":
1)找一些東西:var function 參數(shù)
第一步: a = 未定義 所有的變量,在正式運(yùn)行代碼之前焙贷,都提前賦了一個值:未定義
第二步:fn1=function fn1(){alert(2);}
所有的函數(shù)撵割,在正式運(yùn)行代碼之前,都是整個函數(shù)塊
以上兩步即辙芍,JS的預(yù)解析
【注意】:遇到重名的:只留一個:
1.變量和函數(shù)重名了,就只留下函數(shù)啡彬;
(因?yàn)榈谝粋€未定義羹与,所以留函數(shù))
2.重名的函數(shù),后面的留下庶灿。
【注意】:
-
script(域) 全局變量纵搁,全局函數(shù):
自上而下
作用域鏈:子級作用域返回到父級去找,就是作用域鏈往踢。 -
函數(shù)
由里向外 - {}(對象)
2)逐行解讀代碼:
表達(dá)式:= + - * / % ++ -- 腾誉! …… 參數(shù) Number()(能改變值的都是表達(dá)式)
表達(dá)式可以修改預(yù)解析的值!
【注意思考】
<script>
alert(a);
var a=1;
</script>
為什么:用瀏覽器打開峻呕,得到是彈出框提示undefined利职?
【注意思考】
<script>
alert(a);
a=1;
</script>
為什么:用瀏覽器打開,無反應(yīng)瘦癌,打開后臺發(fā)現(xiàn)報錯猪贪?
二、全局與局部作用域解析佩憾、作用域鏈
【面試案例】:
<script>
alert(a);
var a=1;
alert(a);
function a(){alert(2);}
alert(a);
var a = 3;
alert(a);
function a(){alert(4);}
alert(a);
</script>
【結(jié)果】:
【解析】:
1)預(yù)解析:var function 參數(shù)……
/*a=…未定義
a=function a(){alert(2);}
因?yàn)橛龅街孛模褐涣粢粋€(第一個未定義,所以留函數(shù))
變量和函數(shù)重名了,就只留下函數(shù)
a=function a(){alert(2);}
a=function a(){alert(4);}
后面的干掉前面的干花,所以留下:a=function a(){alert(4);}*/
a=function a(){alert(4);}
所以得到第一個alert(a)的結(jié)果
2)逐行解讀代碼:
表達(dá)式可以修改預(yù)解析的值妄帘!
所以依據(jù)41行var a =3,第42行
(一)、script(域) 全局變量池凄,全局函數(shù):自上而下抡驼、由里向外
【注意】:
js是單線程,一個域處理完肿仑,再處理另一個域的內(nèi)容:
自上而下,內(nèi)可得外:
【案例1】
<script>
alert(a);//報錯:Uncaught ReferenceError: a is not defined
</script>
##三致盟、調(diào)用局部數(shù)據(jù)、全局聲明尤慰、for嵌套函數(shù)中i取值
<script>
var a =1;
</script>
【結(jié)果】瀏覽器無效果馏锡,后臺報錯Uncaught ReferenceError: a is not defined
【案例2】
<script>
alert(a);//undefined 因?yàn)樽兞刻嵘?var a =1;
</script>
<script>
</script>
【案例3】
<script>
var a =1;
</script>
<script>
alert(a);//彈出框1,說明域自上而下
</script>
(二)伟端、函數(shù)也是一個域(是局部的域)也要進(jìn)行解析器的兩步操作.
【案例1】:
<script>
var a=1;
function fn1(){
alert(a);//undefined
var a = 2;
alert(a);//2
}
fn1();
alert(a);//1
</script>
【解析】:
1)**預(yù)解析:var function 參數(shù)……**
a=1
fn1=function fn1(){
alert(a);
var a = 2;
}
2)**逐行解讀代碼:**
**表達(dá)式**
**函數(shù)調(diào)用** (函數(shù)也是一個域,是局部的域杯道,所以調(diào)用后,進(jìn)行預(yù)解析——解讀)
1>**預(yù)解析:var function 參數(shù)**
a=…
2>**逐行解讀代碼**
【案例2】:
<script>
var a=1;
function fn1(){
alert(a);//1责蝠;自內(nèi)向外党巾,獲取外部的1
a = 2;
}
fn1();
alert(a);//2:自上而下,因表達(dá)式獲取12行的2霜医,所以這里為2
</script>
★作用域鏈:子級作用域返回到父級去找齿拂,就是作用域鏈。
<script>
var a=1;
function fn1(a){
alert(a);//undefind:這里是獲取參數(shù)a,調(diào)用時無即未傳參肴敛,則參數(shù)無署海,所以為undefined
a = 2;
alert(a);//2 參數(shù)a因?yàn)楸磉_(dá)式賦值為2
}
fn1();
alert(a);//1
</script>
★參數(shù)本質(zhì)上是局部變量吗购;此例子中未傳參則為undefined;
函數(shù)調(diào)用:
再次說明叹侄,出現(xiàn)函數(shù)調(diào)用了巩搏,函數(shù)內(nèi)部即是作用域,需要進(jìn)行預(yù)解析和逐行解讀代碼趾代。
【案例3】:
<script>
var a=1;
function fn1(a){
alert(a);//1:參數(shù)a也是個變量
a = 2;
}
fn1(a);
alert(a);//1
</script>
【解析】:
參數(shù)是局部變量贯底,而且參數(shù)還是個表達(dá)式
三、調(diào)用局部數(shù)據(jù)撒强、全局聲明禽捆、for嵌套函數(shù)中i取值
【案例1】
<script>
var sum =0;
function fn1(){
num++;//作用域鏈的原理,里面獲取外面的
}
fn1();
var sum =0;
function fn2(){
num--;//作用域鏈的原理飘哨,里面獲取外面的
}
fn2();
fn1();
fn2();
alert(num);//-1
</script>
【案例2】:
<script>
function fn1(a){
var a='大雞腿~';
}
fn1();
alert(a);//報錯:Uncaught ReferenceError: a is not defined胚想;因?yàn)橥饷娴牟荒苷业嚼锩娴?</script>
上面兩個例子說明,★函數(shù)只可內(nèi)獲取到外芽隆,外面獲取不到內(nèi)浊服。內(nèi)即是局部,外即是全局胚吁。
四牙躺、那么外部如何獲取函數(shù)內(nèi)的值?
★想要獲取函數(shù)內(nèi)的值:
方法一:通過全局變量腕扶,獲取函數(shù)內(nèi)的內(nèi)容
<script>
var str="";
function fn1(){
var a='大雞腿~';
str=a;
}
fn1();
alert(str);//彈出大雞腿:通過全局變量獲取到了函數(shù)里面的內(nèi)容
</script>
方法二:通過參數(shù)傳統(tǒng)實(shí)現(xiàn)的局部調(diào)用
script>
function fn2(){
var a="大雞腿";
fn3(a);
}
fn2();
function fn3(a){
alert(a);
}
</script>
五孽拷、if(){}和for(){}不是作用域,證明:
<script>
alert(a);
function fn1(){
var a =1;
}//報錯
</script>
不要把函數(shù)和變量var放在if或者for循環(huán)內(nèi)
<script>
//alert(a);//undefined
alert(fn1);//function fn1(){
//alert(123);
//}但是有些函數(shù)讀取不出來半抱,所以不要把函數(shù)和變量var放在if或者for循環(huán)內(nèi)
if(true){
var a =1;
function fn1(){
alert(123);
}
}
</script>
六脓恕、其他
<script>
window.onload = function (){
var aBtn = document.getElementsByTagName('input');
for( var i=0; i<aBtn.length; i++ ){
aBtn[i].onclick = function (){
alert(i);//3
};
}
};
</script>
上面的源碼:alert(i);//3
<script>
window.onload = function (){
var aBtn = document.getElementsByTagName('input');
for( var i=0; i<aBtn.length; i++ ){
aBtn[i].onclick = function (){
alert(i);//undefined
for( var i=0; i<aBtn.length; i++ ){
aBtn[i].style.background = 'yellow';
}
};
}
};
</script>
上面的源碼:alert(i);//undefined
<script>
window.onload = function (){
var aBtn = document.getElementsByTagName('input');
for( var i=0; i<aBtn.length; i++ ){
aBtn[i].onclick = function (){
alert(i);//3
for( i=0; i<aBtn.length; i++ ){
aBtn[i].style.background = 'yellow';
}
};
}
};
</script>
上面的源碼alert(i);//3