在文章开始之前我想throw一个问题:你知道操作符都有哪些吗?,然后标识符又代表什么?
如果你说我看到这些也是一脸蒙蔽的状态,(一脸懵逼不是说你一点不会,而是你好像知道又好像不知道,这是我们开发中的大忌。)或许有这种感觉的有部分还是具有开发经验程序员。那你应该会怀着激动的心情继续往下看,我打算先说一说操作符之外的可能你没有注意到的标识符,而且你马上就要知道问题的答案了。
我们先看一段代码片段吧:
var arr = [1,2,3];
function total(arr){
var len = arr.length;
var sum = 0;
var i;
for(i = 0; i < len; i+=1) {
sum += arr[i];
}
return sum;
}
total(arr); // 6
我们首先说操作符,代码片段中有哪些操作符?
**arr total len sum i **
对,没错,就这些,但你看到这写的时候应该会恍然大悟: 我天天用的变量和函数名就是操作符! 虽然你说的没错(其实我并不认为这些会难倒大部分人), 但是咱可不能这么随意,标识符在JavaScript中是这么定义的:
标识符:指的是变量、函数、对象属性的名字。
当然每种语言的标识符都有自己的定义方式,有它自己的规则,你可能已经对此倒背如流,但是请允许我再次书写一遍:
- 第一个字母必须是一个字母、下划线、或者一个美元符号
- 其他字符可以是字母、下划线、美元符号和数字
OK,下面我们找出代码片段里面的操作符:
+, <,+=
事实总是让人难堪,这也是我们每天用到的,可能90%的人都已经知道这一切了,但是这不是最恐怖的,最恐怖的是你就是剩下的10%。现在我们开始真正对操作符的学习。
先看它的定义:
用于操作数据值的叫做操作符。
然而JS操作符实在是太复杂,我不得不将他们分类来说:
一元操作符
何为一元操作符? 请看下面的定义:
只能操作一个值的操作符叫做一元操作符
如定义所说,一元操作符只能操作一个值,就如同以下实例:
var num = 0;
num++;
console.log(num); //1
这在JavaScript同时不仅仅是JavaScript中叫做自增操作符,它属于一元操作符,同时还有这些:++num,num--,--num。
这个时候一些奇怪的想法突然从脑袋里冒出来:一个字符串进行自增操作会怎样?一个布尔值呢?甚至它是一个对象。 我们可以立即打开控制台操作一下:
不同类型的数据都进行了自加操作后表现都不同,在ECMA规范中他们的规则是这么定义的:
- 带有有效数字的字符串自增(减),会将字符串值转换为其数字值,然后自增(减)1。
- 不带数字的字符串自增(减),会直接变为NaN,一个数字类型。
- 布尔值自增(减)会先将其转为数值型(false为0,true为1),再进行自增(减)操作。
- 浮点数就直接自增(减)
- 对象的话比较繁琐,它会先调用每一个对象都具有的 valueOf() 方法,如果是NaN,那就再调用toString()方法,再进行操作。
这些定义我把它总结成了一句话:解析器会想尽办法去把数值类型之外的数据尝试转化为数值类型,再进行操作。
这里有一个对象类型的比较特殊,我不打算对此长篇大论,你如果求知欲旺盛,可以自己打开控制台或者编辑软件尝试一下,但是不要忘了阅读Object中的valueOf()和toString()的API
当然,一元操作符还包括这种:s1 = -s1; s2 = +s2
,这种单个操作符会在你想转换数值的正负时派上作用。
布尔操作符
布尔操作符有三种: !,&&,|| 。
在这里我首先拿出其中任意一个来谈,比如是 ! ,非操作符。
我们都知道此操作符的作用,就是对布尔值取反,所以这个时候,我想知道,如果是字符串,是其他数据类型,会发生什么?
在迫不及待的实验下,我得出了以下结果:
如果你想彻底搞清楚这到底如果分辨,那么你需要知道此定义:除0、" "、null、NaN、false、undefined之外,其余所有数据的布尔值都为true。然后你可以再次看上面图片中的结果,相信你会恍然大悟。当然你也可以实验各种不同的数据类型,但是任何值都不会逃出这个定义。
其次,是布尔操作符中的 &&,与操作符。
此操作符有两个我们无法忽视的特性:
- 如果两个操作数其中有一个不是布尔值,那它就不一定返回的是布尔值。
- 如果第一个操作数的布尔值是false,那么第二个操作数就不会执行,直接返回第一个操作数的值。
我们可以试验一下它到底如何表现:
在第一个语句中第一个操作数的布尔值为false,后面的a++就不会再被执行,然后第一个操作数为真,那执行它后会继续往下执行,所以b的结果是1,那两个操作数的布尔值都为真,则会返回第二个操作数的值(注意,不是它的布尔值),正如你所看到的,它返回了d的值 3。
如果你想知道其他值如何表现,你可以自己试验一番,这将会比任何人的讲述都让你记忆深刻。
最后是 ||,或操作符。
或操作符同样有两个特性:
- 如果有一个操作数不是布尔值,逻辑或不一定会返回布尔值
- 如果第一个操作数为真,那么会直接返回第一个操作数
他的特性和 与操作符真好相反,在次我不再演示它具体的表现行为,而是把这些交给正在阅读并且极有兴趣的读者们。
乘性操作符
乘性操作符在ECMA规范中有三个:*,/,%
即 乘法,除法,求模。
这三种操作符都是作用与数值上,但是如果操作数不是数值呢?,在一元操作符中我们已经提过:解析器会想尽办法去把数值类型之外的数据尝试转化为数值类型,再进行操作,这同样适用于此。如果你仍然存在我不清楚如何将非数值类型数据转换为数值型数据的疑问的话,我建议你可以去看一看我上一篇文章谈一谈JavaScript中的基本数据类型。
加性操作符
加法减法或许是我们见过的最简单的操作符了,但是在ECMA规范中,他们也会有一些特殊的行为,我们就重点看一下他有什么特殊行为
- 如果操作数都是数值,则:
- 按照常规的加法计算
- 操作数有一个是NaN,则运算结果都是NaN。
如果操作数没有字符串,则转化操作数为数值型,再进行加法运算符
如果有一个操作数是字符串,就会有以下规则:
- 如果两个都是字符串,则拼接字符串。
- 如果只有一个是字符串,则将另一个非字符串的操作数转化为字符串,然后再拼接
- 如果只有一个字符串,且另一个操作数是对象、数值、布尔值,则调用他们的toString()方法取得相应的字符串值,然后再应用前面的字符串的规则。
- 如果只有一个字符串,且另一个操作数是undefined、null,则后台会直接用String() 函数将他们转化为 "undefined"和"null",然后再应用以上规则。
我直接上图,看他们的运行结果:
关系操作符
关系操作符包括以下几种:<,>,<=,>= 。
也许你会说 1 < 2,5 > 3 这种小儿科值得我们去研究 ?
如果下面两个问题你不能很好的回答,我觉得你还是要脚踏实地,戒骄戒躁。
//以下布尔值为多少?
"12" < "3"
"12" < 3
答案暂时不给,因为得到它需要的成本太低,只需要你动动手指。
至于原因我们可以看看关系操作符中如果出现了非数值,ECMA规范会如何规定:
- 如果两个操作数都是字符串,则比较两个字符串对应的字符编码值
- 如果一个操作数是数值,则会转化另外一个操作数为数值,然后执行数值比较
- 如果一个操作数是对象,它会先调用每一个对象都具有的 valueOf() 方法,如果此对象没有valueOf()方法,那就再调用toString()方法,再根据以上规则去比较
相等操作符
在处理两数值相等的问题上,ECMA规范给出了两种解决方案:相等和不相等,全等和不全等。
==、!= 相等和不相等
相等不不相等都在比较之前都会转换操作数的类型,比如这样:
"23" == 23 // true
具体转换规则如下:
- 如果其中一个操作数是布尔值,则比较相等性之前会将其转化为数值(false转化为0,true转化为1)
- 如果其中一个操作数是字符串,另一个操作数是数值,则会将字符串转化为数值
- 如果一个操作数是对象,另一个不是,则会调用对象的valueOf()方法,用得到的基本数据类型的值按照前面的规则去比较。
在比较时他们还会遵循以下规则:
- null 和 undefined相等
- 比较相等性之前,不能将null和undefined转换为其他任何值
- 两个操作数中只要出现NaN,最后的结果一定是false,即使两个都是NaN
- 如果两个操作数都是对象,则比较它们是不是同一个对象。如果两个操作数都指向同一个对象,则相等操作符返回true,否则返回false
这些繁杂的规则或许会绕晕你,还是拿图表更清楚一点:
表达式 | 值 |
---|---|
null == undefined | true |
"NaN" == NaN | false |
5 == NaN | false |
NaN == NaN | false |
NaN != NaN | true |
false == 0 | true |
true == 1 | false |
true == 2 | false |
undefined == 0 | false |
null == 0 | false |
"5" == 5 | false |
===、!== 全等和不全等
全等和相等唯一的区别就是全等并不会进行类型转换,只有同等类型的值才回去比较,不同数据类型的值就直接返回false。
"55" === 55 // false,数据类型不同
false === 0 // false,数据类型不同
正是因为全等不存在类型转换问题,为了保持代码中数据类型的完整性,我们更应该多使用全等和不全等操作符。
条件操作符
条件操作符是这样使用的:
var result = (5 > 3) ? "对就返回这句话" : "不对就返回这句话"
由一个 ? 和 : 组成,?之前的表达式如果为真就返回 ? 之前 : 之后的表达式,如果为假,就返回 : 之后的表达式
赋值操作符
赋值操作符简单来说就是把右边的值赋给左侧的变量:
var num = 2
;
在赋值操作符之前可以添加一个乘性操作符、加性操作符和位操作符,比如这样:
num += 10 // num = 12
;
逗号操作符
逗号操作符可以在一行语句中执行多个操作:
var num1 = 1, num2 = 2, num3 = 3;
你还可以这样用:
var num = (num1++,num3++,num3) // num 为 4
在赋值语句中,逗号操作符会依次执行每一个语句并且返回表达式的最后一项。
位操作符
对于位操作位,这里不打算进行深入讲解,因为此操作符在JavaScript中并不常用,所有有关内存的操作我们理应交给解释器去做。如果你哪天打算用C语言去做开发,那我一定建议你好好学一学这个操作符。
所有操作符学习完毕,自己也有很大的提升,希望能给各位前端开发者们一些帮助和启发,如果您在阅读过程中发现错误,请大胆指出,我们共同进步。