4月阅读周·你不知道的JavaScript | 从值的转换到数学计算,ES6新增API,辅助完成常见的任务

举报
叶一一 发表于 2024/04/22 09:38:28 2024/04/22
【摘要】 背景去年下半年,我在微信书架里加入了许多技术书籍,各种类别的都有,断断续续的读了一部分。没有计划的阅读,收效甚微。新年伊始,我准备尝试一下其他方式,比如阅读周。每月抽出1~2个非连续周,完整阅读一本书籍。这个“玩法”虽然常见且板正,但是有效,已经坚持阅读三个月。4月份的阅读计划有两本,《你不知道的JavaScrip》系列迎来收尾。已读完书籍:《架构简洁之道》、《深入浅出的Node.js》、《...

背景

去年下半年,我在微信书架里加入了许多技术书籍,各种类别的都有,断断续续的读了一部分。

没有计划的阅读,收效甚微。

新年伊始,我准备尝试一下其他方式,比如阅读周。每月抽出1~2个非连续周,完整阅读一本书籍。

这个“玩法”虽然常见且板正,但是有效,已经坚持阅读三个月。

4月份的阅读计划有两本,《你不知道的JavaScrip》系列迎来收尾。

已读完书籍《架构简洁之道》、《深入浅出的Node.js》、《你不知道的JavaScript(上卷)》、《你不知道的JavaScript(中卷)》

当前阅读周书籍《你不知道的JavaScript(下卷)》

新增API

Object

从ES6开始,Object静态方法也开始用于那些还没有更自然的有另外归属的(比如Array.from(..))通用全局API。

静态函数Object.is(..)

静态函数Object.is(..)执行比===比较更严格的值比较。

比如:

var x = NaN,
  y = 0,
  z = -0;

x === x; // false
y === z; // true

Object.is(x, x); // true
Object.is(y, z); // false

应该继续使用===进行严格相等比较;不应该把Object.is(..)当作这个运算符的替代。但是,如果需要严格识别NaN或者-0值,那么应该选择Object.is(..)。

静态函数Object.getOwnPropertySymbols(..)

Symbol很可能会成为对象最常用的特殊(元)属性。所以引入了工具Object.getOwnPropertySymbols(..),它直接从对象上取得所有的符号属性:

var o = {
  foo: 42,
  [Symbol('bar')]: 'hello world',
  baz: true,
};

Object.getOwnPropertySymbols(o); // [ Symbol(bar) ]

静态函数Object.setPrototypeOf(..)

工具Object.setPrototypeOf(..)设置对象的[[Prototype]]用于行为委托。

比如:

var o1 = {
  foo() {
    console.log('foo');
  },
};

var o2 = Object.setPrototypeOf(
  {
    // .. o2的定义 ..
  },
  o1,
);

// 委托给o1.foo()
o2.foo(); // foo

更通俗地说,o2和o1的关系在o2的定义上指定。

静态函数Object.assign(..)

ES6新增了Object.assign(..),这是这些算法的简化版本。第一个参数是target,其他传入的参数都是源,它们将按照列出的顺序依次被处理。对于每个源来说,它的可枚举和自己拥有的(也就是不是“继承来的”)键值,包括符号都会通过简单=赋值被复制。Object.assign(..)返回目标对象。

var target = {},
  o1 = { a: 1 },
  o2 = { b: 2 },
  o3 = { c: 3 },
  o4 = { d: 4 };

// 设定只读属性
Object.defineProperty(o3, 'e', {
  value: 5,
  enumerable: true,
  writable: false,
  configurable: false,
});

// 设定不可枚举属性
Object.defineProperty(o3, 'f', {
  value: 6,
  enumerable: false,
});

o3[Symbol('g')] = 7;

// 设定不可枚举符号
Object.defineProperty(o3, Symbol('h'), {
  value: 8,
  enumerable: false,
});

Object.setPrototypeOf(o3, o4);
Object.assign(target, o1, o2, o3);

target.a; // 1
target.b; // 2
target.c; // 3

Object.getOwnPropertyDescriptor(target, 'e');
// { value: 5, writable: true, enumerable: true,
//   configurable: true }

Object.getOwnPropertySymbols(target);
// [Symbol("g")]

只有属性a、b、c、e以及Symbol("g")会被复制到target中。

Math

ES6增加了几个新的数学工具,填补了常用计算方面的空白。

这些工具的使用者更可能是asm.js/transpile的JavaScript代码,而非直接开发者。

三角函数

双曲余弦函数:

cosh(..)

反双曲余弦函数:

acosh(..)

双曲正弦函数:

sinh(..)

反双曲正弦函数:

asinh(..)

双曲正切函数:

tanh(..)

反双曲正切函数:

atanh(..)

平方和的平方根(也即:广义勾股定理):

hypot(..)

算术

立方根:

cbrt(..)

计算32位二进制表示的前导0个数:

clz32(..)

等价于exp(x) -1:

expm1(..)

二进制对数(以2为底的对数):

log2(..)

以10为底的对数:

log10(..)

等价于log(x + 1):

log1p(..)

两个数字的32位整数乘法:

imul(..)

元工具

返回数字符号:

sign(..)

返回数字的整数部分向:

trunc(..)

最接近的32位(单精度)浮点值取整:

fround(..)

Number

对Number的两个新增内容就是指向已有的全局函数的引用: Number.parseInt(..)和Number.parseFloat(..)。

静态属性

ES6新增了一些作为静态属性的辅助数字常量:

  • Number.EPSILON

任意两个值之间的最小差:2^-52(使用了这个值作为浮点数算法的精度误差值)

  • Number.MAX SAFE INTEGER

JavaScript可以用数字值无歧义“安全”表达的最大整数:2^53-1

  • Number.MIN SAFE INTEGER

JavaScript可以用数字值无歧义“安全”表达的最小整数:-(2^53-1)或(-2)^53+ 1

静态函数Number.isNaN(..)

标准全局工具isNaN(..)自出现以来就是有缺陷的,它对非数字的东西都会返回true,而不是只对真实的NaN值返回true,因为它把参数强制转换为数字类型(可能会错误地导致NaN)。ES6增加了一个修正工具Number.isNaN(..),可以按照期望工作:

var a = NaN,
  b = 'NaN',
  c = 42;
isNaN(a); // true

isNaN(b); // true--oops!
isNaN(c); // false

Number.isNaN(a); // true
Number.isNaN(b); // false--修正了!
Number.isNaN(c); // false

静态函数Number.isFinite(..)

Number.isFinite(..)用来检查一个数值是否是有限的。

标准的全局isFinite(..)会对参数进行强制类型转换,但是Number.isFinite(..)会略去这种强制行为。比如:

var a = NaN,
  b = Infinity,
  c = 42;

Number.isFinite(a); // false
Number.isFinite(b); // false

Number.isFinite(c); // true
var a = '42';

isFinite(a); // true
Number.isFinite(a); // false

整型相关静态函数

JavaScript的数字值永远都是浮点数(IEE-754)。所以确定数字是否为“整型”的概念并不是检查其类型,因为JavaScript并没有这样区分。

ES6新增了一个辅助工具Number.isInteger(..),检查这个值的小数部分是否非0:

Number.isInteger(4); // true
Number.isInteger(4.2); // false

另外,Number.isInteger(..) 会过滤掉x === Math.floor(x)可能会搞混的明显非整数值:

Number.isInteger(NaN); // false
Number.isInteger(Infinity); // false

ES6还定义了一个工具Number.isSafeInteger(..),这个工具检查一个值以确保其为整数并且在Number.MIN SAFE INTEGER-Number.MAX SAFE INTEGER范围之内(全包含):

var x = Math.pow(2, 53),
  y = Math.pow(-2, 53);

Number.isSafeInteger(x - 1); // true
Number.isSafeInteger(y + 1); // true

Number.isSafeInteger(x); // false
Number.isSafeInteger(y); // false

字符串

Unicode函数

String.fromCodePoint(..)、String#codePointAt(..)和String#normalize(..)。新增这些函数是为了提高JavaScript字符串值对Unicode的支持。

字符串原型方法normalize(..) 用于执行Unicode规范化,或者把字符用“合并符”连接起来或者把合并的字符解开。

一般来说,规范化不会对字符串的内容造成可见的效果,但是会改变字符串的内容,这可能会影响像length属性的结果,以及通过位置访问字符的方式:

var s1 = 'e\u0301';
s1.length; // 2

var s2 = s1.normalize();
s2.length; // 1
s2 === '\xE9'; // true

normalize(..)接受一个可选的参数,来指定要使用的规范化形式。这个参数必须是这几个值之一:"NFC" ( 默认)、 "NFD"、 "NFKC"或者"NFKD"。

静态函数String.raw(..)

String.raw(..)工具作为内置标签函数提供,与模板字符串字面值(参见第2章)一起使用,用于获得不应用任何转义序列的原始字符串。

这个函数基本上不会被手动调用,而是与标签模板字面值一起使用:

var str = 'bc';

String.raw`\ta${str}d\xE9`;
// "\tabcd\xE9", 而不是"  abcdé"

在结果字符串中,\和t是独立的原始字符,而不是转义字符\t。对于Unicode转义序列也是一样。

原型函数repeat(..)

ES6定义了一个字符串原型方法repeat(..)来完成复制的任务:

'foo'.repeat(3); // "foofoofoo"

字符串检查函数

除了ES6之前的String#indexOf(..)和String#lastIndexOf(..),又新增了3个用于搜索/检查的新方法:startsWith(..)、endsWidth(..)和includes(..)。

var palindrome = 'step on no pets';

palindrome.startsWith('step on'); // true
palindrome.startsWith('on', 5); // true

palindrome.endsWith('no pets'); // true
palindrome.endsWith('no', 10); // true

palindrome.includes('on'); // true
palindrome.includes('on', 6); // false

对于所有的字符串搜索/检查方法,如果寻找空字符串"",总是会在字符串的开头或结尾找到。

总结

我们来总结一下本篇的主要内容:

  • Object新增了静态函数is(..)和assign(..)。
  • Math新增了静态函数acosh(..)和clz32(..)。
  • Number新增了静态属性Number.EPSILON,以及静态函数Number.isFinite(..)。
  • String新增了静态函数String.fromCodePoint(..)和String.raw(..),以及原型函数repeat(..)和includes(..)。

作者介绍
非职业「传道授业解惑」的开发者叶一一。
《趣学前端》、《CSS畅想》等系列作者。华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。
如果看完文章有所收获,欢迎点赞👍 | 收藏️ | 留言📝

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。