整数
1 == 1.0 // true
1 === 1.0 // true
JavaScript 内部,所有数字都是以64位浮点数形式储存,即使整数也是如此。所以,1与1.0是相同的,是同一个数。
正0和负0
+0 === -0 // true
-0 === 0 // true
+0 === 0 // true
+0 和 -0的符号表示位不同,正负0的比较只有用ES6中的Object.is判断才返回false
Object.is(+0,-0) // false
Object.is(+0,0) // true
Object.is(-0,0) // false
无穷数
2 ** 1024 // Infinity
1/-0 // -Infinity
根据IEE64标准,64位浮点数的指数部分的长度是11个二进制位,意味着指数部分的最大值是2047(2的11次方减1)。也就是说,64位浮点数的指数部分的值最大为2047,分出一半表示负数,则 JavaScript 能够表示的数值范围为21024到2-1023(开区间),超出这个范围的数无法表示。
如果一个数大于等于2的1024次方,那么就会发生“正向溢出”,即 JavaScript 无法表示这么大的数,这时就会返回Infinity
整数最大/最小值
// 超过范围的计算
9007199254740992 + 1 // 9007199254740992
9007199254740992 + 2 // 9007199254740994
Number.MAX_SAFE_INTEGER === 9007199254740991 // true
Number.MAX_SAFE_INTEGER === 2**53-1 //true
js中整数最大值的安全范围是Number.MIN_SAFE_INTEGER到Number.MAX_SAFE_INTEGER即-(2的53次方-1) 到 (2的53次方-1)
原始类型
Number
String
Null
Undefined
Symbol
BigInt
Symbol
原始类型不可以修改,可以重新赋值
var num = 1;
function changeNumber(n){
num++;
}
console.log(num); // 1
引用类型可以被修改
var obj = {n:1};
function changeObjProperty(o,p){
o[p] = undefined;
}
changeObjProperty(obj,'n');
console.log(obj); // {n: undefined}
比较
[] == ![] // true
NaN !== NaN // true
[] == '' // true
1 == true // true
2 == true // false
"2" == true // flase
null > 0 // false
null < 0 // false
null == 0 // false
null >= 0 // true
对于被广泛使用的比较运算符(==)来说,会在进行比较之前,将两个操作数转换成相同的类型。对于关系运算符(比如 <=)来说,会先将操作数转为原始值,使它们类型相同,再进行比较运算。
比较的特点:
-
对于两个拥有相同字符顺序,相同长度,并且每个字符的位置都匹配的字符串,应该使用严格比较运算符。
-
对于两个数值相同的数字应该使用严格比较运算符,NaN和任何值不相等,包括其自身,正数零等于负数零。
-
对于两个同为true或同为false的布尔操作数,应使用严格比较运算符。
不要使用严格比较运算符或比较运算符来比较两个不相等的对象。 -
当比较一个表达式和一个对象时,仅当两个操作数引用相同的对象(指针指向相同对象)。
-
对于Null 和 Undefined 类型而言,应使用严格比较运算符比较其自身,使用比较运算符进行互相比较。
-
对象和字符串比较,对象转为字符串两者再比较
==,===和Object.is
三个都是判断相等的有什么不同呢,看下面表格
变量x | 变量y | == | === | Object.is |
---|---|---|---|---|
undefined | undefined | true | true | true |
null | null | true | true | true |
true | true | true | true | true |
false | false | true | true | true |
“foo” | “foo” | true | true | true |
0 | 0 | true | true | true |
+0 | -0 | true | true | false |
0 | false | true | false | false |
“” | false | true | false | false |
“” | 0 | true | false | false |
“0” | 0 | true | false | false |
“17” | 17 | true | false | false |
[1,2] | “1,2” | true | false | false |
new String(“foo”) | “foo” | true | false | false |
null | undefined | true | false | false |
null | false | false | false | false |
undefined | false | false | false | false |
{ foo: “bar” } | { foo: “bar” } | false | false | false |
new String(“foo”) | new String(“foo”) | false | false | false |
0 | null | false | false | false |
0 | NaN | false | false | false |
“foo” | NaN | false | false | false |
NaN | NaN | false | false | true |
加法
let obj = {};
{} + 1 // 1,这里的 {} 被当成了代码块 相当于 + 1
{ 1 + 1 } + 1 // 1
obj + 1 // [object Object]1
{} + {} // Chrome 上显示 "[object Object][object Object]",Firefox 显示 NaN
[] + {} // [object Object]
[] + a // [object Object]
+ [] // 等价于 + "" => 0
{} + [] // 0 {} 被当做代码块 相当于 + []
a + [] // [object Object]
[2,3] + [1,2] // '2,31,2'
[2] + 1 // '21'
[2] + (-1) // "2-1"
js在+运算的时候, 会先推断两个操作数是不是Number类型。 如果都是Number类型,则直接相加得出结果。 如果其中有一个操作数为String类型,则将另一个操作数隐式的转换为String,然后进行字符串拼接得出结果。
[]和{}转字符串的不同
String({}) // "[object Object]"
String([]) // ""
减法
// 减法或其他操作,无法进行字符串连接,因此在错误的字符串格式下返回 NaN
[2] - 1 // 1
[2,3] - 1 // NaN
{} - 1 // -1