es6新增的api

从值的转换到数学计算,ES6给各类内建原生类型和对象增长了许多静态属性和方法来辅助这些常见任务。另外,一些原生类型的实例经过各类新的原型方法得到了新的能力。javascript

注意: 大多数这些特性均可以被忠实地填补。咱们不会在这里深刻这样的细节,可是关于兼容标准的shim/填补,你能够看一下“ES6 Shim”(https://github.com/paulmillr/es6-shim/)。java

Array

在JS中被各类用户库扩展得最多的特性之一就是数组类型。ES6在数组上增长许多静态的和原型(实例)的帮助功能应当并不使人惊讶。git

Array.of(..) 静态函数

Array(..)的构造器有一个尽人皆知的坑:若是仅有一个参数值被传递,并且这个参数值是一个数字的话,它并不会制造一个含有一个带有该数值元素的数组,而是构建一个长度等于这个数字的空数组。这种操做形成了不幸的和怪异的“空值槽”行为,而这正是JS数组为人诟病的地方。es6

Array.of(..)做为数组首选的函数型构造器取代了Array(..),由于Array.of(..)没有那种单数字参数值的状况。考虑以下代码:github

var a = Array( 3 ); a.length; // 3 a[0]; // undefined var b = Array.of( 3 ); b.length; // 1 b[0]; // 3 var c = Array.of( 1, 2, 3 ); c.length; // 3 c; // [1,2,3]

在什么样的环境下,你才会想要是使用Array.of(..)来建立一个数组,而不是使用像c = [1,2,3]这样的字面语法呢?有两种可能的状况。正则表达式

若是你有一个回调,传递给它的参数值本应当被包装在一个数组中时,Array.of(..)就完美地符合条件。这可能不是那么常见,可是它能够为你的痒处挠上一把。算法

另外一种场景是若是你扩展Array构成它的子类,并且但愿可以在一个你的子类的实例中建立和初始化元素,好比:数组

class MyCoolArray extends Array { sum() { return this.reduce( function reducer(acc,curr){ return acc + curr; }, 0 ); } } var x = new MyCoolArray( 3 ); x.length; // 3 -- 噢! x.sum(); // 0 -- 噢! var y = [3]; // Array,不是 MyCoolArray y.length; // 1 y.sum(); // `sum` is not a function var z = MyCoolArray.of( 3 ); z.length; // 1 z.sum(); // 3

你不能(简单地)只建立一个MyCoolArray的构造器,让它覆盖Array父构造器的行为,由于这个父构造器对于实际建立一个规范的数组值(初始化this)是必要的。在MyCoolArray子类上“被继承”的静态of(..)方法提供了一个不错的解决方案。安全

Array.from(..) 静态函数

在JavaScript中一个“类数组对象”是一个拥有length属性的对象,这个属性明确地带有0或更高的整数值。数据结构

在JS中处理这些值出了名地让人沮丧;将它们变形为真正的数组曾经是十分常见的作法,这样各类Array.property方法(map(..)indexOf(..)等等)才能与它一块儿使用。这种处理一般看起来像:

// 类数组对象 var arrLike = { length: 3, 0: "foo", 1: "bar" }; var arr = Array.prototype.slice.call( arrLike );

另外一种slice(..)常常被使用的常见任务是,复制一个真正的数组:

var arr2 = arr.slice();

在这两种状况下,新的ES6Array.from(..)方法是一种更易懂并且更优雅的方式 —— 也不那么冗长:

var arr = Array.from( arrLike ); var arrCopy = Array.from( arr );

Array.from(..)会查看第一个参数值是不是一个可迭代对象(参见第三章的“迭代器”),若是是,它就使用迭代器来产生值,并将这些值“拷贝”到将要被返回的数组中。由于真正的数组拥有一个能够产生这些值的迭代器,因此这个迭代器会被自动地使用。

可是若是你传递一个类数组对象做为Array.from(..)的第一个参数值,它的行为基本上是和slice()(不带参数值的!)或apply()相同的,它简单地循环全部的值,访问从0开始到length值的由数字命名的属性。

考虑以下代码:

var arrLike = {
    length: 4, 2: "foo" }; Array.from( arrLike ); // [ undefined, undefined, "foo", undefined ]

由于在arrLike上不存在位置01,和3,因此对这些值槽中的每个,结果都是undefined值。

你也能够这样产生相似的结果:

var emptySlotsArr = [];
emptySlotsArr.length = 4; emptySlotsArr[2] = "foo"; Array.from( emptySlotsArr ); // [ undefined, undefined, "foo", undefined ]

避免空值槽

前面的代码段中,在emptySlotsArrArray.from(..)调用的结果有一个微妙但重要的不一样。Array.from(..)从不产生空值槽。

在ES6以前,若是你想要制造一个被初始化为在每一个值槽中使用实际undefined值(不是空值槽!)的特定长数组,你不得不作一些额外的工做:

var a = Array( 4 ); // 四个空值槽! var b = Array.apply( null, { length: 4 } ); // 四个 `undefined` 值

但如今Array.from(..)使这件事简单了些:

var c = Array.from( { length: 4 } ); // 四个 `undefined` 值

警告: 使用一个像前面代码段中的a那样的空值槽数组能够与一些数组函数工做,可是另外一些函数会忽略空值槽(好比map(..)等)。你永远不该该刻意地使用空值槽,由于它几乎确定会在你的程序中致使奇怪/不可预料的行为。

映射

Array.from(..)工具还有另一个绝技。第二个参数值,若是被提供的话,是一个映射函数(和普通的Array#map(..)几乎相同),它在将每一个源值映射/变形为返回的目标值时调用。考虑以下代码:

var arrLike = { length: 4, 2: "foo" }; Array.from( arrLike, function mapper(val,idx){ if (typeof val == "string") { return val.toUpperCase(); } else { return idx; } } ); // [ 0, 1, "FOO", 3 ]

注意: 就像其余接收回调的数组方法同样,Array.from(..)接收可选的第三个参数值,它将被指定为做为第二个参数传递的回调的this绑定。不然,this将是undefined

一个使用Array.from(..)将一个8位值数组翻译为16位值数组的例子,参见第五章的“类型化数组”。

建立 Arrays 和子类型

在前面几节中,咱们讨论了Array.of(..)Array.from(..),它们都用与构造器类似的方法建立一个新数组。可是在子类中它们会怎么作?它们是建立基本Array的实例,仍是建立衍生的子类的实例?

class MyCoolArray extends Array { .. } MyCoolArray.from( [1, 2] ) instanceof MyCoolArray; // true Array.from( MyCoolArray.from( [1, 2] ) ) instanceof MyCoolArray; // false

of(..)from(..)都使用它们被访问时的构造器来构建数组。因此若是你使用基本的Array.of(..)你将获得Array实例,但若是你使用MyCoolArray.of(..),你将获得一个MyCoolArray实例。

在第三章的“类”中,咱们讲解了在全部内建类(好比Array)中定义好的@@species设定,它被用于任何建立新实例的原型方法。slice(..)是一个很棒的例子:

var x = new MyCoolArray( 1, 2, 3 ); x.slice( 1 ) instanceof MyCoolArray; // true

通常来讲,这种默认行为将多是你想要的,可是正如咱们在第三章中讨论过的,若是你想的话你 能够 覆盖它:

class MyCoolArray extends Array { // 强制 `species` 为父类构造器 static get [Symbol.species]() { return Array; } } var x = new MyCoolArray( 1, 2, 3 ); x.slice( 1 ) instanceof MyCoolArray; // false x.slice( 1 ) instanceof Array; // true

要注意的是,@@species设定仅适用于原型方法,好比slice(..)of(..)from(..)不使用它;它们俩都只使用this绑定(哪一个构造器被用于发起引用)。考虑以下代码:

class MyCoolArray extends Array { // 强制 `species` 为父类构造器 static get [Symbol.species]() { return Array; } } var x = new MyCoolArray( 1, 2, 3 ); MyCoolArray.from( x ) instanceof MyCoolArray; // true MyCoolArray.of( [2, 3] ) instanceof MyCoolArray; // true

copyWithin(..) 原型方法

Array#copyWithin(..)是一个对全部数组可用的新修改器方法(包括类型化数组;参加第五章)。copyWithin(..)将数组的一部分拷贝到同一个数组的其余位置,覆盖以前存在在那里的任何东西。

它的参数值是 目标(要被拷贝到的索引位置),开始(拷贝开始的索引位置(含)),和可选的 结束(拷贝结束的索引位置(不含))。若是这些参数值中存在任何负数,那么它们就被认为是相对于数组的末尾。

考虑以下代码:

[1,2,3,4,5].copyWithin( 3, 0 ); // [1,2,3,1,2] [1,2,3,4,5].copyWithin( 3, 0, 1 ); // [1,2,3,1,5] [1,2,3,4,5].copyWithin( 0, -2 ); // [4,5,3,4,5] [1,2,3,4,5].copyWithin( 0, -2, -1 ); // [4,2,3,4,5]

copyWithin(..)方法不会扩张数组的长度,就像前面代码段中的第一个例子展现的。当到达数组的末尾时拷贝就会中止。

与你可能想象的不一样,拷贝的顺序并不老是从左到右的。若是起始位置与目标为重叠的话,它有可能形成已经被拷贝过的值被重复拷贝,这大概不是你指望的行为。

因此在这种状况下,算法内部经过相反的拷贝顺序来避免这个坑。考虑以下代码:

[1,2,3,4,5].copyWithin( 2, 1 ); // ???

若是算法是严格的从左到右,那么2应当被拷贝来覆盖3,而后这个被拷贝的2应当被拷贝来覆盖4,而后这个被拷贝的2应当被拷贝来覆盖5,而你最终会获得[1,2,2,2,2]

与此不一样的是,拷贝算法把方向反转过来,拷贝4来覆盖5,而后拷贝3来覆盖4,而后拷贝2来覆盖3,而最后的结果是[1,2,2,3,4]。就期待的结果而言这可能更“正确”,可是若是你仅以单纯的从左到右的方式考虑拷贝算法的话,它就可能让人糊涂。

fill(..) 原型方法

ES6中的Array#fill(..)方法原生地支持使用一个指定的值来彻底地(或部分地)填充一个既存的数组:

var a = Array( 4 ).fill( undefined ); a; // [undefined,undefined,undefined,undefined]

fill(..)可选地接收 开始 与 结束 参数,它们指示要被填充的数组的一部分,好比:

var a = [ null, null, null, null ].fill( 42, 1, 3 ); a; // [null,42,42,null]

find(..) 原型方法

通常来讲,在一个数组中搜索一个值的最多见方法曾经是indexOf(..)方法,若是值被找到的话它返回值的位置索引,没有找到的话返回-1

var a = [1,2,3,4,5]; (a.indexOf( 3 ) != -1); // true (a.indexOf( 7 ) != -1); // false (a.indexOf( "2" ) != -1); // false

indexOf(..)比较要求一个严格===匹配,因此搜索"2"找不到值2,反之亦然。没有办法覆盖indexOf(..)的匹配算法。不得不手动与值-1进行比较也很不幸/不优雅。

提示: 一个使用~操做符来绕过难看的-1的有趣(并且争议性地使人糊涂)技术,参见本系列的 类型与文法

从ES5开始,控制匹配逻辑的最多见的迂回方法是some(..)。它的工做方式是为每个元素调用一个回调函数,直到这些调用中的一个返回true/truthy值,而后它就会中止。由于是由你来定义这个回调函数,因此你就拥有了如何作出匹配的彻底控制权:

var a = [1,2,3,4,5]; a.some( function matcher(v){ return v == "2"; } ); // true a.some( function matcher(v){ return v == 7; } ); // false

但这种方式的缺陷是你只能使用true/false来指示是否找到了合适的匹配值,而不是实际被匹配的值。

ES6的find(..)解决了这个问题。它的工做方式基本上与some(..)相同,除了一旦回调返回一个true/truthy值,实际的数组值就会被返回:

var a = [1,2,3,4,5]; a.find( function matcher(v){ return v == "2"; } ); // 2 a.find( function matcher(v){ return v == 7; // undefined });

使用一个自定义的matcher(..)函数还容许你与对象这样的复杂值进行匹配:

var points = [
    { x: 10, y: 20 }, { x: 20, y: 30 }, { x: 30, y: 40 }, { x: 40, y: 50 }, { x: 50, y: 60 } ]; points.find( function matcher(point) { return ( point.x % 3 == 0 && point.y % 4 == 0 ); } ); // { x: 30, y: 40 }

注意: 和其余接收回调的数组方法同样,find(..)接收一个可选的第二参数。若是它被设置了的话,就将被指定为做为第一个参数传递的回调的this绑定。不然,this将是undefined

findIndex(..) 原型方法

虽然前一节展现了some(..)如何在一个数组检索给出一个Boolean结果,和find(..)如何从数组检索中给出匹配的值,可是还有一种需求是寻找匹配的值的位置索引。

indexOf(..)能够完成这个任务,可是没有办法控制它的匹配逻辑;它老是使用===严格等价。因此ES6的findIndex(..)才是答案:

var points = [ { x: 10, y: 20 }, { x: 20, y: 30 }, { x: 30, y: 40 }, { x: 40, y: 50 }, { x: 50, y: 60 } ]; points.findIndex( function matcher(point) { return ( point.x % 3 == 0 && point.y % 4 == 0 ); } ); // 2 points.findIndex( function matcher(point) { return ( point.x % 6 == 0 && point.y % 7 == 0 ); } ); // -1

不要使用findIndex(..) != -1(在indexOf(..)中常常这么干)来从检索中取得一个boolean,由于some(..)已经给出了你想要的true/false了。并且也不要用a[ a.findIndex(..) ]来取得一个匹配的值,由于这是find(..)完成的任务。最后,若是你须要严格匹配的索引,就使用indexOf(..),若是你须要一个更加定制化的匹配,就使用findIndex(..)

注意: 和其余接收回调的数组方法同样,find(..)接收一个可选的第二参数。若是它被设置了的话,就将被指定为做为第一个参数传递的回调的this绑定。不然,this将是undefined

entries()values()keys() 原型方法

在第三章中,咱们展现了数据结构如何经过一个迭代器来提供一种模拟逐个值的迭代。而后咱们在第五章探索新的ES6集合(Map,Set,等)如何为了产生不一样种类的迭代器而提供几种方法时阐述了这种方式。

由于Array并非ES6的新东西,因此它可能不被认为是一个传统意义上的“集合”,可是在它提供了相同的迭代器方法:entries()values(),和keys()的意义上,它是的。考虑以下代码:

var a = [1,2,3]; [...a.values()]; // [1,2,3] [...a.keys()]; // [0,1,2] [...a.entries()]; // [ [0,1], [1,2], [2,3] ] [...a[Symbol.iterator]()]; // [1,2,3]

就像Set同样,默认的Array迭代器与values()放回的东西相同。

在本章早先的“避免空值槽”一节中,咱们展现了Array.from(..)如何将一个数组中的空值槽看做带有undefined的存在值槽。其实际的缘由是,在底层数组迭代器就是以这种方式动做的:

var a = []; a.length = 3; a[1] = 2; [...a.values()]; // [undefined,2,undefined] [...a.keys()]; // [0,1,2] [...a.entries()]; // [ [0,undefined], [1,2], [2,undefined] ]

Object

几个额外的静态帮助方法已经被加入Object。从传统意义上讲,这种种类的函数是关注于对象值的行为/能力的。

可是,从ES6开始,Object静态函数还用于任意种类的通用全局API —— 那些尚未更天然地存在于其余的某些位置的API(例如,Array.from(..))。

Object.is(..) 静态函数

Object.is(..)静态函数进行值的比较,它的风格甚至要比===比较还要严格。

Object(..)调用底层的SameValue算法(ES6语言规范,第7.2.9节)。SameValue算法基本上与===严格等价比较算法相同(ES6语言规范,第7.2.13节),可是带有两个重要的例外。

考虑以下代码:

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(..)是如今的首选方式。

注意: ES6还增长了一个Number.isNaN(..)工具(在本章稍后讨论),它多是一个稍稍方便一些的测试;比起Object.is(x, NaN)你可能更偏好Number.isNaN(x)。你 能够 使用笨拙的x == 0 && 1 / x === -Infinity来准确地测试-0,但在这种状况下Object.is(x,-0)要好得多。

Object.getOwnPropertySymbols(..) 静态函数

第二章中的“Symbol”一节讨论了ES6中的新Symbol基本值类型。

Symbol可能将是在对象上最常常被使用的特殊(元)属性。因此引入了Object.getOwnPropertySymbols(..),它仅取回直接存在于对象上的symbol属性:

var o = { foo: 42, [ Symbol( "bar" ) ]: "hello world", baz: true }; Object.getOwnPropertySymbols( o ); // [ Symbol(bar) ]

Object.setPrototypeOf(..) 静态函数

仍是在第二章中,咱们提到了Object.setPrototypeOf(..)工具,它为了 行为委托 的目的(意料之中地)设置一个对象的[[Prototype]](参见本系列的 this与对象原型)。考虑以下代码:

var o1 = { foo() { console.log( "foo" ); } }; var o2 = { // .. o2 的定义 .. }; Object.setPrototypeOf( o2, o1 ); // 委托至 `o1.foo()` o2.foo(); // foo

另外一种方式:

var o1 = { foo() { console.log( "foo" ); } }; var o2 = Object.setPrototypeOf( { // .. o2 的定义 .. }, o1 ); // 委托至 `o1.foo()` o2.foo(); // foo

在前面两个代码段中,o2o1之间的关系都出如今o2定义的末尾。更常见的是,o2o1之间的关系在o2定义的上面被指定,就像在类中,并且在对象字面量的__proto__中也是这样(参见第二章的“设置[[Prototype]]”)。

警告: 正如展现的那样,在对象建立以后当即设置[[Prototype]]是合理的。可是在好久以后才改变它通常不是一个好主意,并且常常会致使困惑而非清晰。

Object.assign(..) 静态函数

许多JavaScript库/框架都提供将一个对象的属性拷贝/混合到另外一个对象中的工具(例如,jQuery的extend(..))。在这些不一样的工具中存在着各类微妙的区别,好比一个拥有undefined值的属性是否被忽略。

ES6增长了Object.assign(..),它是这些算法的一个简化版本。第一个参数是 目标对象 而全部其余的参数是 源对象,它们会按照罗列的顺序被处理。对每个源对象,它本身的(也就是,不是“继承的”)可枚举键,包括symbol,将会好像经过普通=赋值那样拷贝。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; // 设置不可枚举 symbol Object.defineProperty( o3, Symbol( "h" ), { value: 8, enumerable: false } ); Object.setPrototypeOf( o3, o4 );

仅有属性abce,和Symbol("g")将被拷贝到target

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")]

属性df,和Symbol("h")在拷贝中被忽略了;非枚举属性和非自身属性将会被排除在赋值以外。另外,e做为一个普通属性赋值被拷贝,而不是做为一个只读属性被复制。

在早先一节中,咱们展现了使用setPrototypeOf(..)来在对象o2o1之间创建一个[[Prototype]]关系。这是利用Object.assign(..)的另一种形式:

var o1 = { foo() { console.log( "foo" ); } }; var o2 = Object.assign( Object.create( o1 ), { // .. o2 的定义 .. } ); // 委托至 `o1.foo()` o2.foo(); // foo

注意: Object.create(..)是一个ES5标准工具,它建立一个[[Prototype]]连接好的空对象。更多信息参见本系列的 this与对象原型

Math

ES6增长了几种新的数学工具,它们协助或填补了常见操做的空白。全部这些操做均可以被手动计算,可是它们中的大多数如今都被原生地定义,这样JS引擎就能够优化计算的性能,或者进行与手动计算比起来小数精度更高的计算。

与直接的开发者相比,asm.js/转译的JS代码(参见本系列的 异步与性能)更多是这些工具的使用者。

三角函数:

  • cosh(..) - 双曲余弦
  • acosh(..) - 双曲反余弦
  • sinh(..) - 双曲正弦
  • asinh(..) - 双曲反正弦
  • tanh(..) - 双曲正切
  • atanh(..) - 双曲反正切
  • hypot(..) - 平方和的平方根(也就是,广义勾股定理)

算数函数:

  • cbrt(..) - 立方根
  • clz32(..) - 计数32位二进制表达中前缀的零
  • expm1(..) - 与exp(x) - 1相同
  • log2(..) - 二进制对数(以2为底的对数)
  • log10(..) - 以10为底的对数
  • log1p(..) - 与log(x + 1)相同
  • imul(..) - 两个数字的32为整数乘法

元函数:

  • sign(..) - 返回数字的符号
  • trunc(..) - 仅返回一个数字的整数部分
  • fround(..) - 舍入到最接近的32位(单精度)浮点数值

Number

重要的是,为了你的程序可以正常工做,它必须准确地处理数字。ES6增长了一些额外的属性和函数来辅助常见的数字操做。

两个在Number上新增的功能只是既存全局函数的引用:Number.parseInt(..)Number.parseFloat(..)

静态属性

ES6以静态属性的形式增长了一些有用的数字常数:

  • Number.EPSILON - 在任意两个数字之间的最小值:2^-52(关于为了应对浮点算数运算不精确的问题而将这个值用作容差的讲解,参见本系列的 类型与文法 的第二章)
  • Number.MAX_SAFE_INTEGER - 能够用一个JS数字值明确且“安全地”表示的最大整数:2^53 - 1
  • Number.MIN_SAFE_INTEGER - 能够用一个JS数字值明确且“安全地”表示的最小整数:-(2^53 - 1)(-2)^53 + 1.

注意: 关于“安全”整数的更多信息,参见本系列的 类型与文法 的第二章。

Number.isNaN(..) 静态函数

标准的全局isNaN(..)工具从一开始就坏掉了,由于不只对实际的NaN值返回true,并且对不是数字的东西也返回true。其缘由是它会将参数值强制转换为数字类型(这可能失败而致使一个NaN)。ES6增长了一个修复过的工具Number.isNaN(..),它能够正确工做:

var a = NaN, b = "NaN", c = 42; isNaN( a ); // true isNaN( b ); // true —— 噢! isNaN( c ); // false Number.isNaN( a ); // true Number.isNaN( b ); // false —— 修好了! Number.isNaN( c ); // false

Number.isFinite(..) 静态函数

看到像isFinite(..)这样的函数名会诱令人们认为它单纯地意味着“不是无限”。但这不十分正确。这个新的ES6工具备更多的微妙之处。考虑以下代码:

var a = NaN, b = Infinity, c = 42; Number.isFinite( a ); // false Number.isFinite( b ); // false Number.isFinite( c ); // true

标准的全局isFinite(..)会强制转换它收到的参数值,可是Number.isFinite(..)会省略强制转换的行为:

var a = "42"; isFinite( a ); // true Number.isFinite( a ); // false

你可能依然偏好强制转换,这时使用全局isFinite(..)是一个合法的选择。或者,而且多是更明智的选择,你可使用Number.isFinite(+x),它在将x传递前明确地将它强制转换为数字(参见本系列的 类型与文法 的第四章)。

整数相关的静态函数

JavaScript数字值老是浮点数(IEEE-754)。因此断定一个数字是不是“整数”的概念与检查它的类型无关,由于JS没有这样的区分。

取而代之的是,你须要检查这个值是否拥有非零的小数部分。这样作的最简单的方法一般是:

x === Math.floor( x );

ES6增长了一个Number.isInteger(..)帮助工具,它能够潜在地断定这种性质,并且效率稍微高一些:

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

注意: 在JavaScript中,44.4.0,或4.0000之间没有区别。它们都将被认为是一个“整数”,所以都会从Number.isInteger(..)中给出true

另外,Number.isInteger(..)过滤了一些明显的非整数值,它们在x === Math.floor(x)中可能会被混淆:

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

有时候处理“整数”是信息的重点,它能够简化特定的算法。因为为了仅留下整数而进行过滤,JS代码自己不会运行得更快,可是当仅有整数被使用时引擎能够采起几种优化技术(例如,asm.js)。

由于Number.isInteger(..)NanInfinity值的处理,定义一个isFloat(..)工具并不像!Number.isInteger(..)同样简单。你须要这么作:

function isFloat(x) { return Number.isFinite( x ) && !Number.isInteger( x ); } isFloat( 4.2 ); // true isFloat( 4 ); // false isFloat( NaN ); // false isFloat( 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

String

在ES6以前字符串就已经拥有好几种帮助函数了,可是有更多的内容被加入了进来。

Unicode 函数

在第二章的“Unicode敏感的字符串操做”中详细讨论了String.fromCodePoint(..)String#codePointAt(..)String#normalize(..)。它们被用来改进JS字符串值对Unicode的支持。

String.fromCodePoint( 0x1d49e ); // "𝒞" "ab𝒞d".codePointAt( 2 ).toString( 16 ); // "1d49e"

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"

注意: 规范化形式和它们在字符串上的效果超出了咱们要在这里讨论的范围。更多细节参见“Unicode规范化形式”(http://www.unicode.org/reports/tr15/)。

String.raw(..) 静态函数

String.raw(..)工具被做为一个内建的标签函数来与字符串字面模板(参见第二章)一块儿使用,取得不带有任何转译序列处理的未加工的字符串值。

这个函数几乎永远不会被手动调用,可是将与被标记的模板字面量一块儿使用:

var str = "bc"; String.raw`\ta${str}d\xE9`; // "\tabcd\xE9", not " abcdé"

在结果字符串中,`和t是分离的未被加工过的字符,而不是一个转译字符序列\t`。这对Unicode转译序列也是同样。

repeat(..) 原型函数

在Python和Ruby那样的语言中,你能够这样重复一个字符串:

"foo" * 3; // "foofoofoo"

在JS中这不能工做,由于*乘法是仅对数字定义的,所以"foo"会被强制转换为NaN数字。

可是,ES6定义了一个字符串原型方法repeat(..)来完成这个任务:

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

字符串检验函数

做为对ES6之前的String#indexOf(..)String#lastIndexOf(..)的补充,增长了三个新的搜索/检验函数: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

对于全部这些字符串搜索/检验方法,若是你查询一个空字符串"",那么它将要么在字符串的开头被找到,要么就在字符串的末尾被找到。

警告: 这些方法默认不接受正则表达式做为检索字符串。关于关闭实施在第一个参数值上的isRegExp检查的信息,参见第七章的“正则表达式Symbol”。

复习

ES6在各类内建原生对象上增长了许多额外的API帮助函数:

  • Array增长了of(..)from(..)之类的静态函数,以及copyWithin(..)fill(..)之类的原型函数。
  • Object增长了is(..)assign(..)之类的静态函数。
  • Math增长了acosh(..)clz32(..)之类的静态函数。
  • Number增长了Number.EPSILON之类的静态属性,以及Number.isFinite(..)之类的静态函数。
  • String增长了String.fromCodePoint(..)String.raw(..)之类的静态函数,以及repeat(..)includes(..)之类的原型函数。

这些新增函数中的绝大多数均可以被填补(参见ES6 Shim),它们都是受常见的JS库/框架中的工具启发的。

相关文章
相关标签/搜索