1.js變量的查找
js中函數(shù)嵌套是十分普遍的
對(duì)變量是如何尋找的谬哀?------->從內(nèi)部向外部尋找
首先在函數(shù)內(nèi)尋找
找不到就在外層找
直到全局(window)區(qū)域
源碼例子
var c=5;
function t1(){
var d=6;
function t2(){
var e=7;
//var d=3; 去掉注釋觀察結(jié)果的變化
alert(c+d+e);
}
t2();
}
t1();//分別得到15,18
2.聲明變量var的作用
alert(window.d);//undefine
alert(window.e);//undefine
function t(){
d=5;
var e=6;
}
t();
alert(window.d);//5 沒有加var就是僅僅是賦值操作故爵,尋找t域內(nèi)的函數(shù)玻粪,沒有找到隅津,繼續(xù)尋找。劲室。伦仍。。>window-->window.d=5
alert(window.e);//undefine
//var 是在函數(shù)運(yùn)行的上下文中很洋,申明一個(gè)變量 如果不加var充蓝,則是一個(gè)賦值操作,不要狹隘理解為創(chuàng)造了一個(gè)全局變量
function t1(){
var d;
function t2(){
d=5;
e=6;
}
t2();
}
t1();
console.log(d);//d is not defined錯(cuò)誤
console.log(e);//6
console.log(window.d);//undefine
//注意:以window.xxx引用全局變量喉磁,尋找不到作為某個(gè)屬性不存在谓苟,返回 undefined 直接以xxx引用某變量尋找不到則是報(bào) xxx is not define 錯(cuò)誤
例題
var str1='global';
function t1(){
console.log(str1);//返回global
console.log(str2);//報(bào)str2 is not defined
str2='local';//做了window.str2='local'這樣一個(gè)操作
}
t1();
//在t1尋找str1---沒有,在window上尋找str1---有 打印global
//在t1尋找str2---沒有协怒,在window上尋找str2---沒有涝焙,報(bào)str2 is not defined
//(實(shí)際上出錯(cuò)還沒有執(zhí)行到這一些)才把全局的str2的變量賦值上去
var str1='global';
function t1(){
console.log(str1);//返回global
console.log(str2);//返回undefined
var str2='local';
}
t1();
js代碼自上而下執(zhí)行
但是js代碼在整體運(yùn)行分為 詞法分析期 ,運(yùn)行期
自上而下執(zhí)行之前孕暇,先有個(gè)詞法分析過程
------------------------------------------------例如---------------------------------------------------------------
第一步:先分析t1函數(shù)
分析出t1內(nèi)有str2局部變量仑撞,注意此時(shí)代碼未運(yùn)行str2未賦值,所以str2的值是undefined
第二步:執(zhí)行t1函數(shù)
console.log(str1);//返回global
console.log(str2);//返回undefined
str2='local'//此時(shí)str2的值為local
3.詞法分析
詞法分析
第一步:分析參數(shù)
第二部:分析變量聲明
第三步:分析函數(shù)聲明
一個(gè)函數(shù)能使用的全局變量妖滔,就是按照上面的三個(gè)步驟分析而來的
具體步驟:
0:函數(shù)運(yùn)行前的瞬間隧哮,生成active object(活動(dòng)對(duì)象),下面簡(jiǎn)稱為ao
1:函數(shù)聲明的參數(shù)形成ao的屬性座舍,參數(shù)的值就是屬性的值沮翔,接收實(shí)參,形成ao相應(yīng)屬性的值
2:分析變量的聲明
如果ao沒有有age屬性則添加為ao屬性曲秉,值全是undefined
如果ao上已經(jīng)有age屬性采蚀,則不做任何影響
3:分析函數(shù)申明,如function foo(){}
把函數(shù)賦給ao.foo屬性
注:如果此時(shí)foo屬性已經(jīng)存在岸浑,則被無情覆蓋
實(shí)例1
function t(age){
alert(age);
}
t(5);//5
t();//undefined
/*
詞法分析過程
ao{age:undefined}
運(yùn)行過程:
t(5)-->ao.age=5;alert(ao.age);//5
t()--->ao.age沒有得到賦值還是undefined
*/
實(shí)例2
function t2(age){
var age=99;
alert(age);
}
t2(5);
/*
分析過程:
0:形成ao={}
1:分析形參ao={age:undefined}
接收形參ao={age:5}
2:分析var age搏存,發(fā)現(xiàn)ao已經(jīng)有age屬性,不做任何影響
執(zhí)行過程:
ao.age=99;
alert(age);
*/
實(shí)例3
function t3(greet){
var greet='hello';//試著變成var greet試一下
alert(greet);
function greet(){
}
alert(greet);
}
t3(null);//hello hello
/*
詞法分析過程:
0:ao={}
1:分析參數(shù)ao={greet:undefined}
接收形參ao={greet:null}
2:分析greet變量聲明矢洲,ao已經(jīng)有g(shù)reet 屬性璧眠,因此不做任何影響
3:分析greet函數(shù)聲明,ao.greet=function(){},被覆蓋為函數(shù)
執(zhí)行過程:
greet='hello';
alert(greet);//---------->hello
alert(greet);//---------->hello
*/
實(shí)例4
function a(b){
alert(b);
function b(){
alert(b);
}
b();
}
a(1);
/*
分析:
0:ao={}
1:分析參數(shù)ao= {b:undefined}
接收參數(shù)ao={b:1}
2:分析var 聲明读虏,此函數(shù)沒有var
3:分析函數(shù)聲明责静,ao={b:function{alert(b);}}
執(zhí)行:
alert(b);
*/
實(shí)例6
function a(b){
alert(b);
b=function(){
alert(b);
}
b();
}
a(1);
/*
分析:
0:生成ao對(duì)象ao={}
1:分析參數(shù)ao={b:undefined}-->{b:1}
2:分析var聲明--->沒有
3:分析函數(shù)聲明,--->沒有盖桥,b=function(){}是一個(gè)賦值過程灾螃,是函數(shù)表達(dá)式返回值賦給變量b,這是一個(gè)賦值過程,要在執(zhí)行過程中生效
執(zhí)行:
alert(b);//1
b=function(){
alert(b);
}
b();//function
*/
4.函數(shù)聲明和函數(shù)表達(dá)式
js被稱為披著c外衣的lisp語言揩徊,
lisp是一種強(qiáng)大的函數(shù)式語言
函數(shù)的地位比較高腰鬼,函數(shù)可以作為參數(shù)來傳遞嵌赠,可以復(fù)制給變量
function t1(){}//t1是函數(shù)聲明
t2=function(){}//t2是函數(shù)賦值過程,值是右側(cè)表達(dá)式的返回結(jié)果
//function(){}在js看來就是3+2一樣熄赡,是一個(gè)表達(dá)式姜挺,返回一個(gè)結(jié)果
//因此,t1 t2 在詞法分析過程有著明顯的區(qū)別彼硫,前者在詞法分析階段就發(fā)揮作用炊豪,后者在運(yùn)行階段才發(fā)揮作用
(function (window.undefined){})(window);
//這是jquery的最外層代碼
(function(window.undefined))//內(nèi)層表達(dá)式,返回值是函數(shù)拧篮,包在小括號(hào)內(nèi)词渤,當(dāng)成表達(dá)式來使用
(window)//立即調(diào)用,并傳一個(gè)window
//而內(nèi)層函數(shù)沒有起名字串绩,叫匿名函數(shù)缺虐,這種方法好處: 立即執(zhí)行不污染全局,稱為 立即執(zhí)行匿名函數(shù)表達(dá)式
//為什么傳window不傳undefined赏参?
//傳window是為了速度志笼,加快內(nèi)部查找全局變量的速度,直接把window以參數(shù)形式傳進(jìn)來把篓,這樣window就在jquery內(nèi)部的ao上
function(){
function(){
function(){
function{
function(){
document.getElementById()//這個(gè)document會(huì)將作用域?qū)訉由险遥钡阶钔鈱? }
}
}
}
}
//不傳undefined是為了安全腰涧,在ie低版本張韧掩,undefined竟然可以重新賦值,如undefined=3
//聲明undefined局部變量(名字是undefined而已)窖铡,同時(shí)又不傳參疗锐,值自熱是undefined,阻止了外界對(duì)undefined的污染
5.作用域鏈
JavaScript 開發(fā)進(jìn)階:理解 JavaScript 作用域和作用域鏈
Js作用域與作用域鏈詳解