JavaScript中的几个奇怪操作符
注:原文出自《JavaScript for PHP developers》,博主只是根据自己的理解增加了一些内容.
本文主要介绍几个JavaScript中的几个奇怪的操作符,并与PHP中的类似操作符进行比较.这些操作符又:in
,字符串连接
,类型强制转换
,void
,逗号操作符
.
1.in
1.1 for-in循环
说in操作符之前,不得不说一下for-in循环.在JavaScrip中当我们需要关联一个数组的时候,我们使用对象.并且,我们使用for-in循环而不是foreach来遍历数组.
假设我们在PHP中定义了如下的数组:
//PHP
$clothes = array(
'shirt' => 'white',
'pants' => 'blue',
'shoes' => 'black', //结尾建议加上逗号,这样要添加一个新单元时更方便
);
//自PHP5.4起
$clothes = [
'shirt' => 'white',
'pants' => 'blue',
'shoes' => 'black', //结尾建议加上逗号,这样要添加一个新单元时更方便
];
在JavaScript中,相同的数据如下所示:
//JavaScript
var clothes = {
shirt : 'white',
pants : 'blue',
shoes : 'black' //由于旧的IE的存在,结尾放逗号的话会出问题
}
//上面的JavaScript是直接定义的对象.也可直接定义数组.在JavaScript中,数组也是对象.
//数组定义方式如下:
var clothes = new Array();
clothes['shirt'] = 'white';
clothes['pants'] = 'blue';
clothes['shirt'] = 'black';
typeof clothes;//"object"
在PHP中我们像下面这样遍历数组:
//PHP
$result = '';
foreach ($clothes as $key => $value) {
$result .= $key . ':' . $value . '\n';
}
在JavaScript中我们使用for-in循环:
//JavaScript
var result ='';
for (var key in clothes) {
result += key + ':' + clothes[key] . '\n';
}
在该循环中,我们不能直接访问下一个属性的值,因此,我们使用方括号表示法clothes[key]来获取值.
还要注意,枚举属性的顺序不是固定的并且依赖于具体实习.换句话说,shoes可能出现在shirt之前,尽管其在定义中位于后面.如果想要保持这个顺序,我们需要使用一个常规的数组来存储数据.
这里只是为了说明,如果你暂时忘了PHP中的foreach必须使用=>来访问值,你也可以在PHP中像下面这样做,以模拟JavaScript中的for-in循环:
$result = '';
foreach (array_keys($clothes) as $key) {
$result .= $key . ':' .$clothes[$key] . '\n';
}
1.2.in
在前面in操作符用来遍历一个对象的属性.它也可用来检查一个对象中是否存在某个属性:
if ('shirt' in clothes) { //true
//do something
}
if ('hat' in clothes) { //false
//do something
}
也可用如下代码来进行检查:
if (clothes['shirt']) { //true
//do something
}
或者,更常用的方法是使用点表示法
if (clothes.shirt) { //true
//do something
}
不同指出在于,in只是检查该属性是否存在,他根本不会查看其值.使用clothes.shirt检查,只是在该属性存在且其值为非假的时候,才返回true.
例如,如果我们添加一个新的属性:
clothes.jacket = undefined;
那么:
'jacket' in clothes; //true
但是:
clothes.jacket; //undefined
!!clothes.jacket; //false
因为clothes.jacket的值是undefined,这是一个假值,并且会强制转换为false.
这类属于PHP中isset()和empty()的区别.
此外,更麻烦一点,我们可以四月typeof操作符来只检查属性是否存在二不检查其值:
typeof clothes.jacket !== "undefined"; //true
//但是请注意,当一个属性是`undefined`值的时候,相应的就会得到false
clothes.i_am_undefined = undefined;
typeof clothes.i_am_undefined === typeof clothes.i_dont_exist; //true
这种写法的一种更简单的方式是,与undefined值比较:
clothes.jacket !== undefined; //true
2.字符串连接
在PHP中我们使用.
操作符来连接字符串.在查看for-in循环的时候,你可能已经注意到了,JavaScript中+
操作符来连接字符串:
var alphabet = 'a' + 'b' + 'c';
alphabet; //"abc"
这可能有些奇怪,但是+
操作符既可用来将数字相加,也可用来连接字符串:
var numbers = '1' + '2' + '3';
var sum = 1 + 2 + 3;
numbers; //"123"
sum; //6
那么,我们如何知道该执行哪一种操作呢?这取决于操作数的类型.如果操作数是字符串,那么+
就是连接字符串;如果操作数是数字,那么+
就是求和.
不必说,+
操作符经常会导致错误,因此,记住变量类型就很重要.
如果在计算和的时候,操作数是字符串,或者不清楚操作数的类型,可使用parseFloat()或parseInt()方法将字符串类型转换为数字类型,然后再求和:
var a = '1', b = '2', c = '3';
sum = parseFloat(a) + parseFloat(b) + parseFloat(c); //6
对于连接字符串,一种替代方法是,将要添加的字符串存储到一个数组中,完成之后,再将数组的元素连接起来.这种方式在较早的浏览器例如IE7甚至更早的版本中都能很好的工作:
['R', '2', '-', 'D', '2'].join(''); //"R2-D2"
最后,还可以使用contact()方法,该方法不需要我们为了连接字符串二创建临时的数组对象:
''.contact('R', '2', '-', 'D', '2'); //"R2-D2"
String.prototype.contact('R', '2', '-', 'D', '2'); //"R2-D2"
3.类型强制转换
由于+
既可用于加法,也可用于字符串连接,我们也可用+
来快速的转换变量的类型:
+'1'; //将字符串"1"转换为数字1
''+1; //将数字1转换为字符串"1"
这样,我们就可以像下面这样连接字符串或者求和:
var numbers = ''+1 + ''+2 + ''+3;
var sum = +'1' + +'2' + +'3';
numbers; //"123"
sum; //6
说到强制转换,我们可以使用!!将变量转换为布尔类型:
!!1; //true
!!''; //false
第一个!取反,并且如果该值是假的话,会返回一个布尔true;第二个!再次取反,得到转换为布尔类型后我们想要的结果.此外,内建的构造函数也可用来执行变量的强制转换:
Number('1') === 1; //true
String(100) === '100'; //true
Boolean(0) === false; //true
Boolean(100) === true; //true
4.void
我们可能会遇到的另一个操作符是void,它接受任意的表达式作为操作数,并且返回undefined:
var a = void 1;
typeof a === 'undefined'; //true
void操作数很少用到,它会用作链接红的href.和typeof操作符一样,人们常常错误的将其与分组操作符()
一起使用,这使其看上去像是一个函数调用.
有时候,typeof()用作一个函数,但是,不建议这么做.记住,typeof不是一个函数,而是一个操作符.在这种用法中,typeof()之所以像一个函数一样使用,是因为()
也是一个操作符,它叫做分组操作符(grouping operator),通常用来覆盖操作优先级.例如:
3 * (2 + 1); //9
3 * 2 + 1; //7
<!--这不是一个好的做法-->
<a href="javascript:void(0)">Click and Nothing Happens</a>
这中糟糕的做法看上去是挺无辜的,但是,你思考一下就会发现,这么做确实很傻.在这个过程中,发生了如下的使其:
- 用户单击,计算一个JavaScript表达式
- 直接量0作为一个操作数发送给分组操作符()
- 分组操作符返回数组中的最终值0
- 现在发送给void操作符
- void在这里是一个黑洞,它接受操作符并返回undefined
即便不考虑这种什么也不是的链接的糟糕语义,人们还是会将herf设置为javascript:undefined.
JavaScript中的typeof(a)
和typeof a
的关系,就像PHP中echo ($a);
和echo $a;
的关系(尽管使用二者的原因不同).PHP中的include($a)
和include $a
也是基于同样的道理.即使这种写法有效,大妈仍然被看做是一种糟糕的写法,因为它有点鱼目混珠.
5.逗号操作符
逗号操作符是另一个奇怪的操作符,它是JavaScript中优先级最低的操作符,它直接返回传递给它的最后一个操作数的值:
var a = ('hello', 'there');
a; //"there"
var a = ('hello', 'there', 'young', 'one');
a; //"one"
它类似于&&和||,然而,当结果一目了然的时候,这些表达式会停止计算,但是逗号操作符会继续计算:
0 && 2 && 1; //0
0 || 2 || 1; //2
0 , 2 , 1, //1
当JavaScript只期望一个表达式,而你想要偷偷插入另一个表达式的时候,逗号操作符就很有作用了.
你是否注意到,前面的例子中,&&和||并不总是像PHP那样返回一个布尔值,.相反,它们返回想要表达式的值.这可能有点令人混淆,特别是在如下的常用模式中,也按照默认情况编写JavaScript的时候:
//JavaScript
var a = 100;
var b = a || 200;
b; //100
//PHP
$a = 100;
$b = $a || 200;
var_dump($b); //bool(true)