1.*錯誤處理:
錯誤:程序執行過程中,發生的導致程序無法繼續執行的狀態
錯誤處理:即使程序出錯,也要保證程序不退出的機制
Error對象:在發生錯誤時,*自動創建的封裝錯誤信息的對象
屬性:err.name:錯誤類型:6種
SyntaxError:語法錯誤
RefernceError: 引用錯誤,找不到對象或變量時
TypeError:類型錯誤,錯誤的使用了對象的*方法
RangeError:範圍錯誤,參數超範圍
EvalError:Eval錯誤
URIError:URI錯誤
如何錯誤處理:語法:
try{ 可能出錯的語句; }catch(err){ 一旦出錯,執行的錯誤處理代碼; }[finally{ 無論是否出錯,都要執行的代碼; }]
強調:被try包裹的代碼,執行效率會降低;所以,try應儘量少的包裹代碼
#筆試題:***js中如何解決瀏覽器兼容性問題:3種
1.不兼容的類型或方法:2種:
if else
try catch
2.不兼容的值:短路邏輯中的||:
值1||值2
IETester問題:
1.只支持document.write輸出
2.只要出錯,當前窗口不能繼續使用,必須重新打開窗口
3.將網頁文件拖拽到窗口內,自動加載
***案例:異常處理中的return
1.finally中的return,會替換try catch中的return
2.即使finally中沒有return,finally中的代碼一定會在return前執行,但無法影響已確定的return結果
不報錯時:
/*筆試題:錯誤處理中的return*/ var n=1; function fun() { try { return n;//return --等待 } catch (err) { n++; } finally { n++;//2 // return n; } } console.log(fun());//1 console.log(n);//2報錯時:
var n=1; function fun() { try { m++; return n;//3 } catch (err) { n++; } finally { n++;//3 return n;//3 } } console.log(fun());//3 console.log(n);//3
拋出:自定義錯誤:
何時使用:方法定義者向方法調用者拋出使用錯誤
如何拋出:throw new Error(“錯誤消息”)
1*****函數對象:
執行環境棧:ECS,保存全局以及每個函數的執行環境的棧結構
執行環境:EC 調用函數時,創建的引用函數資源的對象
窗口一打開,默認ECS中壓入一個全局EC;全局EC應用了window對象VO;window對象中的變量都是全局變量
變量對象:VO,專門存儲變量的對象
函數的生命週期:
定義時:僅創建一個函數對象,封裝了函數的定義,不會讀取函數的內容
調用時:創建函數的EC對象壓入ECS中,函數的EC對象引用了,當前函數的活動對象AO
活動對象:AO,專門保存本次函數調用時的局部變量;AO中有一個屬性始終指向window對象
變量使用的規則:優先在AO中找,找不到,纔去window對象找
調用後:函數的EC對象出棧,AO對象失去引用,被回收;AO對象中的局部變量一起被釋放
***重載:overload
相同名稱,不同參數列表的多個函數
在調用時,可根據傳入的參數的不同,動態選擇對應的函數執行
js語法默認不支持重載,但是可用arguments對象模擬重載的效果
arguments對象:調用時,自動接收所有傳入的參數值,類(like)數組(的)對象
2點:1.arguments[i] 2.argument.length獲得個數
function calc(){ if(arguments.length>=2){ return arguments[0]+arguments[1]; }else { return arguments[0]*arguments[0]; } } console.log(calc(12,23)); console.log(calc(13));何時使用:今後只要多個操作,公用一個函數名時,皆能使用
***類數組對象 vs 數組對象
類型不同:類數組對象的父類型時Object;數組對象的父類型是Array -->導致類數組對象無法使用數組類型的方法
類數組對象 to Array固定套路:
var arr=Array.prototype.slice.apply(arguments);
爲什麼還要定義參數:作用:2個
1.提示調用者,改如何傳入參數
2.簡化函數定義,在函數內使用參數值
結論:今後大部分方法依舊要定義參數,只有不確定傳入值個數時,才省略參數,用arguments
****匿名函數:定義時,沒有任何變量引用的函數
何時使用:2種情況:
1.如果一個函數只執行一次 --匿名函數自調
語法:(function(參數變量){函數體:return 返回值})(參數值)
2.如果一個函數作爲對象交給其他函數使用時 --回調
創建一個比較函數:3種:
1.聲明方式定義函數:function compare(a,b){return a-b}
***只有聲明方式定義的函數才能被聲明提前
***以下兩種方式定義的函數都不能被提前
2.函數直接量方式定義:var compare=function(a,b){return a-b};
3.使用new 關鍵字:var compare=new Function("a","b","return a-b"); --ps:引號必須要加
var arr=[2,12,123,33,23,3,1]; /*用三種方法定義比較器函數對象 */ /* function compare(a,b){return a-b};*/ /* var compare=function(a,b){return a-b};*/ var compare=new Function("a","b","return a-b"); arr.sort(compare); console.log(arr);慣例寫法:回調
arr.sort(function(a,b){return a-b;});匿名函數優點:節約內存空間;調用前和調用後,內存中不創建任何函數對象
2.自調
/*自調*/ (function(){ alert("開始加載。。。"); })();案例:運用遍歷和累加
/*定義add函數,可接受任意個數字參數,求所有數字參數的和*/ function add(){ //遍歷arguments中每個參數值,同時聲明sum=0 for(var i= 0,sum=0;i<arguments.length;i++){ sum+=arguments[i]; } //將當前參數值累計到sum中 //返回sum return sum; } console.log(add(1,2,3)); console.log(add(1,2,3,5,2,9,7)); console.log(add(1,2,3,8,7,5,3,2));
****作用域和作用域鏈:
作用域:一個變量的可用範圍,其實就是變量的實際存儲位置;只能是window中或AO中
window:全局作用域 ---全局變量
AO:函數作用域 ---局部變量
本質:EC對象的一個scope屬性,引用了window或AO對象
作用域鏈:已當前EC的scope屬性爲起點依次應用每個AO,直到window結束,形成的多級引用關係;只要在作用域鏈上存在的變量,當前函數都可以使用
*****閉包:
問題:全局變量 vs 局部變量
全局變量:
優:反覆使用,且共享使用
缺:可能隨時在任意位置被篡改 --全局污染
建議:儘量避免使用全局變量
局部變量:特點:不可反覆使用,方法調用完自動釋放
解決方案:閉包:反覆使用一個局部變量,且不會被污染
何時使用:想反覆使用一個局部變量,且不希望被污染時,就要用閉包結構保護局部變量
如何使用:3步:
1.定義外部函數(工廠函數)
特點:2步:
1.定義了受保護的局部變量
2.返回一個專門操作局部變量的內部函數對象
2.調用外層函數(工廠函數),獲得返回的內部函數對象
3.使用獲得的內部函數對象,操作受保護的局部變量 --ps:唯一途徑
//定義工廠函數保護局部變量 function factory(){ var n=0;//受保護局部變量 return function (){ return ++n;} } var ccb=factory(); //ccb:function(){return ++n;} console.log(ccb());//使用變量
判斷閉包輸出結構:
1.找受保護的局部變量
2.外層函數被調用幾次,就創建了幾個受保護的變量副本
3.同一次外層函數調用返回的內層函數,總使用同一個局部變量
function fun(){ for(var i= 0,arr=[];i<3;i++){ arr[i]=function(){return i;} //i=3 } return arr; } var funs=fun();//外層函數調用1次,只有一個受保護的變量i=3 /*funs=[ function(){return i;} function(){return i;} function(){return i;} 同一次外層函數調用,返回的所有函數對象,使用相同一個受保護的局部變量 ] * */ console.log(funs[0]());//3 console.log(funs[1]());//3 console.log(funs[2]());//3
過程圖:
筆試題:
/*匯率轉換:定義外層函數,創建人民幣對指定匯率的轉換器函數*/ function factory(rate){ return function (money){ //返回一個函數對象,接收一個參數 return (money/rate).toFixed(2);//函數體:返回money/rate,保留2位小數 } } var rmb2$=factory(6.1); console.log(rmb2$(6000)); var rmb2euro=factory(10); console.log(rmb2euro(8684));
例2:
/*getter/setter訪問器: * 獲取或設置一個變量的值專門方法 * get變量名/set變量名 * */ var getSalary,setSalary;//專門操作salary變量的訪問器 function factory(){ //保護一個局部變量salary,初始爲0 var salary=0; //爲getSalary變量賦值一個函數對象 getSalary=function(){ //函數體:返回salary的值,前面加“¥”,後面保留兩位小數 return "¥"+salary.toFixed(2); }; //爲setSalary變量賦值函數對象,接收一個value參數 setSalary=function(value){ //函數體:如果value不是數字 if(isNaN(value)){ //則拋出異常“工作必須是數字” throw new Error("工資必須是數字"); }else{ //將value賦值個salary salary=value; } } } factory(); salary=5000; console.log(getSalary()); setSalary(6000); console.log(getSalary()); console.log(salary); setSalary("hello");