Object.is()用来比较两个值是否严格相等。它与严格比较运算符(===)的行为基本一致,不同之处只有两个:一是+0不等于-0,二是NaN等于自身。
+0 === -0 //true NaN === NaN // false Object.is(+0, -0) // false Object.is(NaN, NaN) // true
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方法的作用与proto相同,用来设置一个对象的prototype对象。它是ES6正式推荐的设置原型对象的方法。
// 格式 Object.setPrototypeOf(object, prototype) // 用法 var o = Object.setPrototypeOf({}, null);
该方法等同于下面的函数。
function (obj, proto) { obj.__proto__ = proto; return obj; }
该方法与setPrototypeOf方法配套,用于读取一个对象的prototype对象。
Object.getPrototypeOf(obj)
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(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()才会返回由参数组成的新数组。
数组实例的find()用于找出第一个符合条件的数组元素。它的参数是一个回调函数,所有数组元素依次遍历该回调函数,直到找出第一个返回值为true的元素,然后返回该元素,否则返回undefined。
[1, 5, 10, 15].find(function(value, index, arr) { return value > 9; }) // 10
从上面代码可以看到,回调函数接受三个参数,依次为当前的值、当前的位置和原数组。
数组实例的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
ES6提供三个新的方法——entries()用于遍历数组。返回一个遍历器,可以用for…of循环进行遍历,entries()是对键值对的遍历。
for (let [index, elem] of ['a', 'b'].entries()) { console.log(index, elem); } // 0 "a" // 1 "b"
ES6提供三个新的方法—keys()用于遍历数组。返回一个遍历器,可以用for…of循环进行遍历,keys()是对键名的遍历。
for (let index of ['a', 'b'].keys()) { console.log(index); } // 0 // 1
ES6提供三个新的方法values()用于遍历数组。返回一个遍历器,可以用for…of循环进行遍历,values()是对键值的遍历。
for (let elem of ['a', 'b'].values()) { console.log(elem); } // 'a' // 'b'
检查Infinite值。传统方法先调用Number()将非数值的值转为数值,再进行判断,而新方法只对数值有效,非数值一律返回false。
isFinite(25) // true isFinite("25") // true Number.isFinite(25) // true Number.isFinite("25") // false
检查NaN值。传统方法先调用Number()将非数值的值转为数值,再进行判断,而新方法只对数值有效,非数值一律返回false。
isNaN(NaN) // true isNaN("NaN") // true Number.isNaN(NaN) // true Number.isNaN("NaN") // false
ES6将全局方法parseInt()和parseFloat(),移植到Number对象上面,行为完全保持不变。步减少全局性方法,使得语言逐步模块化。
// ES5的写法 parseInt("12.34") // 12 // ES6的写法 Number.parseInt("12.34") // 12
ES6将全局方法parseInt()和parseFloat(),移植到Number对象上面,行为完全保持不变。步减少全局性方法,使得语言逐步模块化。
// ES5的写法 parseFloat('123.45#') // 123.45 // ES6的写法 Number.parseFloat('123.45#') // 123.45
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.trunc方法用于去除一个数的小数部分,返回整数部分。
Math.trunc(4.1) // 4 Math.trunc(4.9) // 4 Math.trunc(-4.1) // -4 Math.trunc(-4.9) // -4
ES6在Math对象上还提供了许多新的数学方法。
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
ES5提供String.fromCharCode方法,用于从码点返回对应字符,但是这个方法不能识别辅助平面的字符(编号大于0xFFFF)。
String.fromCharCode(0x20BB7) // "ஷ"
上面代码中,最后返回码点U+0BB7对应的字符,而不是码点U+20BB7对应的字符。
ES6提供了String.fromCodePoint方法,可以识别0xFFFF的字符,弥补了String.fromCharCode方法的不足。在作用上,正好与codePointAt方法相反。
String.fromCodePoint(0x20BB7) // "𠮷"
注意,fromCodePoint方法定义在String对象上,而codePointAt方法定义在字符串的实例对象上。
ES5提供String.prototype.charAt方法,返回字符串给定位置的字符。该方法不能识别码点大于0xFFFF的字符。
'𠮷'.charAt(0) // '\uD842'
上面代码中,charAt方法返回的是UTF-16编码的第一个字节,实际上是无法显示的。
ES7提供了at方法,可以识别Unicode编号大于0xFFFF的字符,返回正确的字符。
'𠮷'.at(0) // '𠮷'