In the previous article I talked about types and type coercion in JavaScript. In this one I want to talk more about how this coercion applies to JavaScript operators. Lets go over six major operators and look at how they work:
typeof
The typeof
operator returns a string representation of the type of the passed expression. There are two major points to note:
- Unresolvable references will produce
"undefined"
, i.e.typeof a
will return"undefined"
if variablea
was not declared. typeof
lies in two cases fornull
and forfunction () {}
.
Apart from this, operator works pretty much as a lookup table:
Type of expression | Result |
---|---|
Undefined | "undefined" |
Null | "object" ⚠ |
Boolean | "boolean" |
Number | "number" |
String | "string" |
Object, that can’t be invoked | "object" |
Object, that can be invoked | "function" ⚠ |
I marked with “⚠” two places where operator is misleading: type of null
is Null and the actual type of any function is Object.
Subtraction
Converts both arguments to number. "8" - true
is converted to 8 - 1
. Very simple, indeed. Don’t expect the same from addition
Addition
Addition is one of the trickiest operators in JavaScript. Lets see what is going on when you write a + b
:
- Both arguments are converted to primitives. Lets call them
A
andB
. - If any of primitives is a String, concatenate
A
andB
as strings. - Otherwise add
A
andB
as numbers.
For example:
1 | 8 + "5" ➙ "8" + "5" ➙ "85" ; |
2 | 8 + true ➙ 8 + 1 ➙ 9; |
3 | "8" + true ➙ "8" + "true" ➙ "8true" ; |
4 | |
Less-than
In contrast to the addition operator, the less-than operator compares arguments as strings only if both of them are strings. To put it more formally, here are the steps:
- Both arguments are converted to primitives. Lets call them
A
andB
. - If both of primitives are Strings, compare
A
andB
as strings. - Otherwise compare
A
andB
as numbers.
For example:
1 | 8 > "5" ➙ 8 > 5 ➙ true ; |
2 | 8 > true ➙ 8 > 1 ➙ true ; |
3 | "8" > "18" ➙ true ; |
4 | |
Strict Equals
The favourite operator of many, also known as triple equal (===
) does things in a very simple way: checks if the arguments are of the same type and if they are, checks if they are equal. His little brother has a little bit more complicated character.
Equals
Ok, here it comes, the most hated operator of the language. According to the spec it works like so:
- First check for types, if they are the same, apply strict equals.
- If both arguments are either
null
orundefined
, returntrue
. - If one of them is String and the other is Number, convert both to Number and apply strict equals.
- If one of them is Boolean, convert it to Number and go to 1.
- If one of them is String or Number and the other one is Object, convert object into primitive and go to 1.
- Return
false
.
This basically means that equals works like less-than, when the types of the arguments are different and like strict equals, when types are the same. The easy way to remember: when the types are different it converts both arguments into primitives, then into numbers, unless they both are strings. Oh, and null == undefined
is true
.
1 | 8 == "5" ➙ 8 == 5 ➙ false ; |
2 | 1 == true ➙ 1 == 1 ➙ true ; |
3 |
4 | 0 == "" ➙ 0 == 0 ➙ true ; |
5 | 0 == "0" ➙ 0 == 0 ➙ true ; |
6 | "" == "0" ➙ false ; |
7 |
8 | "1000" == "1e3" ➙ false ; |
9 | 1000 == "1e3" ➙ true ; |
10 | 5 == {valueOf: function () { return 5; }} ➙ 5 == 5 ➙ true ; |
11 | |
These are not all the operators, but certainly the most tricky ones.
译文如下
在上一篇文章中,我们讲到了JavaScript中的数据类型和类型转换.今天,我们接着讲一下JavaScript中的每个运算符到底是如何进行类型转换的.下面会依次讲解六个最常用的运算符的工作机制:
typeof
typeof运算符会返回操作数类型的字符串表示
.主要有两个需要注意的地方:
- 未定义或未声明的变量将会返回
"undefined"
, 比如.如果a没有被声明,那么typeof a将会返回
"undefined"
. typeof在操作数是
n
ull或函数的
种情况下会"撒谎"
.
除了这些, 操作数和对应的类型字符串可以从下表查出:
表达式的类型 | 结果 |
---|---|
Undefined | "undefined" |
Null | "object" ⚠ |
Boolean | "boolean" |
Number | "number" |
String | "string" |
Object,不可以被调用 | "object" |
Object,可以被调用 | "function" ⚠ |
我标记“⚠”的两处地方就是上面提到的typeof误导我们的地方:type of null应该返回"
Null",而任意函数的类型应该是"object".
减法(-)
将两边的操作数都转换为数字. "8" - true
会被转换为 8 - 1
.的确非常的简单,不过下面的加法可就不是了.
加法(+)
加法是JavaScript中最麻烦的运算符了.让我们看看在执行a + b的时到底发生了什么
:
- 两边的操作数首先被转换成原始值.这里我们称之为
A
和B
. - 如果有任意一个原始值是字符串,则把另一个也转换成字符串,执行
A和
B的连接操作并返回连接后的字符串
. - 否则把
A和
B都转换为数字,返回两个数字的和
.
例如:
8 + "5" ➙ "8" + "5" ➙ "85"; //"5"是字符串,所以把8也转换成字符串,连接后值为"85" 8 + true ➙ 8 + 1 ➙ 9; //没有字符串,两边都转换成数字,true转换成数字为1,返回相加的和9 "8" + true ➙ "8" + "true" ➙ "8true"; //"8"是字符串,把true也转换成字符串"true",连接后值为"8true"
小于(<)
和加法运算符不同,小于运算符只在两个操作数都为字符串的时候才将他们作为字符串来比较.下面是正式的操作步骤:
- 两边的操作数都转换成原始值.这里我们称之为
A
和 B
. - 如果这个两个原始值都为字符串,则把
A和
B按照字符串来比较
. - 否则将他们都转换位数字,按照数字大小比较.
例如:
8 > "5" ➙ 8 > 5 ➙ true; //两边不都是字符串,"5"转换为数字5 8 > true ➙ 8 > 1 ➙ true; //两边不都是字符串,true转换成数字1 "8" > "18" ➙ true; //两边都是字符串,8的ascii码大于1的ascii码
严格相等(===)
许多运算符中最让人省心的一个,也被称为三等号(===
),它的操作很简单:检查两个操作数的类型是否相等,如果相等的话,检查他们的值是否相等.他的兄弟运算符(==)就比较复杂了.
相等(==)
JavaScript中最让人讨厌的运算符.它的工作机制是这样的:
- 首先检查两个操作数的类型,如果他们是相同的类型,那么继续执行严格相等比较.
- 如果两个操作数都是
null或者是
undefined
,返回true
. - 如果其中一个操作数是字符串另外一个是数字,则将他们都转换数字,再执行严格相等比较.
- 如果其中一个操作数是布尔值,把它转换成数字,然后回到步骤1继续执行.
- 如果其中一个操作数是字符串或者数字,另外一个是对象值,把这个对象值转换成原始值,然后回到步骤1继续执行.
- 返回
false
.
这基本上意味着,如果两个操作数的类型不同,则判断的工作机制类似于小于<比较,如果类型相同,则类似于严格相等比较.总结一下就是:当类型不同时,将两个操作数都转换为原始值,除非两个原始值都是字符串,否则再次将两个原始值转换成数字再比较,还有就是null == undefined是
true
.
8 == "5" ➙ 8 == 5 ➙ false; //"5"转换成数字5 1 == true ➙ 1 == 1 ➙ true; //true转换成数字1 0 == "" ➙ 0 == 0 ➙ true; //""转换成数字0 0 == "0" ➙ 0 == 0 ➙ true; //"0"转换成数字0 "" == "0" ➙ false; //字符串直接判断是否相等 "1000" == "1e3" ➙ false; //字符串直接判断是否相等 1000 == "1e3" ➙ true; //"1e3"转换成1000,科学计数法 5 == {valueOf: function () { return 5; }} ➙ 5 == 5 ➙ true; //对象值转换成原始值5
这六个运算符并不是全部的运算符,但肯定是最麻烦的几个了.
原文:http://blogs.adobe.com/webplatform/2012/09/21/javascript-operators/
译文:http://www.cnblogs.com/ziyunfei/archive/2012/09/24/2699386.html