一、运算符
1、in运算符
in运算符希望它的左操作数是一个字符串或可以转换为字符串,希望它的右操作数是一个对象,如果右侧的对象拥有一个名为左操作数值的属性名,那么表达式返回true,例如:
instanceof运算符希望左操作数是一个对象,右操作数标识对象的类,如果左侧的对象是右侧类的实例,则表达式返回true,否则返回false。如果左操作数不是对象的话,instanceof返回false,如果右操作数不是一个函数,则抛出一个类型错误异常。
instanceof工作过程:为了计算表达式o instanceof f,JavaScript首先计算f.prototype,然后在原型链中查找o,如果找到,那么o是f(或者f的父类)的一个实例,表达式返回true,否则o不是f的实例,返回false。
3、delete运算符
delete是一元操作符,它用来删除对象属性或数组元素,例如:
delete希望它的操作数是一个左值,如果它不是左值,那么delete将不进行任何操作同时返回true。然而并不是所有的属性都可删除,一些内置核心和客户端属性是不可能删除的,用户通过var语句声明的变量不能删除,通过function语句定义的函数和函数参数也不能删除。
在ES5严格模式中,如果delete的操作数是非法的,比如变量、函数或函数参数,delete将抛出一个语法错误(SyntaxError)异常,删除不可配置的属性时会抛出一个类型错误异常。在非严格模式下,这些delete操作都不会报错,只是简单的返回false,表明操作数不能执行删除操作。
void是一元运算符,它出现在操作数之前,操作数可以是任意类型。这个运算符并不是经常使用:操作数会照常计算,但忽略计算结果并返回undefined。
二、语句
1、function
函数定义可以写成语句的形式(函数定义表达式):
2、throw语句
throw语句的语法如下:
3、try/catch/finally语句
try/catch/finally语句是JavaScript的异常处理机制。其中try从句定义了需要处理的异常所在的代码块。catch从句跟随在try从句之后,当try块内某处发生了异常时,调用catch内的代码逻辑。catch从句后跟随finally块,后者中放置清理代码,不管try块中是否产生异常,finally块内的逻辑总是会执行。尽管catch和finally都是可选的,但try从句需要至少二者之一与之组成完整的语句。try、catch和finally语句块都需要使用花括号括起来,这里的花括号是必需的,即使从句中只有一条语句也不能省略花括号。
如果finally块中使用了return、continue、break或者throw语句使程序发生跳转,或者通过调用了抛出异常的方法改变了程序执行流程,不管这个跳转使程序挂起还是继续执行,解释器都会将其忽略。例如,如果finally从句抛出一个异常,这个异常将替代正在抛出的异常;如果finally从句运行到return语句,尽管已经抛出了这个异常且这个抛出的异常还没有被处理,这个方法依然会正常返回。
with语句用于临时扩展作用域链,在严格模式中是禁止使用with语句的,在非严格模式中也是不推荐使用的,具有如下语法:
1、in运算符
in运算符希望它的左操作数是一个字符串或可以转换为字符串,希望它的右操作数是一个对象,如果右侧的对象拥有一个名为左操作数值的属性名,那么表达式返回true,例如:
var point = {x:1,y:1};
"x" in point; //true
"z" in point; //false
"toString" in point; //true,对象继承了toString()方法
2、instanceof运算符instanceof运算符希望左操作数是一个对象,右操作数标识对象的类,如果左侧的对象是右侧类的实例,则表达式返回true,否则返回false。如果左操作数不是对象的话,instanceof返回false,如果右操作数不是一个函数,则抛出一个类型错误异常。
instanceof工作过程:为了计算表达式o instanceof f,JavaScript首先计算f.prototype,然后在原型链中查找o,如果找到,那么o是f(或者f的父类)的一个实例,表达式返回true,否则o不是f的实例,返回false。
3、delete运算符
delete是一元操作符,它用来删除对象属性或数组元素,例如:
var o = {x:1,y:2};
delelte o.x;
"x" in o; //false
删除属性或者删除数组元素不仅仅是设置了一个undefined的值,当删除一个属性时,这个属性将不再存在,读取一个不存在的属性将返回undefined,但是可以通过in运算符来检测这个属性是否在对象中存在。delete希望它的操作数是一个左值,如果它不是左值,那么delete将不进行任何操作同时返回true。然而并不是所有的属性都可删除,一些内置核心和客户端属性是不可能删除的,用户通过var语句声明的变量不能删除,通过function语句定义的函数和函数参数也不能删除。
在ES5严格模式中,如果delete的操作数是非法的,比如变量、函数或函数参数,delete将抛出一个语法错误(SyntaxError)异常,删除不可配置的属性时会抛出一个类型错误异常。在非严格模式下,这些delete操作都不会报错,只是简单的返回false,表明操作数不能执行删除操作。
var o = {x:1,y:2};
delete o.x; //删除一个对象属性,返回true
delete o.x; //删除不存在的属性,返回true
delete o; //不能删除通过var声明的变量,返回true
delete 1; //参数不是一个左值,返回true
this.x = 1; //给全局对象定义一个属性,这里没有使用var
delete x; //试图删除它,在非严格模式下返回true
//在严格模式下会抛出异常,这时使用"delete this.x"来代替
4、void运算符void是一元运算符,它出现在操作数之前,操作数可以是任意类型。这个运算符并不是经常使用:操作数会照常计算,但忽略计算结果并返回undefined。
二、语句
1、function
函数定义可以写成语句的形式(函数定义表达式):
var f = function(x) {return x + 1};
也可以使用函数声明语句:
function f(x) {return x + 1};
尽管函数声明语句和函数定义表达式包含相同的函数名,但二者仍然不同,两种方式都创建了新的函数对象,但函数声明语句中的函数名是一个变量名,变量指向函数对象,函数会被显示地“提前”到脚本或函数顶部,因此它们在整个脚本或函数内都是可见的,可以在声明一个函数之前调用它。使用var的话,只有变量声明提前了,变量的初始化代码仍然在原来的位置,必须在声明之后才可以调用这个函数。2、throw语句
throw语句的语法如下:
throw expression;
expression的值可以是任意类型的,可以抛出一个代表错误码的数字,或者包含可读的错误消息的字符串。当JavaScript解释器抛出异常的时候通常采用Error类型和其子类型,当然也可以使用它们。一个Error对象有一个name属性表示错误类型,这个属性的值和它们的构造函数的名字相同,也就是说,SyntaxError对象的name属性为"SyntaxError",EvalError对象的name属性为"EvalError",一个message属性用来存放传递给构造函数的字符串。
function factorial(x) {
//如果输入参数是非法的,则抛出一个异常
if(x < 0) throw new Error("x不能是负数");
//否则,计算出一个值,并正常地返回它
for(var f = 1; x >1; f *= x, x--); //计算x的阶乘
return f;
}
当抛出异常时,JavaScript解释器会立即停止当前正在执行的逻辑,并跳转至就近的异常处理程序。如果抛出异常的代码块没有一条相关联的catch从句,解释器会检查更高层的闭合代码块,看它是否有相关联的异常处理程序,以此类推,直到找到一个异常处理程序为止。如果抛出异常的函数没有处理它的try/catch/finally语句,异常将向上传播到调用该函数的代码,这样的话,异常就会沿着JavaScript方法的词法结构和调用栈向上传播,如果没有找到任何异常处理程序,JavaScript将把异常当=当作程序错误来处理,并报告给用户。3、try/catch/finally语句
try/catch/finally语句是JavaScript的异常处理机制。其中try从句定义了需要处理的异常所在的代码块。catch从句跟随在try从句之后,当try块内某处发生了异常时,调用catch内的代码逻辑。catch从句后跟随finally块,后者中放置清理代码,不管try块中是否产生异常,finally块内的逻辑总是会执行。尽管catch和finally都是可选的,但try从句需要至少二者之一与之组成完整的语句。try、catch和finally语句块都需要使用花括号括起来,这里的花括号是必需的,即使从句中只有一条语句也不能省略花括号。
try {
//通常来讲,这里的代码会从头执行到尾而不会产生任何问题
//但有时会抛出一个异常,要么是由throw语句直接抛出异常
//要么是通过调用一个方法间接抛出异常
}
catch(e) {
//当且仅当try语句块抛出了异常,才会执行到这里的代码
//这里可以通过局部变量e来获得对Error对象或者抛出的其他值的引用
//这里的代码块可以基于某种原因处理这个异常,也可以忽略这个异常,
//还可以通过throw语句重新抛出异常
}
finally {
//不管try语句块是否抛出了异常,这里的逻辑总会执行,终止try语句块的方式有:
//1)正常终止,执行完语句块的最后一条语句
//2)通过break、continue或return语句终止
//3)抛出一个异常,异常被catch从句捕获
//4)抛出一个异常,异常未被捕获,继续向上传播
}
try {
//要求用户输入一个数字
var n = Number(prompt("请输入一个正整数",""));
//假设输入是合法的,计算这个数的阶乘,函数参照上例
var f = factorial(n);
//显示结果
alert(n + "! = " + f);
}
catch(ex) {
//如果输入不合法,将执行这里的逻辑
alert(ex); //告诉用户产生了什么错误
}
当由于return、continue或break语句使得解释器跳出try语句块时,解释器在执行新的目标代码之前执行finally块中的逻辑。
如果finally块中使用了return、continue、break或者throw语句使程序发生跳转,或者通过调用了抛出异常的方法改变了程序执行流程,不管这个跳转使程序挂起还是继续执行,解释器都会将其忽略。例如,如果finally从句抛出一个异常,这个异常将替代正在抛出的异常;如果finally从句运行到return语句,尽管已经抛出了这个异常且这个抛出的异常还没有被处理,这个方法依然会正常返回。
var foo = function() {
try {
//抛出一个异常
}
finally {
return 1; //未处理异常直接返回,这里将正常返回
}
}
foo();
4、with语句with语句用于临时扩展作用域链,在严格模式中是禁止使用with语句的,在非严格模式中也是不推荐使用的,具有如下语法:
with(object) {
statement
}
这条语句将object添加到作用域的头部,然后执行statement,最后把作用域链恢复到原始状态
with(document.forms[0]) {
name.value = "";
address.value = "";
email.value = "";
}
//等价于
var f = document.forms[0];
f.name.value = "";
f.address.value = "";
f.email.value = "";
文章参考来源:《JavaScript 权威指南》(原书第六版) 作者 弗兰纳根