那些你不知道的js-卷一
1. 特殊类型
因为typeof null === "object"
因此我们需要使用复合条件来检测 null 值的类型
var a = null;
(!a && typeof a === "object"); // true
还有一种情况: typeof function a(){ /* .. */ } === "function";
这样看来,function(函数)也是 JavaScript 的一个内置类型。然而查阅规范就会知道, 它实际上是 object 的一个“子类型”。具体来说,函数是“可调用对象”,它有一个内部属性[[Call]]
,该属性使其可以被调用。
函数不仅是对象,还可以拥有属性。例如:
function a(b,c) {
/* .. */
}
a.length; // 2
函数对象的 length 属性是其声明的参数的个数。
2. typeof
typeof 运算符总是会返回一个字符串
typeof typeof 42; // "string"
typeof 42 首先返回字符串 “number”,然后 typeof “number” 返回 “string”。
3. 数组
如果字符串键值能够被强制类型转换为十进制数字的话,它就会被当作数字索引来处理
var a = [ ];
a["13"] = 42;
a.length; // 14
4. 数字
JavaScript 使用的是“双精度”格式(即 64 位二进制)。
Number.EPSILON
判断 0.1 + 0.2 和 0.3 是否相等呢?
Number.EPSILON 是 JavaScript 中的一个内置常量,它表示在浮点数运算中可接受的最小误差范围。
在 JavaScript 中,由于浮点数的存储方式和运算规则,会导致一些精度问题。例如,当两个浮点数非常接近时,它们可能在计算中产生微小的误差。Number.EPSILON 提供了一个标准的误差范围,用于比较浮点数的相等性。
你可以使用 Number.EPSILON 来判断两个浮点数是否相等,例如:
function isEqual(a, b) {
return Math.abs(a - b) < Number.EPSILON;
}
console.log(isEqual(0.1 + 0.2, 0.3)); // true
在上面的例子中,由于浮点数运算的精度问题,0.1 + 0.2 的结果并不等于 0.3。但是通过使用 Number.EPSILON
,我们可以判断它们是否在可接受的误差范围内,从而得到正确的比较结果。
总之,Number.EPSILON 是用于处理浮点数精度问题的一个常量,可以帮助我们进行更准确的浮点数比较。
5. 整数的安全范围
能够被“安全”呈现的最大整数是2^53 - 1,即9007199254740991,在ES6中被定义为 Number.MAX_SAFE_INTEGER。 最 小 整 数 是 -9007199254740991, 在 ES6 中 被 定 义 为 Number. MIN_SAFE_INTEGER。
有时 JavaScript 程序需要处理一些比较大的数字,如数据库中的 64 位 ID 等。由于 JavaScript 的数字类型无法精确呈现 64 位数值,所以必须将它们保存(转换)为字符串。
6. Number.isInteger() 整数检测
要检测一个值是否是整数,可以使用 ES6 中的 Number.isInteger(..) 方法
Number.isInteger( 42 ); // true
Number.isInteger( 42.000 ); // true
Number.isInteger( 42.3 ); // false
也可以为 ES6 之前的版本 polyfill Number.isInteger(..) 方法
if (!Number.isInteger) {
Number.isInteger = function(num) {
return typeof num == "number" && num % 1 == 0;
};
}
7. NaN
NaN是一个特殊值,它和自身不相等,是唯一一个非自反(自反,reflexive,即x === x不 成立)的值。而 NaN != NaN 为 true
判断是否NAN
// 方法一
function hasNaN(x) {
return x !== x;
}
// 方法二:es6
Number.isNaN(2);
8. 无穷数
任何数除以0都是没有意义的,在传统编译型语言(如 C)就会报错,然而在 JavaScript 中上例的结果为 Infinity(即 Number.POSITIVE_INfiNITY)
var a = 1 / 0; // Infinity
var b = -1 / 0; // -Infinity
9. 0和-0
加法和减法运算不会得到负零
-0转为字符串会变成0
将-0字符串转为数字会变成0
function isNegZero(n) {
n = Number( n );
return (n === 0) && (1 / n === -Infinity);
}
isNegZero( -0 );
isNegZero( 0 / -3 );
isNegZero( 0 );
// true
// true
// false
10. Object.is() 处理特殊等式
如前所述,NaN 和 -0 在相等比较时的表现有些特别。由于 NaN 和自身不相等,所以必须使 用 ES6 中的 Number.isNaN(..)(或者 polyfill)。而 -0 等于 0(对于 === 也是如此,参见第 4 章),因此我们必须使用 isNegZero(..) 这样的工具函数。
ES6 中新加入了一个工具方法 Object.is(..) 来判断两个值是否绝对相等,可以用来处理 上述所有的特殊情况
var a = 2 / "foo";
var b = -3 * 0;
Object.is( a, NaN );
Object.is( b, -0 );
Object.is( b, 0 );
11. 值和引用
由于引用指向的是值本身而非变量,所以一个引用无法更改另一个引用的指向
var a = [1,2,3];
var b = a;
a; // [1,2,3]
b; // [1,2,3]
// 然后
b = [4,5,6];
a; // [1,2,3]
b; // [4,5,6]
b=[4,5,6]
并不影响 a 指向值 [1,2,3]
,除非 b 不是指向数组的引用,而是指向 a 的指针, 但在 JavaScript 中不存在这种情况!函数参数就经常让人产生这样的困惑
function foo(x) {
x.push(4);
x; // [1,2,3,4]
// 然后
x = [4, 5, 6];
x.push(7);
x; // [4,5,6,7]
}
var a = [1, 2, 3];
foo(a);
a; // 是[1,2,3,4],不是[4,5,6,7]
我们向函数传递 a 的时候,实际是将引用 a 的一个复本赋值给 x,而 a 仍然指向 [1,2,3]。在函数中我们可以通过引用x来更改数组的值(push(4)之后变为[1,2,3,4])。但x = [4,5,6] 并不影响 a 的指向,所以 a 仍然指向 [1,2,3,4]。
我们不能通过引用 x 来更改引用 a 的指向,只能更改 a 和 x 共同指向的值。
如果要将 a 的值变为 [4,5,6,7],必须更改 x 指向的数组,而不是为 x 赋值一个新的数组。
function foo(x) {
x.push( 4 );
x; // [1,2,3,4]
// 然后
x.length = 0; // 清空数组 x.push( 4, 5, 6, 7 );
x; // [4,5,6,7]
}
var a = [1,2,3];
foo( a );
a; // 是[4,5,6,7],不是[1,2,3,4]
从上例可以看出,x.length = 0和x.push(4,5,6,7)并没有创建一个新的数组,而是更改 了当前的数组。于是 a 指向的值变成了 [4,5,6,7]。
- 感谢你赐予我前进的力量
本网站的原创文章部分资源内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系博主邮箱:zzyo.yj@outlook.com 进行删除处理
本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向博主举报
声明:版权所有,违者必究 | 如未注明,均为原创 | 本网站采用CC BY-NC-SA 4.0 协议进行授权
转载:转载请注明原文链接 - Lycoris