try-catch \ES5 严格模式
1.try-catch
try 的意思是尝试,catch 是捕捉,这个 try catch 就是防止我们报错的。比如说我现
在写了好多行代码,这段代码里边有可能报错,也有可能不报错,我把握不了,而我
又不想让报错的这一行影响后续代码的执行,这个时候就用 try catch,比如说:
try{
console.log("a");
console.log(b);
console.log("c");
}catch(e){
}
console.log("d");
我们把代码写在 try 里边,现在第二行 b 报错了,但是他不会抛出错误,try 外边的代
码依然可以执行,但是在 try 里边发生的错误,不会执行错误后的 try 里边的代码,
例如上边的,b 那行出错后,c 那行也不会执行,但是 try 外边的 d 可以执行,此时就
输出 a d。假如说 try 里边没有发生错误,他就会正常执行的,就是说如果你不确定这
段代码是不是有错误,你就把它放到 try 里边,他不会影响外边代码的执行。那么,
catch 是干嘛的?
try{
console.log("a");
console.log(b);
console.log("c");
}catch(e){
console.log(e.name + ":" + e.message)
}
console.log("d");
如果 try 里边的代码没有错误,那么 catch 就不会执行,这个 catch 的作用就是捕捉
错误信息的,一般情况下系统会把报错信息抛给控制台,显示的时候是红色的,但是
有了 catch 后,他就会捕捉到错误信息,不会抛给控制台,捕捉之后你想打印或者弹
出啥的都可以,就交给你让你自己处理了,这个错误信息是一个对象 Error,他里边就
只有两个属性 name 和 message,在 catch 括号里传一个参数 e(参数名不固定),然后
我们例如上边的,打印错误信息,他执行的时候先走 try,再走 catch,再走外边的
此时就输出 a ReferenceError:b is not defined d,如果 try 里有多行都是错的,
他就只看第一行错误后,后边的就不看了。这个 try catch 的好处就是不会影响后续
代码的执行。
2.Error.name 六种值对应的错误信息:
(1)EvalError:eval()的使用与定义不一致
解释:这个 eval 是不允许我们用的,如果用了的话他就会显示这个错误信息。
(2)RangeError:数值越界
解释:这个很少见,以后遇到了会讲的。
(3)ReferenceError:非法或不能识别的引用数值
解释:当一个变量未经声明就使用或者当一个函数未经声明就调用就会显示这个。
(4)SyntaxtError:发生语法解析错误
解释:代码在执行前系统先通篇扫描一遍,如果有低级语法错误就显示这个,例如写
了一个中文,少写一个括号等等。
(5)TypeError:类型操作错误
解释:比如说用数组方法操作对象了就会显示这个,后边遇到了再说。
(6)URIError:URI 处理函数使用不当
解释:引用地址发生错误,后面遇到再说。
3.es5的严格模式
es 版本的发展从 es1.0 一直到现在的 es7.0,但是大多数浏览器都是基于 es3.0 的语
法和es5.0的新增方法使用的,也就是说当es3.0和es5.0产生冲突的部分就是用es3.0
的方法。今天我们来讲一个 es5.0 的严格模式,在这个模式下,二者产生冲突的部分
就用 es5.0 的方法,否则使用 es3.0 的方法。
(1)es5.0 严格模式的启动
在逻辑的最顶端写上"use strict";(逻辑的最顶端就是前边可以有空格回车,但是不
能有别的代码,语法规定,必须写在最顶端),你可以写在全局的最顶端,也可以写在
局部的最顶端,写在全局就代表全局上的所有代码都启用 es5.0 的严格模式,写在局
部就只让当前函数体里启用严格模式,比如:
function demo() {
console.log(arguments.callee);
}
demo();
function test() {
"use strict";
console.log(arguments.callee);
try-catch、ES5 严格模式
151
}
test();
arguments.callee 在 es5 里是不允许用的,此时第一个函数会执行,第二个函数就会
报错(TypeError),因为第二个启用了 es5 的严格模式。
(2)不再兼容 es3 的一些不规则语法,使用全新的 es5 规范。
(3)两种用法:全局严格模式(写在全局最顶端);局部函数内的严格模式(局部最
顶端,推荐)
(4)思考:为啥启用 es5 的严格模式要用字符串的启用方式,而不是函数调用?
答:不管是 es3 还是 es5 都必须让浏览器内核实现了 es 对应版本的标准前提下才能好
使,那假如说老版本的浏览器没更新到 es5,你咣当一开始来个函数调用,他识别不了,
就会立马报错,那么后边的代码都没办法执行了,你写成字符串,他就跟表达式一样,
摆在那里也不影响啥,而且新版本的浏览器支持 es5 的话他就会识别并开启严格模式,
起到了向后兼容的作用,即老版本保证不出错,新版本保证能识别。
4.es5 严格模式的语法
(1)不允许用 with
with 之前我们没有讲,今天来讲一下:
var obj = {
name: "obj",
age: 234
}
var name = "window";
function test() {
var age = 123;
var name = "scope";
with(obj) {
console.log(name);
console.log(age);
}
}
test();
这个 with 的小括号里如果不放东西的话他就正常执行,如果小括号里放一个对象进去
的话那就了不得了:他会把这个对象当做 with 所圈定的代码体的作用域链的最顶端,
他会改变作用域链,会把 obj 当成自己的 AO 连到作用域链的最顶端,所以此时输出 obj
234.他会把 obj 当成自己最直接的 AO,反正 AO 也是一个对象,如果 obj 里没有他才会
去找 test 的 AO 再找 GO。
作用:简化代码,我们拿命名空间举个例子:
var org = {
dp1: {
jc: {
name: "abc",
age: 123
},
deng: {
name: "xiaodeng",
age: 234
}
},
dp2: {
}
}
我们以前说命名空间用起来不太方便,其实他是这么用的,你想拿东西就直接:
with(org.dp1.jc){
console.log(name);
}
这个 with 里放的就是我的代码,那么我的代码能访问的最直接的执行期上下文就是
org.dp1.jc,那么我在里边访问的 name 就是 abc,所以我在 with 里访问的话就直接写
变量名就可以了,达到了代码简化的目的。
再比如 document 上有很多方法,我们再用的时候每次都得 document 点啥,太麻烦了,
那我现在直接放到 with 里边:
with(document){
write("a");
}
此时就输出 a,你就直接写 write 就行了,因为你写了之后他就会去对应的执行期上下
文里边找,找到 document,而 document 正好有这个方法,就把 write 拿出来了。
但是,有一点不好就是 with 太强大了,你改啥不好你去改作用域链啊,作用域链是经
过很复杂的过程才生成的,比如说作用域链有十层,你又新加了一层,就等于改了十
一层,因为那十层得往下移啊,改的太深了,那就会达到效率的丧失,所以 es5 为了
提高效率就不准用 with 了。
"use strict";
with(document){
write("a");
}
此时就会报错,告诉你 with 不能使了。
(2)不允许用 arguments.callee 和 function.caller,在启用 es5 的严格模式下,用
这两个也报错,上边试过了。
(3)变量赋值前必须声明
以前我们 es3 变量未经声明就使用叫做暗示全局变量,但是 es5 严格模式不行了:
“use strict”;
a = 3;
此时就会报错,告诉你 a is not defined。
(4)局部的 this 必须被赋值,赋什么就是什么。比如说:
"use strict";
function test() {
console.log(this);
}
test();
我们说在 es3 里边,这个局部的 this 指向 window,但是在 es5.0 里边你必须给他赋值,
不赋值就输出 undefined,你可以用 new 赋值,new test()就输出 test{},也可以
test.call({})就输出{}。
注意:在 es3.0 里,假如说 test.call(123)他会输出对象类型的 123:即 Number{123},
因为 es3 里规定 call 里边不能传原始值,你传了的话他就会调用包装类包装成对象,
但是 es5 里就输出 123,赋什么就是什么。
(5)拒绝重复属性和参数。
"use strict";
function test(name,name) {
console.log(name);
}
test(123);
在 es3 里边这么写不报错,虽然没有人这么写,但是在 es5 里这么写就会报错,重复
的属性也不行:
"use strict";
var obj = {
name: "123",
name: "234"
}
这么写也不行,但是有一点小的区别就是这么写不报错,这可能是浏览器在实现语法
和规定语法的时候一个小误差了,但是后边的会覆盖掉前边的,也许现在不报错,可
能以后就报错了,因为人家明令规定了不能有重复参数和属性。
(6)不能用 eval
这个 eval es3 里都不能用,他也非常强大,他可以把字符串当做代码执行,比如:
var a = 123;
eval(“console.log(a)”);
此时就输出 123,这个 eval 是魔鬼,它还可以改变作用域,他还有自己的作用域,这
里边很复杂,就不说了,反正不能用哈。