目录

对象的新方法

 

Object

Object.is()

Object.is()用来比较两个值是否严格相等。它与严格比较运算符(===)的行为基本一致,不同之处只有两个:一是+0不等于-0,二是NaN等于自身。

+0 === -0 //true
NaN === NaN // false
 
Object.is(+0, -0) // false
Object.is(NaN, NaN) // true

Object.assign()

Object.assign方法用来将源对象(source)的所有可枚举属性,复制到目标对象(target)。它至少需要两个对象作为参数,第一个参数是目标对象,后面的参数都是源对象。只要有一个参数不是对象,就会抛出TypeError错误。

var target = { a: 1 };
 
var source1 = { b: 2 };
var source2 = { c: 3 };
  
Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}

注意,如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。

var target = { a: 1, b: 1 };
 
var source1 = { b: 2, c: 2 };
var source2 = { c: 3 };
 
Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}

为对象添加属性

通过assign方法,将x属性和y属性添加到Point类的对象实例。

class Point {
  constructor(x, y) {
    Object.assign(this, {x, y});
  }
}

为对象添加方法

使用了对象属性的简洁表示法,直接将两个函数放在大括号中,再使用assign方法添加到SomeClass.prototype之中。

Object.assign(SomeClass.prototype, {
  someMethod(arg1, arg2) {
    ···
  },
  anotherMethod() {
    ···
  }
});
 
// 等同于下面的写法
SomeClass.prototype.someMethod = function (arg1, arg2) {
  ···
};
SomeClass.prototype.anotherMethod = function () {
  ···
};

克隆对象

将原始对象拷贝到一个空对象,就得到了原始对象的克隆。

function clone(origin) {
  return Object.assign({}, origin);
}

为属性指定默认值

DEFAULTS对象是默认值,options对象是用户提供的参数。assign方法将DEFAULTS和options合并成一个新对象,如果两者有同名属性,则option的属性值会覆盖DEFAULTS的属性值。

const DEFAULTS = {
  logLevel: 0,
  outputFormat: 'html'
};
 
function processContent(options) {
  let options = Object.assign({}, DEFAULTS, options);
}

Object.setPrototypeOf()

Object.setPrototypeOf方法的作用与proto相同,用来设置一个对象的prototype对象。它是ES6正式推荐的设置原型对象的方法。

// 格式
Object.setPrototypeOf(object, prototype)
 
// 用法
var o = Object.setPrototypeOf({}, null);

该方法等同于下面的函数。

function (obj, proto) {
  obj.__proto__ = proto;
  return obj;
}

Object.getPrototypeOf()

该方法与setPrototypeOf方法配套,用于读取一个对象的prototype对象。

Object.getPrototypeOf(obj)

Array

Array.from()

Array.from()用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象,其中包括ES6新增的Set和Map结构。

let ps = document.querySelectorAll('p');
 
Array.from(ps).forEach(function (p) {
  console.log(p);
});

上面代码中,querySelectorAll方法返回的是一个类似数组的对象,只有将这个对象转为真正的数组,才能使用forEach方法。

Array.from()还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理。

Array.from(arrayLike, x => x * x);
// 等同于
Array.from(arrayLike).map(x => x * x);
Array.from()的一个应用是,将字符串转为数组,然后返回字符串的长度。这样可以避免JavaScript将大于\uFFFF的Unicode字符,算作两个字符的bug。
 
function countSymbols(string) {
  return Array.from(string).length;
}

Array.of()

Array.of()方法用于将一组值,转换为数组。

Array.of(3, 11, 8) // [3,11,8]
Array.of(3).length // 1

这个函数的主要目的,是弥补数组构造函数Array()的不足。因为参数个数的不同,会导致Array()的行为有差异。

Array() // []
Array(3) // [undefined, undefined, undefined]
Array(3,11,8) // [3, 11, 8]

上面代码说明,只有当参数个数不少于2个,Array()才会返回由参数组成的新数组。

Array.prototype.find()

数组实例的find()用于找出第一个符合条件的数组元素。它的参数是一个回调函数,所有数组元素依次遍历该回调函数,直到找出第一个返回值为true的元素,然后返回该元素,否则返回undefined。

[1, 5, 10, 15].find(function(value, index, arr) {
  return value > 9;
}) // 10

从上面代码可以看到,回调函数接受三个参数,依次为当前的值、当前的位置和原数组。

Array.prototype.findIndex()

数组实例的findIndex()的用法与find()非常类似,返回第一个符合条件的数组元素的位置,如果所有元素都不符合条件,则返回-1。

[1, 5, 10, 15].findIndex(function(value, index, arr) {
  return value > 9;
}) // 2

这两个方法都可以接受第二个参数,用来绑定回调函数的this对象。

另外,这两个方法都可以发现NaN,弥补了IndexOf()的不足。

[NaN].indexOf(NaN) 
// -1
 
[NaN].findIndex(y => Object.is(NaN, y))
// 0

Array.prototype.entries()

ES6提供三个新的方法——entries()用于遍历数组。返回一个遍历器,可以用for…of循环进行遍历,entries()是对键值对的遍历。

for (let [index, elem] of ['a', 'b'].entries()) {
  console.log(index, elem);
}
// 0 "a"
// 1 "b"

Array.prototype.keys()

ES6提供三个新的方法—keys()用于遍历数组。返回一个遍历器,可以用for…of循环进行遍历,keys()是对键名的遍历。

for (let index of ['a', 'b'].keys()) {
  console.log(index);
}
// 0
// 1

Array.prototype.values()

ES6提供三个新的方法values()用于遍历数组。返回一个遍历器,可以用for…of循环进行遍历,values()是对键值的遍历。

for (let elem of ['a', 'b'].values()) {
  console.log(elem);
}
// 'a'
// 'b'

Number

Number.isFinite()

检查Infinite值。传统方法先调用Number()将非数值的值转为数值,再进行判断,而新方法只对数值有效,非数值一律返回false。

isFinite(25) // true
isFinite("25") // true
Number.isFinite(25) // true
Number.isFinite("25") // false

Number.isNaN()

检查NaN值。传统方法先调用Number()将非数值的值转为数值,再进行判断,而新方法只对数值有效,非数值一律返回false。

isNaN(NaN) // true
isNaN("NaN") // true
Number.isNaN(NaN) // true
Number.isNaN("NaN") // false

Number.parseInt()

ES6将全局方法parseInt()和parseFloat(),移植到Number对象上面,行为完全保持不变。步减少全局性方法,使得语言逐步模块化。

// ES5的写法
parseInt("12.34") // 12
 
// ES6的写法
Number.parseInt("12.34") // 12

Number.parseFloat()

ES6将全局方法parseInt()和parseFloat(),移植到Number对象上面,行为完全保持不变。步减少全局性方法,使得语言逐步模块化。

// ES5的写法
parseFloat('123.45#') // 123.45
  
// ES6的写法
Number.parseFloat('123.45#') // 123.45

Number.isInteger()

Number.isInteger()用来判断一个值是否为整数。需要注意的是,在JavaScript内部,整数和浮点数是同样的储存方法,所以3和3.0被视为同一个值。

Number.isInteger(25) // true
Number.isInteger(25.0) // true
Number.isInteger(25.1) // false

JavaScript能够准确表示的整数范围在-2ˆ53 and 2ˆ53之间。ES6引入了Number.MAX_SAFE_INTEGER和Number.MIN_SAFE_INTEGER这两个常量,用来表示这个范围的上下限。Number.isSafeInteger()则是用来判断一个整数是否落在这个范围之内。

var inside = Number.MAX_SAFE_INTEGER;
var outside = inside + 1;
  
Number.isInteger(inside) // true
Number.isSafeInteger(inside) // true
 
Number.isInteger(outside) // true
Number.isSafeInteger(outside) // false

Math

Math.trunc()

Math.trunc方法用于去除一个数的小数部分,返回整数部分。

Math.trunc(4.1) // 4
Math.trunc(4.9) // 4
Math.trunc(-4.1) // -4
Math.trunc(-4.9) // -4

数字方法

ES6在Math对象上还提供了许多新的数学方法。

String

String.prototype.codePointAt()

JavaScript内部,字符以UTF-16的格式储存,每个字符固定为2个字节。对于那些需要4个字节储存的字符(Unicode码点大于0xFFFF的字符),JavaScript会认为它们是两个字符。

var s = "𠮷";
 
s.length // 2
s.charAt(0) // ''
s.charAt(1)    // ''
s.charCodeAt(0) // 55362        
s.charCodeAt(1) // 57271

上面代码中,汉字“𠮷”的码点是0x20BB7,UTF-16编码为0xD842 0xDFB7(十进制为55362 57271),需要4个字节储存。对于这种4个字节的字符,JavaScript不能正确处理,字符串长度会误判为2,而且charAt方法无法读取字符,charCodeAt方法只能分别返回前两个字节和后两个字节的值。

ES6提供了codePointAt方法,能够正确处理4个字节储存的字符,返回一个字符的码点。

var s = "𠮷a";
 
s.codePointAt(0) // 134071
s.codePointAt(1) // 57271
  
s.charCodeAt(2) // 97

codePointAt方法的参数,是字符在字符串中的位置(从0开始)。上面代码中,JavaScript将“𠮷a”视为三个字符,codePointAt方法在第一个字符上,正确地识别了“𠮷”,返回了它的十进制码点134071(即十六进制的20BB7)。在第二个字符(即“𠮷”的后两个字节)和第三个字符“a”上,codePointAt方法的结果与charCodeAt方法相同。

总之,codePointAt方法会正确返回四字节的UTF-16字符的码点。对于那些两个字节储存的常规字符,它的返回结果与charCodeAt方法相同。

codePointAt方法是测试一个字符由两个字节还是由四个字节组成的最简单方法。

function is32Bit(c) {
  return c.codePointAt(0) > 0xFFFF;
}
  
is32Bit("𠮷") // true
is32Bit("a") // false

String.fromCodePoint()

ES5提供String.fromCharCode方法,用于从码点返回对应字符,但是这个方法不能识别辅助平面的字符(编号大于0xFFFF)。

String.fromCharCode(0x20BB7)
// "ஷ"

上面代码中,最后返回码点U+0BB7对应的字符,而不是码点U+20BB7对应的字符。

ES6提供了String.fromCodePoint方法,可以识别0xFFFF的字符,弥补了String.fromCharCode方法的不足。在作用上,正好与codePointAt方法相反。

String.fromCodePoint(0x20BB7) 
// "𠮷"

注意,fromCodePoint方法定义在String对象上,而codePointAt方法定义在字符串的实例对象上。

String.prototype.at()

ES5提供String.prototype.charAt方法,返回字符串给定位置的字符。该方法不能识别码点大于0xFFFF的字符。

'𠮷'.charAt(0)
// '\uD842'

上面代码中,charAt方法返回的是UTF-16编码的第一个字节,实际上是无法显示的。

ES7提供了at方法,可以识别Unicode编号大于0xFFFF的字符,返回正确的字符。

'𠮷'.at(0)
// '𠮷'