- RegExp對象
******Function****** - 回顧函數
- 創(chuàng)建函數三種方式
- 重載
- 匿名函數
- 作用域和作用域鏈
一. RegExp對象:
問題: 其實屹蚊,js語言默認看不懂正則表達式的废亭!就要一種東西缺虐,可以將正則表達式翻譯為js可以看懂的內容篮撑,并執(zhí)行驗證和查找功能喉誊。
什么是RegExp對象: 專門在js中保存一條正則表達式,并提供驗證和查找功能的特殊對象独令。
何時: 今后只要想在js中用正則表達式執(zhí)行驗證和查找功能,都要用RegExp對象
-
如何創(chuàng)建: 2種方式:
(1). 標準: var 變量=new RegExp("正則","ig");
a. 今后液肌,只要正則表達式需要用程序動態(tài)生成時,都用new RegExp()來創(chuàng)建
b. 原理: new RegExp()中需要的是一個字符串類型的正則表達式鸥滨。而在js語言中嗦哆,有無數種方法,可以拼接出我們想要的任意字符串來婿滓!
c. 坑: 正則中有\(zhòng)d等寫法老速,js的字符串中也有\(zhòng)t、\n寫法凸主。正則中的\和js字符串中的\沖突了橘券!
d. 解決: 今后,只要在new RegExp()的""中出現\卿吐,都要改為\
比如: new RegExp("\d{6}") //6位數字
應該改為: new RegExp("\d{6}")
其中: 第一個\是js中的轉義字符旁舰,意思是告訴js,后續(xù)的內容與js字符串無關嗡官!不要按js解析箭窜!
第二個\才是和\d組合的正則表達式字符集,表示一位數字衍腥。
js地盤 |正則| js地盤
(2). 簡寫: var 變量=/正則/ig;
a. 問題: //之中是正則表達式的地盤磺樱,其中不認識js變量或js表達式。
b. 所以婆咸,將來只有正則表達式是固定不變的時候竹捉,才會用//來創(chuàng)建正則表達式。如果正則表達式需要用程序動態(tài)生成時擅耽,是不能用//創(chuàng)建正則表達式的。
c. 比如: 手機物遇、電子郵件乖仇、url網址...(1). 示例: 根據數組內容查找多種敏感詞
1_new_RegExp.html
<script>
//在服務器端保存一個數據庫表憾儒,其中保存所有要防守的敏感詞。
//用服務器端接口和ajax乃沙,將要防守的敏感詞查詢回前端js程序中
//假設起趾,我們從服務器端請求來一個包含敏感詞的數組
var arr=["我草","wocao","尼瑪","nmb","sb"];
// var str=arr.join("|");//將數組arr中所有元素用|相連拼接為一個大的字符串
// console.log(str);
//驗證用戶輸入的內容中,是否包含敏感詞
//1. 請用戶輸入一條消息內容
var str=prompt("請輸入消息內容");
//2. 用search去消息中查找是否包含敏感詞
var reg=new RegExp(arr.join("|"),"i");
var i=str.search(reg);//i ignore 忽略大小寫警儒!
//如果找到训裆,返回>=0的一個下標
//如果沒找到,返回-1
//3. 判斷如果search找到了敏感詞
if(i!=-1){
//就提示: 包含敏感詞蜀铲,禁止發(fā)送边琉!
console.error("包含敏感詞,禁止發(fā)送")
}else{//4. 否則如果search沒找到敏感詞
//就提示: 然哥說: xxxx
console.log(`然哥說:${str}`);//復習一階段模板字符串
}
</script>
5. 驗證字符串格式:
(1). var 驗證結果=正則表達式對象.test(要驗證的字符串)
(2). 意為: 用正則表達式驗證要驗證的字符串是否符合格式要求记劝!
(3). 返回值: 如果字符串符合正則表達式要求变姨,就返回true;否則厌丑,如果字符串不符合正則表達式要求定欧,就返回false。
(4). 問題: 正則表達式默認怒竿,只要部分匹配就返回true砍鸠。默認不要求從頭到尾必須完整匹配.
(5). 解決: 今后,只要要求必須重頭到尾完整匹配耕驰,就必須同時前加^爷辱,后加$。
(6). 示例: 驗證用戶輸入的手機號格式是否正確:
<script>
//請用戶輸入一個手機號
var str=prompt("請輸入手機號");
//用正則表達式驗證用戶輸入的手機號格式是否正確
var reg=/^1[3-9]\d{9}$/;
var result=reg.test(str);
//如果驗證通過
if(result==true){
//則輸出手機號格式正確
console.log(`手機號格式正確`)
}else{//否則如果驗證不通過
//就輸出手機號格式不正確
console.error(`手機號格式不正確`)
}
</script>
6. 查找敏感詞:
(1). 只查找一個敏感詞的內容和位置:
a. var 數組=正則表達式對象.exec(字符串)
b. 意為: 在字符串中查找第一個符合正則表達式對象要求的敏感詞的內容和位置耍属。
c. 與search()的差別:
1). search()托嚣,只能獲得敏感詞的位置,無法獲得敏感詞的內容
2). exec()厚骗,既可獲得敏感詞內容示启,又可獲得敏感詞位置
d. 返回值:
1). 如果找到敏感詞,就會返回一個數組:
i. 數組: [ 0: "敏感詞的內容", index:敏感詞的下標位置 ]
ii. 比如: 那天领舰,我去了她家夫嗓,我說:我草!你家真大
0 1 2 3 4 5 6 7 8 9 0 1 2
會返回數組: [ 0:"我草", index:12 ]
iii. 強調: exec()是瀏覽器已經定義好的函數冲秽。不是我們自己寫的舍咖!所以,用別人寫好的函數锉桑,首先要學會聽話排霉!別人說,讓你去哪個位置訪問民轴,你就只能去那個位置訪問攻柠!背過球订!沒有為什么!
iv. 所以:
想獲取本次找到的敏感詞內容:
數組["0"]瑰钮,可簡寫為: 數組[0]
想獲取本次找到的敏感詞位置:
數組["index"]冒滩,可簡寫為: 數組.index
2). 如果沒找到敏感詞,就返回null浪谴。
所以开睡,可以用if(數組!=null)來判斷本次是否找到了敏感詞
e. 示例: 查找一個敏感詞的內容和位置:
<script>
//驗證用戶輸入的內容中,是否包含敏感詞
//1. 請用戶輸入一條消息內容
var str=prompt("請輸入消息內容");
//2. 用search去消息中查找是否包含敏感詞
var reg=/我草|wocao|尼瑪|nmb/i;//i ignore 忽略大小寫苟耻!
var arr=reg.exec(str);
//如果找到篇恒,返回有內容的數組
//如果沒找到,返回null
//3. 判斷如果exec找到了敏感詞
if(arr!=null){
//就提示: 包含敏感詞梁呈,禁止發(fā)送婚度!
//標準寫法
// console.error(`在位置${arr["index"]}發(fā)現敏感詞${arr["0"]},禁止發(fā)送!`);
//簡寫:
console.error(`在位置${arr.index}發(fā)現敏感詞${arr[0]}官卡,禁止發(fā)送!`);
}else{//4. 否則如果search沒找到敏感詞
//就提示: 然哥說: xxxx
console.log(`小明說:${str}`);
}
</script>
f. 問題: 只能查找一個敏感詞蝗茁,無法查找所有敏感詞。
(2). 查找所有敏感詞內容和位置
a. 2步:
1). 正則表達式要加后綴g寻咒,意為global哮翘,表示全部。
i. 依然無法找所有毛秘。
ii. 因為reg.exec()采用狗熊掰棒子的方式饭寺,查找敏感詞的。
每次只能找一個敏感詞叫挟,放入數組中艰匙。數組中也只能放一個敏感詞的內容和位置.
再找下一個敏感詞時,就會丟棄舊的敏感詞抹恳,把數組中換成新的敏感詞员凝。結果,數組中始終只保存一個敏感詞奋献。
2). 必須配合循環(huán)反復調用健霹!
var reg=/正則/g;
//無論字符串是否包含敏感詞,都要先找一次瓶蚂,才能確定是否有必要繼續(xù)找糖埋。
do{//所以,選擇do while循環(huán)
var arr=reg.exec(字符串);
if(arr!=null){
對本次找到的數組arr內容執(zhí)行操作
}
}while(arr!=null); //只有本次找到了敏感詞窃这,才有必要繼續(xù)找下一次
b. 示例: 查找字符串中所有以小字開頭的人名瞳别。
<script>
var str="老師:請用小紅 我的 朋友造句。小亮:小紅是我的朋友。小然:朋友祟敛!小紅是我的倍奢!";
//找出這句話中所有以小字開頭的人名
var reg=/小[紅亮然]/g; //global,找所有
do{
//先找一次
var arr=reg.exec(str);//最后一次會返回null
//而null是不能加.調用index和[0]的垒棋。
//加判斷
//只有這次找到的不是null時,才執(zhí)行操作
if(arr!=null){
console.log(`在位置${arr.index}發(fā)現人名:${arr[0]}`);
}//否則如果這次找到的已經是null痪宰,就什么也不做叼架!
}while(arr!=null);//只有本次找到了敏感詞,才有必要繼續(xù)找下一次衣撬!
</script>
****Function****
一. 回顧函數:
問題: 在程序中有很多代碼片段乖订,可能被多次反復使用。如果重復編寫很多遍具练,或復制粘貼很多遍乍构,極其不便于維護。修改時扛点,復制過多少次副本哥遮,就要重復修改多少處!只要有一處忘記修改陵究,程序就會出錯眠饮!
解決: 今后,只要會被反復使用的代碼段铜邮,都要保存在函數中仪召,并反復調用函數。
什么是函數: 內存中松蒜,一塊專門存儲代碼片段的存儲空間扔茅,再起一個名字。
-
如何: 2步:
(1). 定義函數秸苗,保存一段可重用的代碼片段召娜,再起一個名字:
function 函數名(){
要反復調用的代碼片段
}
其中: function是new Function()的縮寫!程序中难述,只要讀到一個function萤晴,就會立刻在內存中,創(chuàng)建一個存儲空間胁后,用來存儲一端代碼片段店读。
問題: function,只負責創(chuàng)建新函數攀芯,保存代碼片段屯断,不負責執(zhí)行函數!(2). 調動函數:
a. 函數名();
b. 意為: 讓程序找到指定名稱的函數,自動執(zhí)行函數中的代碼片段殖演。
c. 問題: 函數內的變量都是寫死的氧秘!一個函數無法處理多種不同數據的情況
5. 定義參數:
(1). 何時: 今后,只要一個函數內部有不確定來源的變量時(不是我自己var的)趴久,都要為函數定義參數丸相。
(2). 如何: 2步:
a. 在創(chuàng)建函數時,定義形參變量:
function 函數名(形參變量1, 形參變量2, ...){
函數體中:
就可使用形參變量1和形參變量2暫時為將來可能的數據占位彼棍。
}
b. 將來調用函數時灭忠,給函數的形參變量傳遞實參值
函數名(實參值1, 實參值2,...)
(3). 問題: 無法對函數的執(zhí)行結果,繼續(xù)執(zhí)行后續(xù)操作座硕!
6. 返回值:
(1). 何時: 今后弛作,只要函數的外部,需要獲得函數的執(zhí)行結果华匾,繼續(xù)執(zhí)行后續(xù)操作時映琳,都要為函數定義返回值。
(2). 如何: 2步:
a. 創(chuàng)建函數時:
function 函數名(形參列表){
函數體
return 執(zhí)行結果
}
b. 調用函數時:
var 變量=函數名(實參值列表);
c. 結果: 程序先調用函數蜘拉,函數內的return關鍵字萨西,會將執(zhí)行結果拋出/返回到主程序中,保存到=前的變量里旭旭。之后就可被反復使用了原杂!
- 示例: 定義函數,對數組內容求和
6_function.html
<script>
//希望sum函數可對任意一個數組求和
//因為函數內只有一個變量arr1將來不確定來源您机。
//所以穿肄,只定義一個形參為將來可能的一個數組占位
// 預留
function sum(arr){
//先定義一個變量result,準備接住后邊遍歷出的每個數組元素的值
var result=0;
//遍歷數組中每個元素值
// 預留
for(var i=0;i<arr.length;i++){
//將當前i位置的元素值累加到result變量上
// 預留
result+=arr[i];
}
//循環(huán)結束后际看,變量result中就保存了數組所有元素的和
//把求和的結果返回到函數外部
return result;
}
var arr1=[1,2,3];
//對數組1求和
var result1=sum(arr1); //arr1->sum函數的arr形參
//在求和后咸产,再對數組1求平均: 和/個數
console.log(`平均值為:${result1/arr1.length}`);
var arr2=[1,2,3,4,5];
//對數組2求和
var result2=sum(arr2); //arr2->sum函數的arr形參
//在求和后,再對數組2求平均
console.log(`平均值為:${result2/arr2.length}`);
//求數組1和數組2的總和
console.log(`總和:${result1+result2}`);
</script>
- 函數執(zhí)行的本質:
(1). 所有程序自己都是不會執(zhí)行的仲闽!
(2). 所有創(chuàng)建函數脑溢,調用函數,傳參赖欣,遍歷數組屑彻,計算,賦值都是由js引擎程序幫我們完成顶吮!
二. 創(chuàng)建函數: 3種方式:
1. 用聲明方式: 必須包含四樣東西: function社牲,函數名,()悴了,{}
(1). function 函數名(形參列表){
函數體
return 返回值
}
(2). 問題: 會被聲明提前
a. 什么是:
1). 在程序開始執(zhí)行前——時機
2). js引擎會掃描程序中2樣東西:
var聲明的變量 和 function聲明的函數
3). 將這兩樣東西提前到當前作用域的頂部集中創(chuàng)建搏恤。
4). 賦值會被留在原地
5). 當聲明提前階段結束后违寿,才開始正式執(zhí)行程序的所有代碼!
b. 缺點: 聲明提前打亂了程序正常的執(zhí)行順序熟空!極容易造成歧義和錯誤——JS語言廣受詬病的缺陷
c. 鄙視時: 只要碰到聲明提前的題藤巢,都要先把程序改造成聲明提前之后的樣式!再開始讀改造后程序息罗!
2. 用賦值方式創(chuàng)建:
(1). var 函數名=function(形參列表){
函數體
}
(2). 結果和第一種聲明方式創(chuàng)建出來的函數是完全一樣的掂咒!
(3). 優(yōu)點: 因為這個格式不符合聲明提前的語法格式,所以不會被提前迈喉!
(4). 總結: 今后俏扩,創(chuàng)建函數時,強烈建議都用賦值方式弊添。
(5). 示例: 判斷聲明提前的程序的輸出結果:
_hoist.html
<script>
console.log(a);//undefined
var a=10;
console.log(a);//10
// function fun(){ console.log(1) }
// fun();//2
// function fun(){ console.log(2) }
// fun();//2
var fun=function(){ console.log(1) }
fun();//1
var fun=function(){ console.log(2) }
fun();//2
</script>
運行結果:
undefined
10
1
2
- 用new: (幾乎不用)
(1). var 函數名=new Function("形參1","形參2",...,"函數體")
(2). 揭示了: js中函數本質上也是一個引用類型的對象
a. 程序中所有小寫的function,運行時都會被自動翻譯為new Function捌木。都會自動創(chuàng)建一個新對象油坝,保存函數的定義。每個函數對象都有自己唯一的地址值刨裆。
b. 函數也可以用作變量賦值和傳參澈圈。
c. 兩個長得完全一樣的函數,做==比較帆啃,返回false瞬女!
因為兩個引用類型的對象做==比較,比的是地址值努潘。
三. 重載(overload):
問題: 實際開發(fā)中诽偷,經常遇到一件事,可能根據傳入的參數不同疯坤,執(zhí)行不同的邏輯报慕。但是,如果為一件事压怠,創(chuàng)建多個不同名稱的函數眠冈,將來調用時,極其麻煩菌瘫!
解決: 重載
-
什么是: 為一件事蜗顽,定義多個相同函數名,不同參數列表的多個函數雨让。在調用時雇盖,程序可以自動根據我傳入的實參值不同,自動選擇執(zhí)行對應版本的函數栖忠!
優(yōu)點: 即使一個任務有多種不同的邏輯刊懈,也不用其很多的函數名这弧。只需要一個函數名即可!
問題: js中不允許多個同名函數同時存在虚汛。如果存在匾浪,只有最后一個同名函數才能留下在!覆蓋之前所有同名函數卷哩!——所以蛋辈,js中不能用類似于Java中的重載!
解決: js中要變通實現: 2步:
(1). 只定義一個函數将谊,且不要定義任何形參變量冷溶!
(2). 在函數內,自動由arguments對象接住所有的實參值尊浓。
a. 什么是: arguments對象是:
1). 每個函數中都自帶的——不用我們自己創(chuàng)建逞频,就可直接使用
2). 專門自動接受所有傳入函數的實參值的——內容
3). 類數組對象——格式/存儲結構
i. 什么是: 長的像數組的對象:
ii. 和數組相比:
相同點: 1. 數字下標, 2. length, 3. for循環(huán)遍歷
不同點: 類數組對象不是數組類型的對象,而是Object類型的對象栋齿,不能使用數組家提供的所有函數苗胀。
b. 示例: 使用重載實現一個函數根據傳入參數不同執(zhí)行不同的付款方式
9_overload.html
<script>
//想定義三個函數,分別實現三種支付方式:
//手機支付: 不需要提供任何參數
//現金支付: 需要給服務員現金
//刷卡支付: 需要給服務員卡號瓦堵,而且還要輸入密碼
function pay( ){
// arguments[ ].length
// 0 1 2 3 ...
console.log(arguments);
//希望沒有傳入實參值基协,則手機支付
if(arguments.length==0){
console.log(`手機支付...`)
}else if(arguments.length==1){//否則如果只傳入一個實參值,則現金支付
//第一個實參值
console.log(`現金支付菇用,收您${ arguments[0] }元`)
}else{//否則其余都刷卡支付
//第一個實參值
console.log(`刷卡支付澜驮,從您卡號${arguments[0]}扣款成功`)
}
}
pay();
pay(100);
pay("6553 1234","123456");
</script>
運行結果:
四. 匿名函數:
- 什么是: 定義函數時,不指定函數名的函數
- 為什么: 2個原因:
(1). 節(jié)約內存: 匿名函數沒有變量引用著惋鸥,用完就釋放了杂穷!
(2). 避免不同功能之間的程序互相干擾: 因為匿名函數也是函數,只要是函數卦绣,就都是作用域亭畜。內部的數據就無法超出函數的范圍影響外部。 - 何時: 兩種場景:
(1). 今后迎卤,只要回調函數拴鸵,盡量都要用匿名函數
(2). 今后,只要擔心一個功能的數據和另一個功能的數據之間互相干擾蜗搔,就都可以用匿名函數自調劲藐,將不同的功能分塊包裹起來!
五. 作用域(scope)和作用域鏈
對應小程序視頻: 小程序->在線->JSCORE->day01 6. 簡單作用域
- 什么是作用域: 一個變量的使用范圍樟凄。
- 為什么: 避免不同范圍之間的變量互相干擾聘芜。
- 包括: 2級:
(1). 全局作用域:
a. 什么是: 在程序的任何位置都可以訪問到的范圍
b. 其實:
1). 全局作用域也是一個對象: window
2). 其實我們在全局范圍內創(chuàng)建的所有變量和函數,默認都是保存在window中缝龄。
(2). 函數作用域:
a. 什么是: 只能在函數內訪問的范圍
b. 函數作用域中創(chuàng)建的變量或函數汰现,出了函數的范圍都不能使用挂谍!
c. 在使用變量時:
1). 優(yōu)先使用函數作用域內的局部變量
2). 局部沒有,才被迫去全局范圍內查找瞎饲。 - 示例: 簡單作用域練習:
11_scope.html
<script>
//全局作用域
var a=10;
function fun1(){
//函數作用域
var a=100;
a++;
console.log(a)
}
fun1();//101
console.log(a);//10
var b=10;
function fun2(){
b=100;
b++;
console.log(b)
}
fun2();//101
console.log(b);//101
console.log(window);//全局作用域
</script>
</body>
</html>
運行結果:
101
10
101
101
5. 作用域原理: 一個函數的調用過程: 4個階段:
(1). 定義函數時:
a. 在程序開始執(zhí)行時口叙,都會自動創(chuàng)建一個全局作用域對象window
b. 我們定義的所有全局變量和全局函數,都自動保存在window中
c. 每個函數對象身上嗅战,都有一個"好友列表"妄田,保存著一個函數可用的所有作用域對象的地址。
d. 每個函數的好友列表中驮捍,默認只有兩個格子:
1). 離函數近的格子疟呐,暫時空著,預留
2). 離函數遠的格子东且,保存著全局作用域對象window的地址
(2). 調用函數前: (做菜之前——備料)
a. 臨時創(chuàng)建函數作用域對象启具,將函數作用域對象的地址保存到函數對象的好友列表中,離函數近的格子里
b. 掃描函數中是否包含局部變量珊泳。如果函數中包含局部變量鲁冯,則js引擎自動在函數作用域對象中定義局部變量
(3). 調用函數時: (按菜譜做菜)
a. js引擎依次讀取函數中記錄的每行代碼執(zhí)行。
b. 當遇到要使用變量時旨椒,js引擎會按照好友列表中就近原則來使用所有的變量
a. 優(yōu)先去函數作用域對象中查找局部變量使用
b. 如果局部沒有要用的變量,則自動延好友列表向全局去找變量使用
(4). 函數調用后: (做完菜之后——收拾廚房)
a. 自動將函數對象的好友列表中離自己近的一個格子清空堵漱。
b. 導致综慎,函數作用域對象沒人要了!釋放了.
c. 導致勤庐,所有局部變量也就釋放了示惊!
d. 但是: 函數對象是不會釋放的!
6. 作用域鏈:
(1). 什么是: 每個函數對象身上都自帶的愉镰,保存這個函數可用的所有作用域對象的數組米罚。
(2). 存儲著一個函數可用的所有作用域和變量
(3). 控制著函數作用域和變量的使用順序: 就近原則。
總結:
2. RegExp對象:
(1). 創(chuàng)建正則表達式對象:
a. 如果正則是固定的:
var reg=/正則/ig
b. 如果正則需要動態(tài)生成:
var reg=new RegExp("正則",ig)
(2). 驗證字符串格式:
var bool=reg.test(str)
reg必須同時前加^后加$
(3). 查找敏感詞的內容和位置:
a. 只查找一個關鍵詞的內容和位置:
var arr=reg.exec(str) //reg不用加g
返回值數組: [ 0: "敏感詞內容", index: 敏感詞下標位置 ]
b. 既查找每個關鍵詞的內容又查找每個關鍵詞的位置:
var reg=正則表達式對象; //reg要加g
do{
var arr=reg.exec(str);
if(arr!=null){
獲得本次找到的敏感詞的內容(arr[0])和位置(arr.index)
}
}while(arr!=null);
3. 函數:
(1). 創(chuàng)建函數三種方式:
a. function 函數名(形參列表){ 函數體; return 返回值 } //會被聲明提前丈探,不好
b. var 函數名=function(形參列表){ 函數體; return 返回值 }//不會被聲明提前录择,首選
c. var 函數名=new Function("形參1", "形參2", ... , "函數體; return 返回值")
函數本質:
1). 函數也是一個對象,對象中保存著函數的函數體代碼
2). 函數名只是一個普通的變量碗降,函數名通過函數對象地址隘竭,引用著函數對象
3). function在底層等效于new Function()
function 函數名(){ ... }和var 函數名=function(){}在底層都會被翻譯為
var 函數名=new Function(...)
只不過function 函數名(){}是先提前,再翻譯
而var 函數名=function(){}是不提前讼渊,原地翻譯
(2). 重載: 今后动看,一件事,根據傳入不同的參數值爪幻,動態(tài)執(zhí)行不同的邏輯時菱皆,都用重載
function 一個函數名(不寫形參變量){
//arguments對象自動接住所有實參值
if(arguments.length==0){
執(zhí)行一種邏輯
}else if(arguments.length==1){
執(zhí)行另一種邏輯
}else{
執(zhí)行其它邏輯
}
}
其中arguments是類數組對象: 和數組相比:
a. 相同點: 也有下標须误,length屬性,也可for循環(huán)遍歷
b. 不同點: 不是數組類型仇轻,無法使用數組家的函數
(3). 匿名函數:
a. 所有回調函數優(yōu)先使用匿名函數——用完釋放京痢,節(jié)約內存
b. 如果擔心不停功能之間的代碼互相干擾,就可用匿名函數自調將每個功能的代碼包裹起來拯田。
(function(){
某個功能的js代碼
})()
結果: 匿名函數內的都是局部變量历造,不會產生全局變量,不會造成全局污染船庇。
(4). 作用域和作用域鏈:
a. 作用域:
1). 全局作用域:window吭产,保存全局變量
優(yōu): 可重用,缺: 隨處可用, 極易被污染
2). 函數作用域: 保存局部變量
局部變量包括2中: 函數中var出的變量和形參變量
優(yōu): 僅函數內可用鸭轮,不會被污染臣淤,缺: 不可重用
3). 函數作用域對象原理:
i. 每個函數定義時都自帶好友列表,好友列表里2個格子窃爷,一個是空邑蒋,一個引用window
ii. 調用函數時臨時創(chuàng)建函數作用域對象保存函數局部變量。并將函數作用域對象的地址保存到函數好友列表中離自己近的格子里按厘。
iii. 函數執(zhí)行過程中按就近原則先在自己的函數作用域對象中找局部變量使用医吊。如果找不到,才被迫去全局window中找變量使用.
iv. 函數調用后逮京,好友列表中離自己近的格子清空卿堂,導致函數作用域對象以及內部的局部變量被釋放!——所以局部變量不可重用懒棉!
b. 作用域鏈: 保存一個函數所有可用的作用域對象的鏈式結構(好友列表)學名就叫作用域鏈草描。
1). 作用域鏈保存著一個函數可用的所有變量
2). 作用域鏈控制著變量的使用順序。先局部后全局策严。