← 返回目录

12. 对象扩展 / 数值扩展

ES6 对象和数值扩展:Object.assign、Object.keys、Number 新方法。

核心四个:
Object.assign()——合并对象
Object.keys() / values() / entries()——拿键/值/键值对
Number.isFinite() / Number.isNaN()——比全局的更严格
Number.parseInt / parseFloat——替代全局

坑:Object.assign 是浅拷贝、Object.keys 返回数组、Number.isNaN 只判断 NaN

12.1 互动演示

点按钮看扩展方法的输出。

12.2 知识点讲解

一、对象扩展

① Object.is:比 === 更"较真"

=== 平时够用,但它对两个特殊情况很"糊涂":它觉得 NaN === NaN 是 false,还觉得 0 === -0 是 true。Object.is 就是来纠正这两点的。

// false(=== 糊涂了)
console.log(NaN === NaN);

// true ← 较真:NaN 等于 NaN
console.log(Object.is(NaN, NaN));

// true (=== 觉得 ±0 一样)
console.log(0 === -0);

// false ← 较真:0 不等于 -0
console.log(Object.is(0, -0));

如果你平时只是想判断两个值相不相等,用 === 就够了。只有两种场景才需要 Object.is:要判断的可能是 NaN,或者要区分 +0 和 -0。

② Object.assign:合并对象(合并配置必备)

想象你有一份"默认配置",用户又传了一份"自定义配置",想把后者盖到前者上——Object.assign(目标, 源1, 源2...) 就是干这个的。

// 先有个目标对象(默认配置)
let target = { a: 1 };

// 以前:一个个手动加
// 手动加 b
target.b = 2;

// 手动加 c
target.c = 3;

// 现在:一次把多个源对象的属性并进目标
// 把后面两个源对象挨个倒进 target
Object.assign(target, { b: 2 }, { c: 3 });

// ^^^^^^ ^^^^^^^^ ^^^^^^^^
// 加到这 来自源1 来自源2
// {a:1, b:2, c:3}
console.log(target);

Object.assign(目标, 源1, 源2...) 会把后面所有源对象的属性逐个"并"进目标;同名属性后面的覆盖前面的。做"默认配置 + 用户配置"合并时最常用——用户没传的项用默认,传了的项盖掉默认。

二、数值扩展

③ 进制新写法

以前写二进制、八进制容易写错,ES6 给了明确的前缀:0b 是二进制,0o 是八进制,0x 是十六进制。

// 10(0b 开头是二进制)
console.log(0b1010);

// 15(0o 开头是八进制)
console.log(0o17);

// 31(0x 开头是十六进制)
console.log(0x1f);

④ Number 方法更严格(不偷摸转类型)

全局的 isNaN 是个"老好人",会偷偷把传进来的东西先转成数字再判断;Number.isNaN 不转类型,老老实实只认真正的 NaN。

// 全局 isNaN:宽松,先偷偷转类型
// true("abc" 被转成 NaN 了)
console.log(isNaN("abc"));

// Number.isNaN:严格,不转类型
// false("abc" 根本不是 NaN)
console.log(Number.isNaN("abc"));

// false(不是整数)
console.log(Number.isInteger(3.5));

// 3(直接砍掉小数部分,不四舍五入)
console.log(Math.trunc(3.9));

如果你用全局 isNaN("abc") 判断"这是不是一个 NaN",得到 true 就会被误导——它其实是因为 "abc" 转不成数字才 true 的。判断是不是真 NaN 用 Number.isNaN,判断整数用 Number.isInteger,砍小数用 Math.trunc

12.3 实战:用在哪 / 常见坑 / 怎么解决

① 可能在什么地方用:合并默认配置与用户配置(Object.assign)、判断两个值是否严格相同(特殊情况用 Object.is)、表单校验是否整数(Number.isInteger)、取整(Math.trunc)。

② 常见的问题:用全局 isNaN 把字符串误判成 NaN;Object.assign 直接改了原对象(目标和源传成同一个);把 Math.trunc 当成四舍五入。

③ 解决思路:要纯判断就用 Number.isNaN;合并时目标传一个空对象 {} 避免污染源;要四舍五入用 Math.roundMath.trunc 只负责砍小数。

一句话:Object.is 更较真、Object.assign 一键合并;数字有进制新写法、Number.isNaN 等方法更严格

本页重点

API作用参数返回值代码示例
Object.is(a, b)更较真地比较:认 NaN、区分 +0/-0两个值true / falseObject.is(NaN, NaN);
Object.assign(t, s)把后面源对象的属性合并到目标上目标, 源对象...目标对象Object.assign(o, { a: 1 });
Number.isNaN(x)严格判断是不是 NaN(不误判字符串)一个值true / falseNumber.isNaN("x");
0b / 0o / 0x二/八/十六进制写法,值不变数字数字0b1010; // 10