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");