ES6各大數(shù)據(jù)類型的擴(kuò)展

一、字符串?dāng)U展

  1. includes()startsWith()、endsWith()。傳統(tǒng)JavaScript只有indexOf()方法用來確定一個(gè)字符串是否包含在另一個(gè)字符串中,ES6又提供了三個(gè)新方法。
  • includes():返回布爾值,表示是否找到了參數(shù)字符串。
  • startsWith():返回布爾值,表示參數(shù)字符串是否在原字符串的頭部。
  • endsWith():返回布爾值,表示參數(shù)字符串是否在原字符串的尾部。
let s = 'Hello world!';

s.startsWith('Hello') // true
s.endsWith('!') // true
s.includes('o') // true

這三個(gè)方法都支持第二個(gè)參數(shù),表示開始搜索的位置。但是使用第二個(gè)參數(shù)n時(shí),endsWith的行為與其他兩個(gè)方法有所不同。它針對(duì)前n個(gè)字符,而其他兩個(gè)方法針對(duì)從第n個(gè)位置直到字符串結(jié)束。

let s = 'Hello world!';

s.startsWith('world', 6) // true
s.endsWith('Hello', 5) // true
s.includes('Hello', 6) // false
  1. repeatrepeat方法返回一個(gè)新字符串,表示將原字符串重復(fù)n次。
'x'.repeat(3) // "xxx"
'hello'.repeat(2) // "hellohello"
'na'.repeat(0) // ""
  • 參數(shù)如果是小數(shù),會(huì)被向下取整。
  • 如果repeat的參數(shù)是負(fù)數(shù)或者Infinity,會(huì)報(bào)錯(cuò)。
  • 0 到-1 之間的小數(shù),則等同于 0,這是因?yàn)闀?huì)先進(jìn)行取整運(yùn)算。0 到-1 之間的小數(shù),取整以后等于-0repeat視同為 0。
  • 參數(shù)NaN等同于 0。
  • 如果repeat的參數(shù)是字符串,則會(huì)先轉(zhuǎn)換成數(shù)字。
  1. padStart()、padEnd()。ES2017 引入了字符串補(bǔ)全長(zhǎng)度的功能。如果某個(gè)字符串不夠指定長(zhǎng)度,會(huì)在頭部或尾部補(bǔ)全。padStart()用于頭部補(bǔ)全,padEnd()用于尾部補(bǔ)全。
'x'.padStart(5, 'ab') // 'ababx'
'x'.padStart(4, 'ab') // 'abax'

'x'.padEnd(5, 'ab') // 'xabab'
'x'.padEnd(4, 'ab') // 'xaba'
  • 如果原字符串的長(zhǎng)度,等于或大于指定的最小長(zhǎng)度,則返回原字符串。
  • 如果用來補(bǔ)全的字符串與原字符串,兩者的長(zhǎng)度之和超過了指定的最小長(zhǎng)度,則會(huì)截去超出位數(shù)的補(bǔ)全字符串。
  • 如果省略第二個(gè)參數(shù),默認(rèn)使用空格補(bǔ)全長(zhǎng)度。
  1. 模板字符串。
    模板字符串是增強(qiáng)版的字符串,用反引號(hào)(`)標(biāo)識(shí)。它可以當(dāng)作普通字符串使用,也可以用來定義多行字符串,或者在字符串中嵌入變量。
  • 如果在模板字符串中需要使用反引號(hào),則前面要用反斜杠轉(zhuǎn)義。
  • 如果使用模板字符串表示多行字符串,所有的空格和縮進(jìn)都會(huì)被保留在輸出之中。
  • 模板字符串中嵌入變量,需要將變量名寫在${}之中。
  • 大括號(hào)內(nèi)部可以放入任意的 JavaScript 表達(dá)式,可以進(jìn)行運(yùn)算,以及引用對(duì)象屬性。
  • 模板字符串之中還能調(diào)用函數(shù)。
  • 如果大括號(hào)中的值不是字符串,將按照一般的規(guī)則轉(zhuǎn)為字符串。比如,大括號(hào)中是一個(gè)對(duì)象,將默認(rèn)調(diào)用對(duì)象的toString方法。
  • 如果模板字符串中的變量沒有聲明,將報(bào)錯(cuò)。
var name = "追逐",trait = "帥氣";
//es
var str = "我叫"+name+",人非常"+trait+",說話又好聽";

//es6
var str2 = `我叫 ${name} ,人非常 ${trait} ,說話又好聽`;
  1. 標(biāo)簽?zāi)0濉D0遄址梢跃o跟在一個(gè)函數(shù)名后面,該函數(shù)將被調(diào)用來處理這個(gè)模板字符串。這被稱為“標(biāo)簽?zāi)0濉惫δ堋?/li>
alert`123`
// 等同于
alert(123)

標(biāo)簽?zāi)0迤鋵?shí)不是模板,而是函數(shù)調(diào)用的一種特殊形式?!皹?biāo)簽”指的就是函數(shù),緊跟在后面的模板字符串就是它的參數(shù)。如果模板字符里面有變量,就不是簡(jiǎn)單的調(diào)用了,而是會(huì)將模板字符串先處理成多個(gè)參數(shù),再調(diào)用函數(shù)。

let a = 5;
let b = 10;

tag`Hello ${ a + b } world ${ a * b }`;
// 等同于
tag(['Hello ', ' world ', ''], 15, 50);

二、數(shù)值擴(kuò)展

  1. Number.isFinite()、Number.isNaN()。ES6 在Number對(duì)象上,新提供了Number.isFinite()Number.isNaN()兩個(gè)方法。
  • Number.isFinite()用來檢查一個(gè)數(shù)值是否為有限的(finite)。
Number.isFinite(15); // true
Number.isFinite(0.8); // true
Number.isFinite(NaN); // false
Number.isFinite(Infinity); // false
Number.isFinite(-Infinity); // false
Number.isFinite('foo'); // false
Number.isFinite('15'); // false
Number.isFinite(true); // false
  • Number.isNaN()用來檢查一個(gè)值是否為NaN。和全局函數(shù) isNaN() 相比,該方法不會(huì)強(qiáng)制將參數(shù)轉(zhuǎn)換成數(shù)字,只有在參數(shù)是真正的數(shù)字類型,且值為 NaN 的時(shí)候才會(huì)返回 true。
Number.isNaN(NaN);        // true
Number.isNaN(Number.NaN); // true
Number.isNaN(0 / 0)       // true

// 下面這幾個(gè)如果使用全局的 isNaN() 時(shí),會(huì)返回 true。
Number.isNaN("NaN");      // false,字符串 "NaN" 不會(huì)被隱式轉(zhuǎn)換成數(shù)字 NaN。
Number.isNaN(undefined);  // false
Number.isNaN({});         // false
Number.isNaN("blabla");   // false

// 下面的都返回 false
Number.isNaN(true);
Number.isNaN(null);
Number.isNaN(37);
Number.isNaN("37");
Number.isNaN("37.37");
Number.isNaN("");
Number.isNaN(" ");
  1. Number.parseInt()、Number.parseFloat()。ES6 將全局方法parseInt()parseFloat(),移植到Number對(duì)象上面,行為完全保持不變。這樣做的目的,是逐步減少全局性方法,使得語(yǔ)言逐步模塊化。
// ES5的寫法
parseInt('12.34') // 12
parseFloat('123.45#') // 123.45

// ES6的寫法
Number.parseInt('12.34') // 12
Number.parseFloat('123.45#') // 123.45

Number.parseInt === parseInt // true
Number.parseFloat === parseFloat // true
  1. Number.isInteger()。Number.isInteger()用來判斷一個(gè)值是否為整數(shù)。需要注意的是,在 JavaScript 內(nèi)部,整數(shù)和浮點(diǎn)數(shù)是同樣的儲(chǔ)存方法,所以 3 和 3.0 被視為同一個(gè)值。
Number.isInteger(25) // true
Number.isInteger(25.0) // true
Number.isInteger(25.1) // false
Number.isInteger("15") // false
Number.isInteger(true) // false
  1. Math對(duì)象的擴(kuò)展。
    ES6 在 Math 對(duì)象上新增了 17 個(gè)與數(shù)學(xué)相關(guān)的方法。所有這些方法都是靜態(tài)方法,只能在 Math 對(duì)象上調(diào)用。
  • Math.trunc方法用于去除一個(gè)數(shù)的小數(shù)部分,返回整數(shù)部分。對(duì)于非數(shù)值,Math.trunc內(nèi)部使用Number方法將其先轉(zhuǎn)為數(shù)值。對(duì)于空值和無法截取整數(shù)的值,返回NaN。
Math.trunc(4.1) // 4
Math.trunc(4.9) // 4
Math.trunc(-4.1) // -4
Math.trunc(-4.9) // -4
Math.trunc(-0.1234) // -0
  • Math.sign方法用來判斷一個(gè)數(shù)到底是正數(shù)、負(fù)數(shù)、還是零。對(duì)于非數(shù)值,會(huì)先將其轉(zhuǎn)換為數(shù)值。它返回五種值,參數(shù)為正數(shù),返回+1;參數(shù)為負(fù)數(shù),返回-1;參數(shù)為 0,返回0;參數(shù)為-0,返回-0;其他值,返回NaN。
Math.sign(-5) // -1
Math.sign(5) // +1
Math.sign(0) // +0
Math.sign(-0) // -0
Math.sign(NaN) // NaN

Math.sign('')  // 0
Math.sign(true)  // +1
Math.sign(false)  // 0
Math.sign(null)  // 0
Math.sign('9')  // +1
Math.sign('foo')  // NaN
Math.sign()  // NaN
Math.sign(undefined)  // NaN
  • Math.cbrt方法用于計(jì)算一個(gè)數(shù)的立方根。對(duì)于非數(shù)值,Math.cbrt方法內(nèi)部也是先使用Number方法將其轉(zhuǎn)為數(shù)值。
Math.cbrt(-1) // -1
Math.cbrt(0)  // 0
Math.cbrt(1)  // 1
Math.cbrt(2)  // 1.2599210498948734
  • Math.hypot方法返回所有參數(shù)的平方和的平方根。
Math.hypot(3, 4);        // 5
Math.hypot(3, 4, 5);     // 7.0710678118654755
Math.hypot();            // 0
Math.hypot(NaN);         // NaN
Math.hypot(3, 4, 'foo'); // NaN
Math.hypot(3, 4, '5');   // 7.0710678118654755
Math.hypot(-3);          // 3
  1. 指數(shù)運(yùn)算符。ES2016 新增了一個(gè)指數(shù)運(yùn)算符(**)。指數(shù)運(yùn)算符可以與等號(hào)結(jié)合,形成一個(gè)新的賦值運(yùn)算符(**=)。
2 ** 2 // 4
2 ** 3 // 8

let a = 1.5;
a **= 2;
// 等同于 a = a * a;

let b = 4;
b **= 3;
// 等同于 b = b * b * b;

三、函數(shù)擴(kuò)展

  1. 函數(shù)參數(shù)的默認(rèn)值。
  • 基本用法。
function log(x, y = 'World') {
  console.log(x, y);
}

log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello
  • 與解構(gòu)賦值默認(rèn)值結(jié)合使用。
function foo({x, y = 5}) {
  console.log(x, y);
}

foo({}) // undefined 5
foo({x: 1}) // 1 5
foo({x: 1, y: 2}) // 1 2
foo() // TypeError: Cannot read property 'x' of undefined
  • 參數(shù)默認(rèn)值的位置。通常情況下,定義了默認(rèn)值的參數(shù),應(yīng)該是函數(shù)的尾參數(shù)。因?yàn)檫@樣比較容易看出來,到底省略了哪些參數(shù)。如果非尾部的參數(shù)設(shè)置默認(rèn)值,實(shí)際上這個(gè)參數(shù)是沒法省略的。
// 例一
function f(x = 1, y) {
  return [x, y];
}

f() // [1, undefined]
f(2) // [2, undefined])
f(, 1) // 報(bào)錯(cuò)
f(undefined, 1) // [1, 1]

// 例二
function f(x, y = 5, z) {
  return [x, y, z];
}

f() // [undefined, 5, undefined]
f(1) // [1, 5, undefined]
f(1, ,2) // 報(bào)錯(cuò)
f(1, undefined, 2) // [1, 5, 2]
  • 函數(shù)的length屬性。指定了默認(rèn)值以后,函數(shù)的length屬性,將返回沒有指定默認(rèn)值的參數(shù)個(gè)數(shù)。也就是說,指定了默認(rèn)值后,length屬性將失真。fn.length 返回形參個(gè)數(shù),arguments.length 返回實(shí)參個(gè)數(shù)。
(function (a) {}).length // 1
(function (a = 5) {}).length // 0
(function (a, b, c = 5) {}).length // 2
  • 作用域。一旦設(shè)置了參數(shù)的默認(rèn)值,函數(shù)進(jìn)行聲明初始化時(shí),參數(shù)會(huì)形成一個(gè)單獨(dú)的作用域。等到初始化結(jié)束,這個(gè)作用域就會(huì)消失。這種語(yǔ)法行為,在不設(shè)置參數(shù)默認(rèn)值時(shí),是不會(huì)出現(xiàn)的。
var x = 1;

function f(x, y = x) {
  console.log(y);
}

f(2) // 2

上面代碼中,參數(shù)y的默認(rèn)值等于變量x。調(diào)用函數(shù)f時(shí),參數(shù)形成一個(gè)單獨(dú)的作用域。在這個(gè)作用域里面,默認(rèn)值變量x指向第一個(gè)參數(shù)x,而不是全局變量x,所以輸出是2

let x = 1;

function f(y = x) {
  let x = 2;
  console.log(y);
}

f() // 1

上面代碼中,函數(shù)f調(diào)用時(shí),參數(shù)y = x形成一個(gè)單獨(dú)的作用域。這個(gè)作用域里面,變量x本身沒有定義,所以指向外層的全局變量x。函數(shù)調(diào)用時(shí),函數(shù)體內(nèi)部的局部變量x影響不到默認(rèn)值變量x。

var x = 1;

function foo(x = x) {
  // ...
}

foo() // ReferenceError: x is not defined

上面代碼中,參數(shù)x = x形成一個(gè)單獨(dú)作用域。實(shí)際執(zhí)行的是let x = x,由于暫時(shí)性死區(qū)的原因,這行代碼會(huì)報(bào)錯(cuò)”x 未定義“。

var x = 1;
function foo(x, y = function() { x = 2; }) {
  var x = 3;
  y();
  console.log(x);
}

foo()//3
console.log(x); //1

如果將var x = 3var去除,函數(shù)foo的內(nèi)部變量x就指向第一個(gè)參數(shù)x,與匿名函數(shù)內(nèi)部的x是一致的,所以最后輸出的就是2,而外層的全局變量x依然不受影響。

var x = 1;
function foo(x, y = function() { x = 2; }) {
  x = 3;
  y();
  console.log(x);
}

foo() // 2
x // 1
  1. rest參數(shù)。
    ES6 引入 rest 參數(shù)(形式為...變量名),用于獲取函數(shù)的多余參數(shù),這樣就不需要使用arguments對(duì)象了。rest 參數(shù)搭配的變量是一個(gè)數(shù)組,該變量將多余的參數(shù)放入數(shù)組中。
function add(...values) {
  let sum = 0;

  for (var val of values) {
    sum += val;
  }

  return sum;
}

add(2, 5, 3) // 10

arguments對(duì)象不是數(shù)組,而是一個(gè)類似數(shù)組的對(duì)象。所以為了使用數(shù)組的方法,必須使用Array.prototype.slice.call先將其轉(zhuǎn)為數(shù)組。rest 參數(shù)就不存在這個(gè)問題,它就是一個(gè)真正的數(shù)組,數(shù)組特有的方法都可以使用。下面是一個(gè)利用 rest 參數(shù)改寫數(shù)組push方法的例子。

function push(array, ...items) {
  items.forEach(function(item) {
    array.push(item);
    console.log(item);
  });
}

var a = [];
push(a, 1, 2, 3)

注意,rest 參數(shù)之后不能再有其他參數(shù)(即只能是最后一個(gè)參數(shù)),否則會(huì)報(bào)錯(cuò)。

// 報(bào)錯(cuò)
function f(a, ...b, c) {
  // ...
}

函數(shù)的length屬性,不包括 rest 參數(shù)。

(function(a) {}).length  // 1
(function(...a) {}).length  // 0
(function(a, ...b) {}).length  // 1
  1. 嚴(yán)格模式。
    ES2016規(guī)定只要函數(shù)參數(shù)使用了默認(rèn)值、解構(gòu)賦值、或者擴(kuò)展運(yùn)算符,那么函數(shù)內(nèi)部就不能顯式設(shè)定為嚴(yán)格模式,否則會(huì)報(bào)錯(cuò)。
  2. name屬性,返回函數(shù)名。
function foo() {}
foo.name // "foo"

var f = function () {};
f.name // "f"

var fn1 = function fn2(){};
fn1.name // "fn2"
  1. 箭頭函數(shù)
  • 基本用法,ES6 允許使用“箭頭”(=>)定義函數(shù)。
var f = v => v;
//上面的箭頭函數(shù)等同于
var f = function(v) {
  return v;
};

如果箭頭函數(shù)不需要參數(shù)或需要多個(gè)參數(shù),就使用一個(gè)圓括號(hào)代表參數(shù)部分。

var f = () => 5;
// 等同于
var f = function () { return 5 };

var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2) {
  return num1 + num2;
};

如果箭頭函數(shù)的代碼塊部分多于一條語(yǔ)句,就要使用大括號(hào)將它們括起來,并且使用return語(yǔ)句返回。

var sum = (num1, num2) => { return num1 + num2; }

由于大括號(hào)被解釋為代碼塊,所以如果箭頭函數(shù)直接返回一個(gè)對(duì)象,必須在對(duì)象外面加上括號(hào),否則會(huì)報(bào)錯(cuò)。

// 報(bào)錯(cuò)
let getTempItem = id => { id: id, name: "Temp" };

// 不報(bào)錯(cuò)
let getTempItem = id => ({ id: id, name: "Temp" });
  • 函數(shù)體內(nèi)的this對(duì)象,就是定義時(shí)所在的對(duì)象,而不是使用時(shí)所在的對(duì)象。
  • 不可以當(dāng)作構(gòu)造函數(shù),也就是說,不可以使用new命令,否則會(huì)拋出一個(gè)錯(cuò)誤。
  • 不可以使用arguments對(duì)象,該對(duì)象在函數(shù)體內(nèi)不存在。如果要用,可以用 rest 參數(shù)代替。
  • 不可以使用yield命令,因此箭頭函數(shù)不能用作 Generator 函數(shù)。
  • this指向的固定化,并不是因?yàn)榧^函數(shù)內(nèi)部有綁定this的機(jī)制,實(shí)際原因是箭頭函數(shù)根本沒有自己的this,導(dǎo)致內(nèi)部的this就是外層代碼塊的this。正是因?yàn)樗鼪]有this,所以也就不能用作構(gòu)造函數(shù)。
  • 由于箭頭函數(shù)沒有自己的this,所以當(dāng)然也就不能用call()apply()、bind()這些方法去改變this的指向。
// ES6
function foo() {
  setTimeout(() => {
    console.log('id:', this.id);
  }, 100);
}

// ES5
function foo() {
  var _this = this;

  setTimeout(function () {
    console.log('id:', _this.id);
  }, 100);
}
//轉(zhuǎn)換后的 ES5 版本清楚地說明了,箭頭函數(shù)里面根本沒有自己的this,而是引用外層的this。
  1. 函數(shù)參數(shù)的尾逗號(hào)。ES2017允許函數(shù)的最后一個(gè)參數(shù)有尾逗號(hào)。這樣的規(guī)定也使得,函數(shù)參數(shù)與數(shù)組和對(duì)象的尾逗號(hào)規(guī)則,保持一致了。
function clownsEverywhere(
  param1,
  param2,
) { /* ... */ }

clownsEverywhere(
  'foo',
  'bar',
);

四、數(shù)組的擴(kuò)展

  1. 擴(kuò)展運(yùn)算符是三個(gè)點(diǎn)(...)。它好比rest參數(shù)的逆運(yùn)算,將一個(gè)數(shù)組轉(zhuǎn)為用逗號(hào)分隔的參數(shù)序列。該運(yùn)算符將一個(gè)數(shù)組變?yōu)閰?shù)序列。
console.log(...[1, 2, 3])
// 1 2 3

console.log(1, ...[2, 3, 4], 5)
// 1 2 3 4 5

[...document.querySelectorAll('div')]
// [<div>, <div>, <div>]

擴(kuò)展運(yùn)算符后面還可以放置表達(dá)式。

const arr = [
  ...(x > 0 ? ['a'] : []),
  'b',
];

如果擴(kuò)展運(yùn)算符后面是一個(gè)空數(shù)組,則不產(chǎn)生任何效果。

[...[], 1]
// [1]

由于擴(kuò)展運(yùn)算符可以展開數(shù)組,所以不再需要apply方法,將數(shù)組轉(zhuǎn)為函數(shù)的參數(shù)了。

// ES5 的寫法
function f(x, y, z) {
  // ...
}
var args = [0, 1, 2];
f.apply(null, args);

// ES6的寫法
function f(x, y, z) {
  // ...
}
let args = [0, 1, 2];
f(...args);

取一個(gè)數(shù)組中的最大值。

//es5
Math.max.apply(null,[1,5,2,8]) // 8
//es6
Math.max(...[1,5,2,8])//8
//上面兩種方法等同于
Math.max(1,5,2,8)

擴(kuò)展運(yùn)算符可以用于復(fù)制數(shù)組。

//es5
const a1 = [1, 2];
const a2 = a1.concat();
a2[0] = 2;
a1 // [1, 2]
a2 // [2, 2]

//es6
const a1 = [1, 2];
// 寫法一
const a2 = [...a1];
// 寫法二
const [...a2] = a1;

擴(kuò)展運(yùn)算符用于合并數(shù)組。

// ES5
[1, 2].concat(more)
// ES6
[1, 2, ...more]

var arr1 = ['a', 'b'];
var arr2 = ['c'];
var arr3 = ['d', 'e'];

// ES5的合并數(shù)組
arr1.concat(arr2, arr3);
// [ 'a', 'b', 'c', 'd', 'e' ]

// ES6的合并數(shù)組
[...arr1, ...arr2, ...arr3]
// [ 'a', 'b', 'c', 'd', 'e' ]

擴(kuò)展運(yùn)算符可以與解構(gòu)賦值結(jié)合起來,用于生成數(shù)組。

// ES5
a = list[0], rest = list.slice(1)
// ES6
[a, ...rest] = list
const [first, ...rest] = [1, 2, 3, 4, 5];
first // 1
rest  // [2, 3, 4, 5]

const [first, ...rest] = [];
first // undefined
rest  // []

const [first, ...rest] = ["foo"];
first  // "foo"
rest   // []
const [...butLast, last] = [1, 2, 3, 4, 5];
// 報(bào)錯(cuò)

const [first, ...middle, last] = [1, 2, 3, 4, 5];
// 報(bào)錯(cuò)

擴(kuò)展運(yùn)算符還可以將字符串轉(zhuǎn)為真正的數(shù)組。

[...'hello']
// [ "h", "e", "l", "l", "o" ]

擴(kuò)展運(yùn)算符實(shí)現(xiàn)了 Iterator 接口的對(duì)象

let nodeList = document.querySelectorAll('div');
let array = [...nodeList];
  1. Array.from()方法用于將兩類對(duì)象轉(zhuǎn)為真正的數(shù)組。
  • 第一個(gè)參數(shù):一個(gè)類數(shù)組對(duì)象,用于轉(zhuǎn)為真正的數(shù)組
  • 第二個(gè)參數(shù):類似于數(shù)組的map方法,用來對(duì)每個(gè)元素進(jìn)行處理,將處理后的值放入返回的數(shù)組。
  • 第三個(gè)參數(shù):如果map函數(shù)里面用到了this關(guān)鍵字,還可以傳入Array.from的第三個(gè)參數(shù),用來綁定this
// NodeList對(duì)象
let ps = document.querySelectorAll('p');
Array.from(ps).forEach(function (p) {
  console.log(p);
});

// arguments對(duì)象
function foo() {
  var args = Array.from(arguments);
  // ...
}
  1. Array.of()方法用于將一組值,轉(zhuǎn)換為數(shù)組。這個(gè)方法的主要目的,是彌補(bǔ)數(shù)組構(gòu)造函數(shù)Array()的不足。因?yàn)閰?shù)個(gè)數(shù)的不同,會(huì)導(dǎo)致Array()的行為有差異。
//Array
Array() // []
Array(3) // [, , ,]
Array(3, 11, 8) // [3, 11, 8]

Array.of(3, 11, 8) // [3,11,8]
Array.of(3) // [3]
Array.of(3).length // 1
  1. 數(shù)組實(shí)例的copyWithin方法,在當(dāng)前數(shù)組內(nèi)部,將指定位置的成員復(fù)制到其他位置(會(huì)覆蓋原有成員),然后返回當(dāng)前數(shù)組。也就是說,使用這個(gè)方法,會(huì)修改當(dāng)前數(shù)組。
    它接受三個(gè)參數(shù)。
  • target(必需):從該位置開始替換數(shù)據(jù)。
  • start(可選):從該位置開始讀取數(shù)據(jù),默認(rèn)為 0。如果為負(fù)值,表示倒數(shù)。
  • end(可選):到該位置前停止讀取數(shù)據(jù),默認(rèn)等于數(shù)組長(zhǎng)度。如果為負(fù)值,表示倒數(shù)。
    這三個(gè)參數(shù)都應(yīng)該是數(shù)值,如果不是,會(huì)自動(dòng)轉(zhuǎn)為數(shù)值。
[1, 2, 3, 4, 5].copyWithin(0, 3)
// [4, 5, 3, 4, 5]
  1. 數(shù)組實(shí)例的find()findIndex()。這兩個(gè)方法都可以接受第二個(gè)參數(shù),用來綁定回調(diào)函數(shù)的this對(duì)象。
  • 數(shù)組實(shí)例的find方法,用于找出第一個(gè)符合條件的數(shù)組成員。它的參數(shù)是一個(gè)回調(diào)函數(shù),所有數(shù)組成員依次執(zhí)行該回調(diào)函數(shù),直到找出第一個(gè)返回值為true的成員,然后返回該成員。如果沒有符合條件的成員,則返回undefined。
[1, 4, -5, 10].find((n) => n < 0)
// -5
[1, 5, 10, 15].find(function(value, index, arr) {
  return value > 9;
}) // 10
//find方法的回調(diào)函數(shù)可以接受三個(gè)參數(shù),依次為當(dāng)前的值、當(dāng)前的位置和原數(shù)組。
  • findIndex方法的用法與find方法非常類似,返回第一個(gè)符合條件的數(shù)組成員的位置,如果所有成員都不符合條件,則返回-1。
[1, 5, 10, 15].findIndex(function(value, index, arr) {
  return value > 9;
}) // 2
  1. 數(shù)組實(shí)例的fill(),fill方法使用給定值,填充一個(gè)數(shù)組。fill方法用于空數(shù)組的初始化非常方便。數(shù)組中已有的元素,會(huì)被全部抹去。fill方法還可以接受第二個(gè)和第三個(gè)參數(shù),用于指定填充的起始位置和結(jié)束位置。
['a', 'b', 'c'].fill(7)
// [7, 7, 7]

new Array(3).fill(7)
// [7, 7, 7]
  1. for...of是es6引入的作為遍歷所有數(shù)據(jù)結(jié)構(gòu)的統(tǒng)一的方法。一個(gè)數(shù)據(jù)結(jié)構(gòu)只要部署了Symbol.iterator屬性,就被視為具有 iterator 接口,就可以用for...of循環(huán)遍歷它的成員。也就是說,for...of循環(huán)內(nèi)部調(diào)用的是數(shù)據(jù)結(jié)構(gòu)的Symbol.iterator方法。
  2. 數(shù)組實(shí)例的 entries(),keys()values()用于遍歷數(shù)組,它們都返回一個(gè)遍歷器對(duì)象,可以用for...of循環(huán)進(jìn)行遍歷,唯一的區(qū)別是keys()是對(duì)鍵名的遍歷、values()是對(duì)鍵值的遍歷,entries()是對(duì)鍵值對(duì)的遍歷。
for (let index of ['a', 'b'].keys()) {
  console.log(index);
}
// 0
// 1

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

for (let [index, elem] of ['a', 'b'].entries()) {
  console.log(index, elem);
}
// 0 "a"
// 1 "b"
  1. 數(shù)組實(shí)例的includes()方法返回一個(gè)布爾值,表示某個(gè)數(shù)組是否包含給定的值,與字符串的includes方法類似。
[1, 2, 3].includes(2)     // true
[1, 2, 3].includes(4)     // false
[1, 2, NaN].includes(NaN) // true

該方法的第二個(gè)參數(shù)表示搜索的起始位置,默認(rèn)為0。如果第二個(gè)參數(shù)為負(fù)數(shù),則表示倒數(shù)的位置,如果這時(shí)它大于數(shù)組長(zhǎng)度(比如第二個(gè)參數(shù)為-4,但數(shù)組長(zhǎng)度為3),則會(huì)重置為從0開始。
沒有該方法之前,我們通常使用數(shù)組的indexOf方法,檢查是否包含某個(gè)值。indexOf方法有兩個(gè)缺點(diǎn),一是不夠語(yǔ)義化,它的含義是找到參數(shù)值的第一個(gè)出現(xiàn)位置,所以要去比較是否不等于-1,表達(dá)起來不夠直觀。二是,它內(nèi)部使用嚴(yán)格相等運(yùn)算符(===)進(jìn)行判斷,這會(huì)導(dǎo)致對(duì)NaN的誤判。

  1. 數(shù)組的空位指,數(shù)組的某一個(gè)位置沒有任何值。
    空位不是undefined,一個(gè)位置的值等于undefined,依然是有值的??瘴皇菦]有任何值,in運(yùn)算符可以說明這一點(diǎn)。
0 in [undefined, undefined, undefined] // true
0 in [, , ,] // false

es5對(duì)空位的處理很不一致,大多數(shù)情況下會(huì)忽略空位。

  • forEach(), filter(), reduce(), every()some()都會(huì)跳過空位。
  • map()會(huì)跳過空位,但會(huì)保留這個(gè)值
  • join()toString()會(huì)將空位視為undefined,而undefinednull會(huì)被處理成空字符串。
    es6明確將空位轉(zhuǎn)為undefined
  • Array.from方法會(huì)將數(shù)組的空位,轉(zhuǎn)為undefined,也就是說,這個(gè)方法不會(huì)忽略空位。
Array.from(['a',,'b'])
// [ "a", undefined, "b" ]
  • 擴(kuò)展運(yùn)算符(...)也會(huì)將空位轉(zhuǎn)為undefined。
[...['a',,'b']]
// [ "a", undefined, "b" ]
  • copyWithin()會(huì)連空位一起拷貝。
[,'a','b',,].copyWithin(2,0) // [,"a",,"a"]
  • fill()會(huì)將空位視為正常的數(shù)組位置。
new Array(3).fill('a') // ["a","a","a"]
  • for...of循環(huán)也會(huì)遍歷空位。
let arr = [, ,];
for (let i of arr) {
  console.log(1);
}
// 1
// 1

上面代碼中,數(shù)組arr有兩個(gè)空位,for...of并沒有忽略它們。如果改成map方法遍歷,空位是會(huì)跳過的。
entries()、keys()、values()find()findIndex()會(huì)將空位處理成undefined。

// entries()
[...[,'a'].entries()] // [[0,undefined], [1,"a"]]

// keys()
[...[,'a'].keys()] // [0,1]

// values()
[...[,'a'].values()] // [undefined,"a"]

// find()
[,'a'].find(x => true) // undefined

// findIndex()
[,'a'].findIndex(x => true) // 0

由于空位的處理規(guī)則非常不統(tǒng)一,所以建議避免出現(xiàn)空位。

五、對(duì)象的擴(kuò)展

  1. 屬性的簡(jiǎn)潔表示法,ES6 允許直接寫入變量和函數(shù),作為對(duì)象的屬性和方法。這樣的書寫更加簡(jiǎn)潔。
//es6寫法
const foo = 'bar';
const baz = {foo};
baz // {foo: "bar"}

// 等同于es5寫法
const baz = {foo: foo};

//es6寫法
const o = {
  method() {
    return "Hello!";
  }
};

// 等同于es5寫法
const o = {
  method: function() {
    return "Hello!";
  }
};
  1. 屬性名表達(dá)式
    JavaScript 定義對(duì)象的屬性,有兩種方法。
// 方法一
obj.foo = true;

// 方法二
obj['a' + 'bc'] = 123;

但是,如果使用字面量方式定義對(duì)象(使用大括號(hào)),在 ES5 中只能使用方法一(標(biāo)識(shí)符)定義屬性。

var obj = {
  foo: true,
  abc: 123
};

ES6 允許字面量定義對(duì)象時(shí),用方法二(表達(dá)式)作為對(duì)象的屬性名,即把表達(dá)式放在方括號(hào)內(nèi)。

let propKey = 'foo';

let obj = {
  [propKey]: true,
  ['a' + 'bc']: 123
};

表達(dá)式還可以用于定義方法名。

let obj = {
  ['h' + 'ello']() {
    return 'hi';
  }
};

obj.hello() // hi

注意,屬性名表達(dá)式與簡(jiǎn)潔表示法,不能同時(shí)使用,會(huì)報(bào)錯(cuò)。

// 報(bào)錯(cuò)
const foo = 'bar';
const bar = 'abc';
const baz = { [foo] };

// 正確
const foo = 'bar';
const baz = { [foo]: 'abc'};
  1. Object.is()。ES5 比較兩個(gè)值是否相等,只有兩個(gè)運(yùn)算符:相等運(yùn)算符(==)和嚴(yán)格相等運(yùn)算符(===)。它們都有缺點(diǎn),前者會(huì)自動(dòng)轉(zhuǎn)換數(shù)據(jù)類型,后者的NaN不等于自身,以及+0等于-0。JavaScript 缺乏一種運(yùn)算,在所有環(huán)境中,只要兩個(gè)值是一樣的,它們就應(yīng)該相等。
    ES6 提出同值相等算法,用來解決這個(gè)問題。Object.is就是部署這個(gè)算法的新方法。它用來比較兩個(gè)值是否嚴(yán)格相等,與嚴(yán)格比較運(yùn)算符(===)的行為基本一致。
Object.is('foo', 'foo')
// true
Object.is({}, {})
// false

不同之處只有兩個(gè):一是+0不等于-0,二是NaN等于自身。

+0 === -0 //true
NaN === NaN // false

Object.is(+0, -0) // false
Object.is(NaN, NaN) // true
  1. Object.assign()。Object.assign方法用于對(duì)象的合并,將源對(duì)象(source)的所有可枚舉屬性,復(fù)制到目標(biāo)對(duì)象(target)。
const target = { a: 1 };

const source1 = { b: 2 };
const source2 = { c: 3 };

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

如果只有一個(gè)參數(shù),Object.assign會(huì)直接返回該參數(shù)。

const obj = {a: 1};
Object.assign(obj) === obj // true

由于undefinednull無法轉(zhuǎn)成對(duì)象,所以如果它們作為參數(shù),就會(huì)報(bào)錯(cuò)。

Object.assign(undefined) // 報(bào)錯(cuò)
Object.assign(null) // 報(bào)錯(cuò)

注意:Object.assign可以用來處理數(shù)組,但是會(huì)把數(shù)組視為對(duì)象。

Object.assign([1, 2, 3], [4, 5])
// [4, 5, 3]
//把數(shù)組視為屬性名為 0、1、2 的對(duì)象,因此源數(shù)組的 0 號(hào)屬性4覆蓋了目標(biāo)數(shù)組的 0 號(hào)屬性1。
  1. Object.keys()。ES5 引入了Object.keys方法,返回一個(gè)數(shù)組,成員是參數(shù)對(duì)象自身的(不含繼承的)所有可遍歷(enumerable)屬性的鍵名。
var obj = { foo: 'bar', baz: 42 };
Object.keys(obj)
// ["foo", "baz"]

ES2017 引入了跟Object.keys配套的Object.valuesObject.entries,作為遍歷一個(gè)對(duì)象的補(bǔ)充手段,供for...of循環(huán)使用。

let {keys, values, entries} = Object;
let obj = { a: 1, b: 2, c: 3 };

for (let key of keys(obj)) {
  console.log(key); // 'a', 'b', 'c'
}

for (let value of values(obj)) {
  console.log(value); // 1, 2, 3
}

for (let [key, value] of entries(obj)) {
  console.log([key, value]); // ['a', 1], ['b', 2], ['c', 3]
}
  1. Object.values()Object.values方法返回一個(gè)數(shù)組,成員是參數(shù)對(duì)象自身的(不含繼承的)所有可遍歷(enumerable)屬性的鍵值。
const obj = { foo: 'bar', baz: 42 };
Object.values(obj)
// ["bar", 42]

返回?cái)?shù)組的成員順序,下面的代碼中,屬性名為數(shù)值的屬性,是按照數(shù)值大小,從小到大遍歷的,因此返回的順序是b、ca。

const obj = { 100: 'a', 2: 'b', 7: 'c' };
Object.values(obj)
// ["b", "c", "a"]
  1. Object.entries()。Object.entries方法返回一個(gè)數(shù)組,成員是參數(shù)對(duì)象自身的(不含繼承的)所有可遍歷(enumerable)屬性的鍵值對(duì)數(shù)組。
const obj = { foo: 'bar', baz: 42 };
Object.entries(obj)
// [ ["foo", "bar"], ["baz", 42] ]
  1. 對(duì)象的擴(kuò)展運(yùn)算符。
  • 解構(gòu)賦值。
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
x // 1
y // 2
z // { a: 3, b: 4 }

由于解構(gòu)賦值要求等號(hào)右邊是一個(gè)對(duì)象,所以如果等號(hào)右邊是undefinednull,就會(huì)報(bào)錯(cuò),因?yàn)樗鼈儫o法轉(zhuǎn)為對(duì)象。

let { x, y, ...z } = null; // 運(yùn)行時(shí)錯(cuò)誤
let { x, y, ...z } = undefined; // 運(yùn)行時(shí)錯(cuò)誤

解構(gòu)賦值必須是最后一個(gè)參數(shù),否則會(huì)報(bào)錯(cuò)。

let { ...x, y, z } = obj; // 句法錯(cuò)誤
let { x, ...y, ...z } = obj; // 句法錯(cuò)誤

注意,解構(gòu)賦值的拷貝是淺拷貝,即如果一個(gè)鍵的值是復(fù)合類型的值(數(shù)組、對(duì)象、函數(shù))、那么解構(gòu)賦值拷貝的是這個(gè)值的引用,而不是這個(gè)值的副本。

let obj = { a: { b: 1 } };
let { ...x } = obj;
obj.a.b = 2; 
console.log(x.a.b); // 2
  • 擴(kuò)展運(yùn)算符
    擴(kuò)展運(yùn)算符(...)用于取出參數(shù)對(duì)象的所有可遍歷屬性,拷貝到當(dāng)前對(duì)象之中。
let z = { a: 3, b: 4 };
let n = { ...z };
n // { a: 3, b: 4 }

這等同于使用Object.assign方法。

let aClone = { ...a };
// 等同于
let aClone = Object.assign({}, a);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 第5章 引用類型(返回首頁(yè)) 本章內(nèi)容 使用對(duì)象 創(chuàng)建并操作數(shù)組 理解基本的JavaScript類型 使用基本類型...
    大學(xué)一百閱讀 3,674評(píng)論 0 4
  • ??引用類型的值(對(duì)象)是引用類型的一個(gè)實(shí)例。 ??在 ECMAscript 中,引用類型是一種數(shù)據(jù)結(jié)構(gòu),用于將數(shù)...
    霜天曉閱讀 1,218評(píng)論 0 1
  • 三,字符串?dāng)U展 3.1 Unicode表示法 ES6 做出了改進(jìn),只要將碼點(diǎn)放入大括號(hào),就能正確解讀該字符。有了這...
    eastbaby閱讀 1,667評(píng)論 0 8
  • 數(shù)值 判斷NaN更可靠的方法是,利用NaN為唯一不等于自身的值的這個(gè)特點(diǎn),進(jìn)行判斷。 isFinite方法返回一個(gè)...
    guyigg閱讀 1,262評(píng)論 0 2
  • 躺在床上 靜下心來…… 反省自己工作中的點(diǎn)點(diǎn)滴滴,回想自己是不是說話有些緊張,言行是不是有些無意...
    天開文運(yùn)閱讀 374評(píng)論 0 1

友情鏈接更多精彩內(nèi)容