9月阅读周·JavaScript权威指南:表达式和运算符,其他运算符篇
背景
去年下半年,我在微信书架里加入了许多技术书籍,各种类别的都有,断断续续的读了一部分。
没有计划的阅读,收效甚微。
新年伊始,我准备尝试一下其他方式,比如阅读周。每月抽出1~2个非连续周,完整阅读一本书籍。
这个“玩法”虽然常见且板正,但是有效,已经坚持阅读八个月。
已读完书籍:《架构简洁之道》、《深入浅出的Node.js》、《你不知道的JavaScript(上卷)》、《你不知道的JavaScript(中卷)》、《你不知道的JavaScript(下卷)》、《数据结构与算法JavaScript描述》、《WebKit技术内幕》、《前端架构:从入门到微前端》、《秒懂算法:用常识解读数据结构与算法》。
当前阅读周书籍:《JavaScript权威指南》。
其他运算符
条件运算符(?:)
条件运算符是JavaScript中唯一的一个三元运算符(三个操作数),有时直接称做“三元运算符”。通常这个运算符写成“?:”,当然在代码中往往不会这么简写,因为这个运算符拥有三个操作数,第一个操作数在“?”之前,第二个操作数在“?”和“:”之间,第三个操作数在“:”之后,例如:
x>0?x:-x//求x的绝对值
条件运算符的操作数可以是任意类型。第一个操作数当成布尔值,如果它是真值,那么将计算第二个操作数,并返回其计算结果。否则,如果第一个操作数是假值,那么将计算第三个操作数,并返回其计算结果。第二个和第三个操作数总是会计算其中之一,不可能两者同时执行。
其实使用if语句也会带来同样的效果(参照5.4.1节),“?:”运算符只是提供了一种简写形式。这里是一个“?:”的典型应用场景,判断一个变量是否有定义(并拥有一个有意义的真值),如果有定义则使用它,如果无定义则使用一个默认值:
greeting="hello"+(username?username:"there");
这和下面使用if语句的代码是等价的,但显然上面的代码更加简洁:
greeting="hello";
if(username)
greeting+=username;
else
greeting+="there";
typeof运算符
typeof是一元运算符,放在其单个操作数的前面,操作数可以是任意类型。返回值为表示操作数类型的一个字符串。
typeof最常用的用法是写在表达式中,就像这样:
(typeof value=="string")?"'"+value+"'":value
typeof运算符同样在switch语句中非常有用,需要注意的是,typeof运算符可以带上圆括号,这让typeof看起来像一个函数名,而不是一个运算符关键字:
typeof(i)
我们注意到,当操作数是null的时候,typeof将返回"object"。如果想将null和对象区分开,则必须针对特殊值显式检测。对于宿主对象来说,typeof有可能并不返回"object",而返回字符串。但实际上客户端JavaScript中的大多数宿主对象都是"object"类型。
由于所有对象和数组的typeof运算结果是"object"而不是"function",因此它对于区分对象和其他原始值来说是很有帮助的。如果想区分对象的类,则需要使用其他的手段,比如使用instanceof运算符、class特性以及constructor属性。
delete运算符
delete是一元操作符,它用来删除对象属性或者数组元素。就像赋值、递增、递减运算符一样,delete也是具有副作用的,它是用来做删除操作的,不是用来返回一个值的,例如:
var o={x:1,y:2};//定义一个对象
delete o.x;//删除一个属性
"x"in o//=>false:这个属性在对象中不再存在
var a=[1,2,3];//定义一个数组
delete a[2];//删除最后一个数组元素
2 in a;//=>false:元素2在数组中已经不存在了
a.length//=>3:注意,数组长度并没有改变,尽管上一行代码删除了这个元素,但删除操作留下了一个“洞”,实际上并没有修改数组的长度,因此a数组的长度仍然是3
需要注意的是,删除属性或者删除数组元素不仅仅是设置了一个undefined的值。当删除一个属性时,这个属性将不再存在。读取一个不存在的属性将返回undefined,但是可以通过in运算符来检测这个属性是否在对象中存在。
delete希望他的操作数是一个左值,如果它不是左值,那么delete将不进行任何操作同时返回true。否则,delete将试图删除这个指定的左值。如果删除成功,delete将返回true。然而并不是所有的属性都可删除,一些内置核心和客户端属性是不能删除的,用户通过var语句声明的变量不能删除。同样,通过function语句定义的函数和函数参数也不能删除。
在ECMAScript 5严格模式中,如果delete的操作数是非法的,比如变量、函数或函数参数,delete操作将抛出一个语法错误(SyntaxError)异常,只有操作数是一个属性访问表达式的时候它才会正常工作。在严格模式下,delete删除不可配置的属性时会抛出一个类型错误异常。在非严格模式下,这些delete操作都不会报错,只是简单地返回false,以表明操作数不能执行删除操作。
这里有一些关于delete运算符的例子:
var o={x:1,y:2};//定义一个变量,初始化为对象
delete o.x;//删除一个对象属性,返回true
typeof o.x;//属性不存在,返回"undefined"
delete o.x;//删除不存在的属性,返回true
delete o;//不能删除通过var声明的变量,返回false
//在严格模式下,将抛出一个异常
delete 1;//参数不是一个左值,返回true
this.x=1;//给全局对象定义一个属性,这里没有使用var
delete x;//试图删除它,在非严格模式下返回true
//在严格模式下会抛出异常,这时使用"delete this.x"来代替
x;//运行时错误,没有定义x
void运算符
void是一元运算符,它出现在操作数之前,操作数可以是任意类型。这个运算符并不是经常使用:操作数会照常计算,但忽略计算结果并返回undefined。由于void会忽略操作数的值,因此在操作数具有副作用的时候使用void来让程序更具语义。
这个运算符最常用在客户端的URL——javascript:URL中,在URL中可以写带有副作用的表达式,而void则让浏览器不必显示这个表达式的计算结果。例如,经常在HTML代码中的<a>标签里使用void运算符:
<a href="javascript:void window.open();">打开一个新窗口</a>
通过给<a>的onclick绑定一个事件处理程序要比在href中写"javascript:URL"要更加清晰,当然,这样的话void操作符就可有可无了。
逗号运算符(,)
逗号运算符是二元运算符,它的操作数可以是任意类型。它首先计算左操作数,然后计算右操作数,最后返回右操作数的值,看下面的示例代码:
i=0,j=1,k=2;
计算结果是2,它和下面的代码基本上是等价的:
i=0;j=1;k=2;
总是会计算左侧的表达式,但计算结果忽略掉,也就是说,只有左侧表达式具有副作用,才会使用逗号运算符让代码变得更通顺。逗号运算符最常用的场景是在for循环中,这个for循环通常具有多个循环变量:
//for循环中的第一个逗号是var语句的一部分
//第二个逗号是逗号运算符
//它将两个表达式(i++和j--)放在一条(for循环中的)语句中
for(var i=0,j=10;i<j;i++,j--)
console.log(i+j);
总结
JavaScript支持很多各种各样的运算符。
作者介绍
非职业「传道授业解惑」的开发者叶一一。
《趣学前端》、《CSS畅想》等系列作者。华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。
如果看完文章有所收获,欢迎点赞👍 | 收藏⭐️ | 留言📝。
- 点赞
- 收藏
- 关注作者
评论(0)