再看《你不知道的Javascript》总结记录下学习:
//toPrecision(..) 方法用来指定有效数位的显示位数(小数点后面四舍五入),不够的话后面补0
var c = 43.49;
var d = 43.69;
console.log(c.toPrecision(2));//43
console.log(d.toPrecision(2));//44
console.log(c.toPrecision(5));//43.490
var e = 45;
console.log(45..toFixed(3));//45.000 这样则没有问题,因为第一个 . 被视为 number 的一部分,第二个 . 是属性访问运算符。
console.log(45.toFixed(3));//报错,因为数字常量没有.属性的;产生这样的主要原因是因为一个有效的数字字符,会被优先识别为数字常量的一部分,然后才是对象属性访问运算符
整数检测:
在ES6可以直接用Number.isInteger()方法;例如:
console.log(Number.isInteger(42.00));//true
console.log(Number.isInteger(42));//true
console.log(Number.isInteger(42.77));//false
为 ES6 之前的版本 polyfill Number.isInteger(..) 方法:
if(!Number.isInteger){
Number.isInteger = function (num){
return typeof num == 'number' && num%1 == 0;
}
}
特殊数值
JavaScript 数据类型中有几个特殊的值需要开发人员特别注意和小心使用。
*1,不是值的值 *
undefined类型就只有一个值,即undefined,null类型也就只有一个值,即null;但是二者也有细微的差别;例如:
- null指空值(empty value)
- undefined指没有值(missing value)
又或者: - null 指曾赋过值,现在没有值
- undefined指从未赋值
由于undefined 在非严格模式下,是全局标识符,并很容易被改变(设计欠缺考虑造成的);所以我们就要用到void 运算符,表达式 void _ 没有返回值,因此返回结果是 undefined。void 并不改变表达式的结果,只是让表达式不返回值;
例如:
var a = 2;
console.log(void a,a) // undefined 2
void 0、void 1 和 undefined 之间并没有实质上的区别。所以,如果要将代码中的值(如表达式的返回值)设为 undefined,就可以使用 void。
特殊的数字
数字类型中有几个特殊的值,下面将详细介绍:
1,不是数字的数字
如果数学运算的操作数不是数字类型(或者无法解析为常规的十进制或十六进制数字),就无法返回一个有效的数字,这种情况下返回值为 NaN。
NaN 意指“不是一个数字”(not a number),如:
var a = 2/'a';
console.log(a)//NaN;
console,log(typeof === a)//number;
换句话说,“不是数字的数字”仍然是数字类型。
NaN 是一个“警戒值”(sentinel value,有特殊用途的常规值),用于指出数字类型中的错误情况,即“执行数学运算没有成功,这是失败后返回的结果”。
如果要检查变量的值是否为 NaN,可以直接和 NaN 进行比较,就像比较 null
和 undefined 那样。实则不然。
var a = 2/'a';
console.log(a)//NaN;
console.log(a === NaN) //false;
console,log(typeof === a)//number;
NaN 是一个特殊值,它和自身不相等,是唯一一个非自反(自反,reflexive,即 x === x 不成立)的值。而 NaN != NaN 为 true,很奇怪吧?
我们一般如果对NaN进行比较,用isNaN()函数方法,但是这也存在bug; 如下��
var a = 2/'a';
var b = 'sff';
var c = 3;
console.log(isNaN(a));//true
console.log(isNaN(b));//true 这,这不对啊?
console.log(isNaN(c));//false
so,这时候有个好用的方法就是ES6 新增的 Number.isNaN();
var a = 2/'a';
var b = 'sff';
var c = 3;
console.log(Number.isNaN(a));//true
console.log(Number.isNaN(b));//false 这就对了
console.log(Number.isNaN(c));//false
but,这有兼容问题,比如IE;这时候可以做个polyfill处理
if(!Number.isNaN){
Number.isNaN = function(n){
return(
typeof n === 'number'&& isNaN(n)
)
}
}
console.log(Number.isNaN(a));
console.log(Number.isNaN(b));
console.log(Number.isNaN(c));
还有一种处理方法、就是利用NaN自身特性 NaN !==NaN 为true
if(!Number.isNaN){
Number.isNaN = function(n){
return n !== n;
}
}
2、无穷数;3、无穷数 (忽略了��)
4、特殊等式
ES6新增一个方法Object.is()来判断两个值是否绝对相等;例如:
var a = 2/'a';
var e = 0/-3;
console.log(Object.is(a,NaN));//true
console.log(Object.is(e,-0));//true
对于 ES6 之前的版本,Object.is(..) 有一个简单的 polyfill:
if(!Object.is()){
Object.is = function(v1,v2){
//判断是否-0
if(v1 === 0 && v2 === 0){
return 1/v1 === 1/v2;
}
//判断是否NaN
if(v1 !== v1){
return v2 !== v2;
}
//其他情况
return v1 === v2;
}
}
能使用 == 和 ===(参见第 4 章)时就尽量不要使用 Object.is(..),因为前者效率更高、更为通用。Object.is(..) 主要用来处理那些特殊的相等比较
5、值和引用
js对值和引用的赋值/传递在语法上并没有区别,完全根据值的类型来确定;例如:
var a = 2;
var b = a; // b是a的值的一个副本
b++;
console.log(a);//2
console.log(b);//3
var c = [1,2,3];
var d = c;//d是[1,2,3]的一个引用
d.push('5');
console.log(c);//[1,2,3,5]
console.log(d);//[1,2,3,5]
简单值(即标量基本类型值,scalar primitive)总是通过值复制的方式来赋值 / 传递,包括null、undefined、字符串、数字、布尔和 ES6 中的 symbol
复合值(compound value)——对象(包括数组和封装对象,参见第 3 章)和函数,则总是通过引用复制的方式来赋值 / 传递。
上例中 2 是一个标量基本类型值,所以变量 a 持有该值的一个复本,b 持有它的另一个复本。b 更改时,a 的值保持不变。
c 和 d 则分别指向同一个复合值 [1,2,3] 的两个不同引用。请注意,c 和 d 仅仅是指向值[1,2,3],并非持有。所以它们更改的是同一个值(如调用 .push(5)),随后它们都指向更改后的新值 [1,2,3,5]。
由于引用指向的是值本身而非变量,所以一个引用无法更改另一个引用的指向。
//接上面的例子
var e = c
e = [4,5,6]
console.log(c);//[1,2,3,5]
console.log(e);//[4,5,6]
e = [4,5,6] 并不影响c指向[1,2,3,5],除非e不是指向数组的引用,而是指向c的引用,但是这在js是不可能存在这种情况的。
JavaScript 中的引用和其他语言中的引用 / 指针不同,它们不能指向别的变量 / 引用,只能指向值。