溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

es5和es6指的是什么

發(fā)布時間:2022-11-22 09:20:06 來源:億速云 閱讀:275 作者:iii 欄目:開發(fā)技術(shù)

本文小編為大家詳細(xì)介紹“es5和es6指的是什么”,內(nèi)容詳細(xì),步驟清晰,細(xì)節(jié)處理妥當(dāng),希望這篇“es5和es6指的是什么”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學(xué)習(xí)新知識吧。

es5全稱“ECMAScript 5”,是ECMAScript標(biāo)準(zhǔn)的第5版,它通過對現(xiàn)有JavaScript方法添加語句和原生ECMAScript對象做合并實現(xiàn)標(biāo)準(zhǔn)化;ES5還引入了一個語法的嚴(yán)格變種,被稱為”嚴(yán)格模式”。es6全稱ECMAScript6,是于2015年6月正式發(fā)布的JS語言的標(biāo)準(zhǔn);它的目標(biāo)是使得JS語言可以用來編寫復(fù)雜的大型應(yīng)用程序,成為企業(yè)級開發(fā)語言。

es全稱“ECMAScript”

ECMAScript是一種由Ecma國際(前身為歐洲計算機(jī)制造商協(xié)會,European Computer Manufacturers Association)通過ECMA-262標(biāo)準(zhǔn)化的腳本程序設(shè)計語言。這種語言在萬維網(wǎng)上應(yīng)用廣泛,它往往被稱為JavaScript或JScript,所以它可以理解為是JavaScript的一個標(biāo)準(zhǔn),但實際上后兩者是ECMA-262標(biāo)準(zhǔn)的實現(xiàn)和擴(kuò)展。

ECMAScript是一種可以在宿主環(huán)境中執(zhí)行計算并能操作可計算對象的基于對象的程序設(shè)計語言。ECMAScript最先被設(shè)計成一種Web腳本語言,用來支持Web頁面的動態(tài)表現(xiàn)以及為基于Web的客戶機(jī)—服務(wù)器架構(gòu)提供服務(wù)器端的計算能力。但作為一種腳本語言, ECMAScript具備同其他腳本語言一樣的性質(zhì),即“用來操縱、定制一個已存在系統(tǒng)所提供的功能,以及對其進(jìn)行自動化”。

es5是什么

es5全稱“ECMAScript 5”,也被稱為ECMAScript2009,是ECMAScript標(biāo)準(zhǔn)的第5版,與HTML5規(guī)范進(jìn)程本質(zhì)類似,ES5通過對現(xiàn)有JavaScript方法添加語句和原生ECMAScript對象做合并實現(xiàn)標(biāo)準(zhǔn)化。ES5還引入了一個語法的嚴(yán)格變種,被稱為”嚴(yán)格模式(strict mode)”。

es5的新功能:

這些是 2009 年發(fā)布的新功能:

  • The "use strict" Directive

  • String.trim()

  • Array.isArray()

  • Array.forEach()

  • Array.map()

  • Array.filter()

  • Array.reduce()

  • Array.reduceRight()

  • Array.every()

  • Array.some()

  • Array.indexOf()

  • Array.lastIndexOf()

  • JSON.parse()

  • JSON.stringify()

  • Date.now()

  • Property Getters and Setters

  • New Object Property Methods

ES5的嚴(yán)格模式 'use strict'

     給作者提供了選擇一個限制性更強(qiáng)語言變種的方式
        1. 消除不安全之處,保證安全運(yùn)行
        2. 提升編譯效率
        3. 未來發(fā)展趨勢
      規(guī)則:
        1)變量先定義在使用
        2)不允許變量重名
          var a=1;
          function a(){}
        3)不允許使用eval
        4)不允許delete
        4)不允許with語句
          var sMessage = "hello";
          with(sMessage) {alert(toUpperCase());}

es5是什么

es6全稱ECMAScript6(ECMAScript的第6個版本),是于2015年6月正式發(fā)布的JavaScript語言的標(biāo)準(zhǔn),正式名為ECMAScript 2015(ES2015)。它的目標(biāo)是使得JavaScript語言可以用來編寫復(fù)雜的大型應(yīng)用程序,成為企業(yè)級開發(fā)語言。

ES6是JavaScript語言的主要增強(qiáng),允許我們編寫程序。ES6適用于復(fù)雜的應(yīng)用程序。盡管ES5和ES6在本質(zhì)上有一些相似之處,但它們之間也有許多不同之處。

es5和es6的區(qū)別

ES5和ES6之間的比較列表如下:

比較項ES5ES6
定義ES5是ECMAScript(由ECMA International定義的商標(biāo)腳本語言規(guī)范)的第五版。ES6是ECMAScript(ECMA International定義的商標(biāo)腳本語言規(guī)范)的第六版。
發(fā)布它于2009年推出。它于2015年推出。
數(shù)據(jù)類型ES5支持原始數(shù)據(jù)類型,包括字符串,數(shù)字,布爾值,空值和未定義(undefined)。在ES6中,對JavaScript數(shù)據(jù)類型進(jìn)行了一些補(bǔ)充。 它引入了一種新的原始數(shù)據(jù)類型symbol以支持唯一值。
定義變量在ES5中,只能使用var關(guān)鍵字定義變量。在ES6中,有兩種定義letconst變量的新方法。
性能由于ES5早于ES6,因此某些功能不存在,因此其性能比ES6低。由于具有新功能和速記存儲實現(xiàn),因此ES6具有比ES5更高的性能。
支持許多社區(qū)都支持它。它也有很多社區(qū)支持,但是比ES5小。
對象操縱ES5比ES6耗時。由于具有解構(gòu)和速度運(yùn)算符,因此可以在ES6中更平穩(wěn)地處理對象操縱。
箭頭函數(shù)在ES5中,functionreturn關(guān)鍵字均用于定義函數(shù)。箭頭功能是ES6中引入的新功能,通過它不需要function關(guān)鍵字來定義函數(shù)。
循環(huán)在ES5中,使用了for循環(huán)來遍歷元素。ES6引入了for?of循環(huán)的概念,以對可迭代對象的值執(zhí)行迭代。

代碼轉(zhuǎn)換

到目前為止,還沒有完全支持ES6功能的瀏覽器。 但是,我們可以使用轉(zhuǎn)譯將ES6代碼轉(zhuǎn)換為ES5代碼。

有兩個主要的編譯器Babel和Traceur,用于在構(gòu)建過程中將ES6代碼轉(zhuǎn)換為ES5代碼。

擴(kuò)展運(yùn)算符(…)

它在ES6中引入,使合并數(shù)組和對象變得容易。

ES6常用特性:

一、let和const命令

1、let:

(1)基本用法

ES6 新增了let命令,用來聲明變量。類似于var,但是所聲明的變量,只在let命令所在的代碼塊內(nèi)有效。{

   let a = 10;
  var b = 1;
}
a // ReferenceError: a is not defined.
b // 1

(2)let在for循環(huán)中使用

var a = [];
for (var i = 0; i < 10; i++) {
 a[i] = function () {
   console.log(i);
 };
}
a[2](); // 10
a[6](); // 10

這個例子中,i 由 var 聲明,在全局范圍有效,a 的所有組員里面的 i 都是指向同一個 i,導(dǎo)致所有組員運(yùn)行輸出的都是最后一輪的 i 的值。

var a = [];
for (let i = 0; i < 10; i++) {
   a[i] = function () {
       console.log(i);
   }
}
a[2](); // 2
a[6](); // 6

這個例子中, i 由 let 聲明,當(dāng)前的 i 只在本輪循環(huán)有效,所有每次循環(huán)的 i 其實都是一個新的變量。

Tips: 每輪循環(huán)的 i 都是重新聲明的,JavaScript 引擎內(nèi)部會記住上一輪循環(huán)的值,初始化本輪的 i 時,就在上一輪循環(huán)的基礎(chǔ)上進(jìn)行計算。

(3)for循環(huán)的特別之處

在 for 循環(huán)中,設(shè)置循環(huán)變量的那部分是一個父作用域,而循環(huán)內(nèi)部是一個單獨(dú)的子作用域

for (let i = 0; i < 3; i++) {
   let i = 'abc';  // 和上一行for循環(huán)計數(shù)器的i不在同一作用域,所以可以聲明成功。類比下面要講的function(arg){let arg;}會報錯,就是作用域問題
   console.log(i);
}
// abc
// abc
// abc

(4)不能重復(fù)聲明

let 不允許在相同作用域內(nèi),重復(fù)聲明同一個變量。

function func() {
 var a = 10;
 let a = 1;
}
func(); //Identifier 'a' has already been declared

function func() {
 let a = 10;
 let a = 1;
}
func(); //Identifier 'a' has already been declared

function func(arg) {
 let arg;
}
func(); //Identifier 'arg' has already been declared

function func(arg) {
 {
   let arg;
 }
}
func(); //不報錯

(5)不存在變量提升

var 命令會發(fā)生“變量提升”現(xiàn)象,即變量可以在聲明之前使用,值為 undefined。 let 命令改變了語法行為,它所聲明的變量一定要在聲明后使用,否則會報錯。

console.log(foo); //undefined
var foo = 2;
console.log(bar); // ReferenceError: bar is not defined
let bar =  2;

(6)暫時性死區(qū)

ES6規(guī)定,如果區(qū)塊中存在 let 和 const 命令,這個區(qū)塊對這些命令聲明的變量,從一開始就形成了封閉作用域。凡是在聲明之前使用這些變量,就會報錯。這在語法上稱為 “暫時性死區(qū)”。

var tmp = 123;
if(true){
   tmp = 'abc'; // ReferenceError: tmp is not defined
   let tmp;
}

Tips:“暫時性死區(qū)”的本質(zhì)就是:只要一進(jìn)入當(dāng)前作用域,所要使用的變量就已經(jīng)存在了,但不可獲取(否則報錯),只有等到聲明的那一行代碼出現(xiàn),才可以獲取和使用。

2、const:

const命令的用法和let相似,最大不同點就是:const聲明一個只讀的常量。一旦聲明,常量的值就不能改變。

Tips:這個不可改變的是指針,所以對于const聲明的對象和數(shù)組還是可以改變的。如果真的想將對象凍結(jié),應(yīng)該使用Object.freeze方法。

3、let和const部分補(bǔ)充:

ES5 只有兩種聲明變量的方法:var命令和function命令。

ES6 除了添加let和const命令,另外兩種聲明變量的方法:import命令和class命令。所以,ES6 一共有 6 種聲明變量的方法。

頂層對象:在瀏覽器環(huán)境指的是window對象,在 Node 指的是global對象。ES5 之中,頂層對象的屬性與全局變量是等價的。

ES6為了保持兼容性,規(guī)定:a. var 命令和 function 命令聲明的全局變量,依舊是頂層對象的屬性。b. let,const,class 命令聲明的全局變量,不屬于頂層對象的屬性。

var a = 1;
window.a; // 1
let b = 2;
window.b; // undefined

二、變量的解構(gòu)賦值

ES6 允許按照一定模式,從數(shù)組和對象中提取值,對變量進(jìn)行賦值,這被稱為解構(gòu)(Destructuring)。

1、數(shù)組的解構(gòu)賦值

(1)基本用法

// 之前,為變量賦值,可以直接指定值
let a = 1;
let b = 2;
let c = 3;

// ES6中允許這樣
let [a, b, c] = [1, 2, 3];  // 可以從數(shù)組中提取值,按照對應(yīng)位置,對變量賦值。

本質(zhì)上,這種寫法屬于“模式匹配”,只要等號兩邊的模式相同,左邊的變量就會被賦予對應(yīng)的值。下面是一些使用嵌套數(shù)組進(jìn)行解構(gòu)的例子。

let [foo, [[bar], baz]] = [1, [[2], 3]];
foo // 1
bar // 2
baz // 3

let [ , , third] = ["foo", "bar", "baz"];
third // "baz"

let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]

let [x, y, ...z] = ['a'];
x // "a"
y // undefined  - 如果解構(gòu)不成功,變量的值就等于 undefined。
z // []

如果解構(gòu)不成功,變量的值就等于undefined。

上面一種情況是解構(gòu)不成功的;另一種情況是不完全解構(gòu),即等號左邊的模式,只匹配一部分的等號右邊的數(shù)組。這種情況下,解構(gòu)依然可以成功。

let [a, [b], d] = [1, [2, 3], 4];
a // 1
b // 2
d // 4

上面兩個例子,都屬于不完全解構(gòu),但是可以成功。

如果等號的右邊不是數(shù)組,那么將會報錯。

let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};

(2)默認(rèn)值

解構(gòu)賦值允許指定默認(rèn)值。例如:

let [foo = true] = [];
foo;// true

let [x, y = 'b'] = ['a'];
x;//'a'
y;//'b'

Tips:ES6 內(nèi)部使用嚴(yán)格相等運(yùn)算符(===)去判斷一個位置是否有值。所以,只有當(dāng)一個數(shù)組成員嚴(yán)格等于 undefined ,默認(rèn)值才會生效。例如:

let [x = 1] = [undefined];
x // 1

let [x = 1] = [null];
x // null - 默認(rèn)值就不會生效,因為null不嚴(yán)格等于undefined

登錄后復(fù)制

默認(rèn)值可以引用解構(gòu)賦值的其他變量,但該變量必須已經(jīng)聲明。

let [x = 1, y = x] = [1, 2];
x;//1
y;//2

let [x = y, y = 1] = [];// ReferenceError: y is not defined -- let的暫時性死區(qū)
let [x = y, y = 1] = [1, 2];
2、對象的解構(gòu)賦值

(1)基本用法

let { bar, foo } = { foo: "aaa", bar: "bbb" };
foo // "aaa"
bar // "bbb"

let { baz } = { foo: "aaa", bar: "bbb" };
baz // undefined

對象的解構(gòu)與數(shù)組的解構(gòu),一個重要的不同點在于: 數(shù)組元素是按次序排列的,變量的取值由它的位置決定;而對象的屬性沒有次序,變量名與屬性同名,才能取到正確的值。

如果沒有與變量名對應(yīng)的屬性名,導(dǎo)致取不到值,最后等于undefined。

如果變量名和屬性名不一樣,必須寫才下面這樣:

let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
baz // "aaa"

let obj = { first: 'hello', last: 'world' };
let { first: f, last: l } = obj;
f // 'hello'
l // 'world'

這實際上說明,對象的解構(gòu)賦值是下面形式的簡寫:

let { foo: foo, bar: bar } = { foo: "aaa", bar: "bbb" };

也就是說,對象的解構(gòu)賦值的內(nèi)部機(jī)制,是先找到同名屬性,然后再賦給對應(yīng)的變量。真正被賦值的是后者,而不是前者。

let { foo: baz } = { foo: "aaa", bar: "bbb" };
baz // "aaa"
foo // error: foo is not defined

上面代碼中,foo是匹配的模式,baz才是變量。真正被賦值的是變量baz,而不是模式foo。

(2)默認(rèn)值

對象的解構(gòu)也可以指定默認(rèn)值。默認(rèn)值生效的條件是對象的屬性值嚴(yán)格等于 undefined。

let {x, y = 5} = {x: 1};
x;// 1
y;// 5

let { message: msg = 'Something went wrong' } = {};
msg;//"Something went wrong"

Tips:如果要將一個已經(jīng)聲明的變量用于解構(gòu)賦值,需要注意:

let x;
{x} = {x:1};
//上面的代碼會報錯,因為JavaScript引擎會將 {x} 理解為一個代碼塊,從而發(fā)生語法錯誤。只有不將大括號寫在行首,避免JavaScript將其解釋為代碼塊,才能解決這個問題。

//正確的寫法,將需要解構(gòu)的部分用括號()包起來
let x;
({x} = {x:1});
3、字符串的解構(gòu)賦值

字符串也可以解構(gòu)賦值。這是因為此時,字符串被轉(zhuǎn)換成了一個類似數(shù)組的對象。

const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"

類似數(shù)組的對象都有一個 length 屬性,因此還可以對這個屬性解構(gòu)賦值。

let {length: len} = 'hello';
len;// 5
4、數(shù)值和布爾值的解構(gòu)賦值

解構(gòu)賦值時,如果等號右邊是數(shù)值和布爾值,則會先轉(zhuǎn)化為對象:

let {toString: s} = 123;
s === Number.prototype.toString // true

let {toString: s} = true;
s === Boolean.prototype.toString // true

上面代碼中,數(shù)值和布爾值的包裝對象都有 toString 屬性,因此變量 s 都可以取到值。

解構(gòu)賦值的規(guī)則是:只要等號右邊的值不是對象或數(shù)組,就先將其轉(zhuǎn)化為對象。 由于 undefined 和 null 無法轉(zhuǎn)化為對象,所以對他們進(jìn)行解構(gòu)賦值都會報錯。

5、函數(shù)參數(shù)的解構(gòu)賦值
function add([x, y]){
  return x + y;
}

add([1, 2]); // 3

[[1, 2], [3, 4]].map(([a, b]) => a + b);
// [ 3, 7 ]

上面代碼中,函數(shù) add 的參數(shù)看似是一個數(shù)組,但在傳入?yún)?shù)時,數(shù)組參數(shù)就解構(gòu)為變量 x 和 y。對于函數(shù)內(nèi)部代碼來說,參數(shù)就是 x 和 y。

函數(shù)參數(shù)的解構(gòu)也可以使用默認(rèn)參數(shù):

function move({x=0, y=0}={}) {
 return [x, y];
}
move({x:3,y:8});// [3, 8]
move({x:3});// [3, 0]
move({});// [0, 0]
move();// [0, 0]

上例中,函數(shù) move 的參數(shù)是一個對象,通過對這個對象進(jìn)行解構(gòu),得到變量 x 和 y 的值。如果解構(gòu)失敗,x 和 y 等于默認(rèn)值。

再看下面這種寫法:

function move({x, y} = { x: 0, y: 0 }) {
 return [x, y];
}

move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, undefined]
move({}); // [undefined, undefined]
move(); // [0, 0]

上面的代碼是為函數(shù) move 的參數(shù)指定默認(rèn)值,而不是為變量 x 和 y 指定默認(rèn)值。

6、解構(gòu)的用途

(1)交換變量的值

let x = 1;
let y = 2;
[x, y] = [y, x];
x;// 2
y;// 1

(2)從函數(shù)返回多個值
函數(shù)只能返回一個值,如果要返回多個值,只能將它們放在數(shù)組或?qū)ο罄锩娣祷?。有了解?gòu)賦值,取出這些值就非常方便。

//返回一個數(shù)組
function example() {
   return [1, 2, 3];
}
let [a, b, c] = example();
a;//1
b;//2
c;//3

//返回一個對象
function example(){
   return {
       foo: 1,
       bar: 2
   }
}
let {foo, bar} = example();
foo;//1
bar;//2

(3)函數(shù)參數(shù)的定義
解構(gòu)賦值可以方便的將一組參數(shù)與變量名對應(yīng)起來。

//參數(shù)是一組有序值
function f([x, y, z]) {}
f([1, 2, 3]);

//參數(shù)是一組無序值
function f({x, y, z}) {}
f({x: 1, y: 2, z: 3});

(4)提取JSON數(shù)據(jù)

let data = {
   id: 1,
   status: 'ok',
   data: [867, 5612]
};
let {id, status, data:number} = data;
console.log(id, status, number);// 1 "ok"  [867, 5612]

(5)遍歷Map解構(gòu)

const map = new Map();
map.set('first','hello');
map.set('second','world');
for (let [key, value] of map) {
   console.log(key + ' is ' + value );
}
//first is hello
//second is world

// 獲取鍵名
for (let [key] of map) {}

// 獲取鍵值
for (let [,value] of map) {}

三、函數(shù)的默認(rèn)參數(shù)

1、基本用法

ES6 之前,不能直接為函數(shù)的參數(shù)指定默認(rèn)值,只能采用變通的方法。

function log(x, y) {
 y = y || 'World';
 console.log(x, y);
}

log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello World

上面代碼檢查函數(shù)log的參數(shù)y有沒有賦值,如果沒有,則指定默認(rèn)值為World。這種寫法的缺點在于,如果參數(shù)y賦值了,但是對應(yīng)的布爾值為false,則該賦值不起作用。就像上面代碼的最后一行,參數(shù)y等于空字符,結(jié)果被改為默認(rèn)值。

為了避免這個問題,通常需要先判斷一下參數(shù)y是否被賦值,如果沒有,再等于默認(rèn)值。

if (typeof y === 'undefined') {
 y = 'World';
}

ES6 允許為函數(shù)的參數(shù)設(shè)置默認(rèn)值,即直接寫在參數(shù)定義的后面。

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

log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello -- 上面說過,ES6 內(nèi)部使用嚴(yán)格相等運(yùn)算符(===),判斷一個位置是否有值。所以,只有當(dāng)一個數(shù)組成員嚴(yán)格等于 undefined ,默認(rèn)值才會生效。
2、與解構(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

上面代碼只使用了對象的解構(gòu)賦值默認(rèn)值,沒有使用函數(shù)參數(shù)的默認(rèn)值。只有當(dāng)函數(shù)foo的參數(shù)是一個對象時,變量x和y才會通過解構(gòu)賦值生成。

如果函數(shù)foo調(diào)用時沒提供參數(shù),變量x和y就不會生成,從而報錯。

通過提供函數(shù)參數(shù)的默認(rèn)值,就可以避免這種情況。

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

foo() // undefined 5

下面是另一個解構(gòu)賦值默認(rèn)值的例子:

function fetch(url, { body = '', method = 'GET', headers = {} }) {
 console.log(method);
}

fetch('http://example.com', {})
// "GET"

fetch('http://example.com')
// 報錯

上面代碼中,如果函數(shù)fetch的第二個參數(shù)是一個對象,就可以為它的三個屬性設(shè)置默認(rèn)值。

這種寫法不能省略第二個參數(shù),如果結(jié)合函數(shù)參數(shù)的默認(rèn)值,就可以省略第二個參數(shù)。這時,就出現(xiàn)了雙重默認(rèn)值。

function fetch(url, { body = '', method = 'GET', headers = {} } = {}) {
 console.log(method);
}

fetch('http://example.com')
// "GET"

上面代碼中,函數(shù)fetch沒有第二個參數(shù)時,函數(shù)參數(shù)的默認(rèn)值就會生效,然后才是解構(gòu)賦值的默認(rèn)值生效,變量method才會取到默認(rèn)值GET。

因此,與解構(gòu)賦值默認(rèn)值結(jié)合使用時,切記,函數(shù)要定義默認(rèn)參數(shù),防止函數(shù)不傳參時報錯。

四、模板字符串

模板字符串是增強(qiáng)版的字符串,用反引號 (`) 標(biāo)識。它可以當(dāng)普通字符串使用,也可以用來定義多行字符串,或者在字符串中嵌入變量。

1、基本用法
let greeting = `\`Yo\` World!`;  // `Yo` World -- 使用反斜杠轉(zhuǎn)義反引號

// 多行字符串
$('#result').append(`
 There are <b>${basket.count}</b> items
  in your basket, <em>${basket.onSale}</em>
 are on sale!
`);

Tips:
a. 如果在模板字符串中需要使用反引號,則前面需要使用反斜杠轉(zhuǎn)義。
b. 如果使用模板字符串表示多行字符串,所有的空格和縮進(jìn)都會被保留在輸出之中。

2、在模板字符串使用變量

(1) 在模板字符串中嵌入變量,需要將變量名寫在 ${} 之中。
(2) 大括號內(nèi)部可以放入任意的JavaScript表達(dá)式,可以進(jìn)行運(yùn)算,以及引用對象屬性。
(3) 模板字符串之中還能調(diào)用函數(shù)。
(4) 如果大括號中的值不是字符串,將按照一般的規(guī)則轉(zhuǎn)為字符串。如: 如果大括號中是一個對象,將默認(rèn)調(diào)用對象的 toString 方法。
(5) 如果模板字符串中的變量沒有聲明將會報錯。
(6) 如果大括號內(nèi)部是一個字符串,將原樣輸出。

//普通字符串
`In JavaScript '\n' is a line-feed.`;
`Hello ${'World'}`; // "Hello World"

//字符串中嵌入變量
let name = "Bob", time = "today";
console.log(`Hello ${name}, how are you ${time}?`); //  Hello Bob, how are you today?

//字符串中嵌入 JavaScript 表達(dá)式
`${x} + ${y} = ${x + y}`;// "1 + 2 = 3"
`${x} + ${y * 2} = ${x + y * 2}`;// "1 + 4 = 5"

let obj = {x: 1, y: 2};
`${obj.x + obj.y}`;// "3"

// 字符串中嵌入函數(shù)
function fn(){
   return "hello world"
}
`foo ${fn()} bar`;// "foo hello world bar"

// 字符串中嵌入對象
`${obj}`;// "[object Object]"

// 字符串中嵌入未聲明的變量
`Hello, ${place}`;// ReferenceError: place is not defined

五、箭頭函數(shù)

ES6 允許使用 “箭頭” (=>)定義函數(shù)。

1、基本用法
var f = v => v;
//等同于
var f = function (v) {
   return v;
}

=> 前面的部分是函數(shù)的參數(shù),=> 后面的部分是函數(shù)的代碼塊。

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

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

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

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

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

(3)由于大括號會被解釋為代碼塊,所以如果箭頭函數(shù)直接返回一個對象,就必須在對象外面加上括號,否則會報錯。

// 報錯
let getTempItem = id => { id: id, name: "Temp" };

// 不報錯
let getTempItem = id => ({ id: id, name: "Temp" });
getTempItem(1);//{id: 1, name: "Temp"}

let getTempItem = id => {
   return { id: id, name: "Temp" };
}
getTempItem(1);// {id: 1, name: "Temp"}

(4)箭頭函數(shù)內(nèi)部,可以嵌套箭頭函數(shù)

function insert (value) {
   return {into: function (array){
           return {after: function (afterValue) {
                       array.splice(array.indexOf(ahterValue)+1, 0, value);
                       return array;
                   }
              }
       }    
   }
}
insert(2).into([1, 3]).after(1); //[1, 2, 3]

//使用箭頭函數(shù)改寫
let insert = (value) => ({into: (array) => ({after: (afterValue) => {
           array.splice(array.indexOf(afterValue)+1, 0, value);
           return array;
       }
   })
});
2、箭頭函數(shù)與變量解構(gòu)結(jié)合使用
const full = ({ first, last }) => first + ' ' + last;
full({first: 1, last: 2});// "1 2"
// 等同于
function full(person) {
 return person.first + ' ' + person.last;
}
full({first: 1, last: 2});// "1 2"
3、rest 參數(shù)與箭頭函數(shù)結(jié)合
const numbers = (...nums) => nums;
numbers(1,2,3,4);//  [1, 2, 3, 4]

const headAndTail = (head, ...tail) => [head, tail];
headAndTail(1,2,3,4);// [1,[2,3,4]]
4、箭頭函數(shù)的優(yōu)點

(1)簡化代碼

const isEven = n => n%2 == 0;
isEven(3);// false
isEven(4);// true

(2)簡化回調(diào)函數(shù)

[1, 2, 3].map( x => x*x ); //[1, 4, 9]
[3,2,5].sort((a, b) => a - b); // [2, 3, 5]
5、箭頭函數(shù)的注意點——this

ES5中 this 的指向是可變的,但是箭頭函數(shù)中 this 指向固定化。

var  handler = {
   id: '123',
   init: function () {
       document.addEventListener('click',
           event => this.doSomethisng(event.type), false);
   },
   doSomethisng: function (type) {
       console.log('Handling ' + type + ' for ' + this.id);
   }
};
handler.init();  //Handling click for 123  -- this指向handle  -- this是屬于函數(shù)的一個對象,誰調(diào)用指向誰(es5中)

this 指向的固定化,并不是因為箭頭函數(shù)內(nèi)部有綁定 this 的機(jī)制,實際原因是箭頭函數(shù)內(nèi)部根本沒有自己的this,導(dǎo)致內(nèi)部的this 就是外層代碼塊的 this 。

箭頭函數(shù)的this是比較難理解的,但只要能想象到他是如何從ES5轉(zhuǎn)化來的,就可以完全理解它的作用對象。 箭頭函數(shù)轉(zhuǎn)成 ES5 的代碼如下:

// ES6
function foo() {
 setTimeout(() => {
   console.log('id:', this.id);
 }, 100);
}

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

 setTimeout(function () {
   console.log('id:', _this.id);
 }, 100);
}

Tips:

(1) 函數(shù)體內(nèi)的 this 對象,就是定義時所在的對象,而不是使用時所在的對象。
(2) 不可以當(dāng)構(gòu)造函數(shù),即不可以使用 new 命令,因為它沒有 this,否則會拋出一個錯誤。
(3) 箭頭函數(shù)沒有自己的 this,所以不能使用 call()、apply()、bind() 這些方法去改變 this 指向。
(4) 不可以使用arguments 對象,該對象在函數(shù)體內(nèi)不存在。如果要用,可以使用rest參數(shù)代替。

六、數(shù)組的擴(kuò)展(擴(kuò)展運(yùn)算符)

1、擴(kuò)展運(yùn)算符

(1)基本用法

  擴(kuò)展運(yùn)算符(spread)是三個點(...)。它好比 rest 參數(shù)的逆運(yùn)算,將一個數(shù)組轉(zhuǎn)為用逗號分隔的參數(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>]

  該運(yùn)算符主要用于函數(shù)調(diào)用。擴(kuò)展運(yùn)算符與正常的函數(shù)參數(shù)可以結(jié)合使用,非常靈活。function push(array, ...items) {

  array.push(...items);
}

function add(x, y) {
 return x + y;
}

const numbers = [4, 38];
add(...numbers) // 42

function f(v, w, x, y, z) { }
const args = [0, 1];
f(-1, ...args, 2, ...[3]);

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

注意,擴(kuò)展運(yùn)算符如果放在括號中,JavaScript 引擎就會認(rèn)為這是函數(shù)調(diào)用,否則就會報錯。(...[1,2])

// Uncaught SyntaxError: Unexpected number

console.log((...[1,2]))
// Uncaught SyntaxError: Unexpected number

console.log(...[1,2])  // 不會報錯
2、替代函數(shù)的apply方法

由于擴(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);

3、擴(kuò)展運(yùn)算符引用

(1)復(fù)制數(shù)組

數(shù)組是復(fù)合的數(shù)據(jù)類型,直接復(fù)制的話,只是復(fù)制了指向底層數(shù)據(jù)結(jié)構(gòu)的指針(淺拷貝),而不是克隆一個全新的數(shù)組。

如何實現(xiàn)深拷貝呢?下面看看ES5和ES6的實現(xiàn):

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

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

a2[0] = 2;
a1 // [1, 2]

(2)合并數(shù)組

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

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

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

不過,這兩種方法都是淺拷貝,使用的時候需要注意。如果修改了原數(shù)組的成員,會同步反映到新數(shù)組。

const a1 = [{ foo: 1 }];
const a2 = [{ bar: 2 }];

const a3 = a1.concat(a2);
const a4 = [...a1, ...a2];

a3[0] === a1[0] // true
a4[0] === a1[0] // true

(3)與解構(gòu)賦值結(jié)合

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   // []

注意:如果將擴(kuò)展運(yùn)算符用于數(shù)組賦值,只能放在參數(shù)的最后一位,否則會報錯。

const [...butLast, last] = [1, 2, 3, 4, 5]; // 報錯

const [first, ...middle, last] = [1, 2, 3, 4, 5]; // 報錯

(4)字符串

擴(kuò)展運(yùn)算符可以將字符串和函數(shù)參數(shù)arguments轉(zhuǎn)成真正的數(shù)組

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

function (){
  let arr = [...arguments];
}

七、對象的擴(kuò)展

1、屬性的簡潔表示法

ES6 允許直接寫入變量和函數(shù),作為對象的屬性和方法。這樣的書寫更加簡潔。

const foo = 'bar';
const baz = {foo};
baz // {foo: "bar"}

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

上面代碼表明,ES6 允許在對象之中,直接寫變量。這時,屬性名為變量名, 屬性值為變量的值

屬性簡寫:

function f(x, y) {
 return {x, y};
}

// 等同于
function f(x, y) {
 return {x: x, y: y};
}

f(1, 2) // Object {x: 1, y: 2}

方法簡寫:

const o = {
 method() {
   return "Hello!";
 }
};

// 等同于
const o = {
 method: function() {
   return "Hello!";
 }
};

CommonJS 模塊輸出一組變量,就非常合適使用簡潔寫法。

let ms = {};

function getItem (key) {
 return key in ms ? ms[key] : null;
}

function setItem (key, value) {
 ms[key] = value;
}

function clear () {
 ms = {};
}

module.exports = { getItem, setItem, clear };
// 等同于
module.exports = {
 getItem: getItem,
 setItem: setItem,
 clear: clear
};
2、屬性名表達(dá)式

JavaScript 定義對象的屬性,有兩種方法。

// 方法一
obj.foo = true;

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

上面代碼的方法一是直接用標(biāo)識符作為屬性名,方法二是用表達(dá)式作為屬性名,這時要將表達(dá)式放在方括號之內(nèi)。

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

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

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

let propKey = 'foo';

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

表達(dá)式還可以用于定義方法名。比如我們熟悉的Vuex定義Mutation就是推薦這種方式:

// mutation-types.js
export const SOME_MUTATION = 'SOME_MUTATION'

// store.js
import Vuex from 'vuex'
import { SOME_MUTATION } from './mutation-types'

const store = new Vuex.Store({
 state: { ... },
 mutations: {
   // 我們可以使用 ES2015 風(fēng)格的計算屬性命名功能來使用一個常量作為函數(shù)名
   [SOME_MUTATION] (state) {
     // mutate state
   }
 }
})

var test = {            
  'attr0' : 'attr1',            
  'attr1' : 'attr2',            
  'attr2' : 'attr3',            
  'attr3' : 'I'm here',          
}                  
// 輸出: I'm here  , 方括號可以接受任何JS語句,最后都被轉(zhuǎn)化為字符串。利用這個字符串在key-value集合中尋址。
console.log(test[test[test[test['attr0']]]]);

八、Array 的擴(kuò)展方法

擴(kuò)展運(yùn)算符(展開語法):擴(kuò)展運(yùn)算符可以將數(shù)組或者對象轉(zhuǎn)為用逗號分隔的參數(shù)序列

let ary = [1, 2, 3];
...ary // 1, 2, 3console.log(...ary); // 1 2 3,相當(dāng)于下面的代碼console.log(1,2,3);

擴(kuò)展運(yùn)算符可以應(yīng)用于合并數(shù)組

// 方法一 let ary1 = [1, 2, 3];
let ary2 = [3, 4, 5];
let ary3 = [...ary1, ...ary2];// 方法二 ary1.push(...ary2);

構(gòu)造函數(shù)方法:Array.from()

將偽數(shù)組或可遍歷對象轉(zhuǎn)換為真正的數(shù)組

//定義一個集合let arrayLike = {'0': 'a','1': 'b','2': 'c',
length: 3};
//轉(zhuǎn)成數(shù)組let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']

方法還可以接受第二個參數(shù),作用類似于數(shù)組的map方法,用來對每個元素進(jìn)行處理,將處理后的值放入返回的數(shù)組

let arrayLike = { 
"0": 1,"1": 2,"length": 2}
let newAry = Array.from(arrayLike, item => item *2)//[2,4]注意:如果是對象,那么屬性需要寫對應(yīng)的索引

實例方法:find()

用于找出第一個符合條件的數(shù)組成員,如果沒有找到返回undefined

let ary = [{
id: 1,
name: '張三'}, {
id: 2,
name: '李四'}];
let target = ary.find((item, index) => item.id == 2);//找數(shù)組里面符合條件的值,當(dāng)數(shù)組中元素id等于2的查找出來,注意,只會匹配第一個

實例方法:findIndex()

用于找出第一個符合條件的數(shù)組成員的位置,如果沒有找到返回-1

let ary = [1, 5, 10, 15];
let index = ary.findIndex((value, index) => value > 9);
console.log(index); // 2

實例方法:includes()

判斷某個數(shù)組是否包含給定的值,返回布爾值。

[1, 2, 3].includes(2) // true [1, 2, 3].includes(4) // false

arr.splice(index,len,[item])

表示從數(shù)組中刪除或者添加元素,返回新數(shù)組保存所有刪除的元素
index表示要操作的索引位置,len表示要刪除的個數(shù),如果len的值為0表示不刪除,item表示要添加的元素,可以是多個

let ary = [10, 20, 50]; // 把20給刪除
// ary.splice(1, 1);
// console.log(ary);
// 把20刪除,替換成30
// ary.splice(1, 1, 30);
// console.log(ary);
// 在20前面加上15
// ary.splice(1, 0, 15);
// console.log(ary);
// 在50前面加上30,40ary.splice(2, 0, 30, 40);
console.log(ary);

arr.filter()

返回數(shù)組,包含了符合條件的所有元素。如果沒有符合條件的元素則返回空數(shù)組

// 返回數(shù)組,包含了符合條件的所有元素。如果沒有符合條件的元素則返回空數(shù)組
// let result = ary.filter(item => item > 150);
// console.log(result)

String 的擴(kuò)展方法

實例方法:repeat()

repeat方法表示將原字符串重復(fù)n次,返回一個新字符串

'x'.repeat(3) // "xxx" 'hello'.repeat(2) // "hellohello"

Set 數(shù)據(jù)結(jié)構(gòu)

ES6 提供了新的數(shù)據(jù)結(jié)構(gòu)  Set。它類似于數(shù)組,但是成員的值都是唯一的,沒有重復(fù)的值。

Set本身是一個構(gòu)造函數(shù),用來生成  Set  數(shù)據(jù)結(jié)構(gòu)

const s = new Set();

Set函數(shù)可以接受一個數(shù)組作為參數(shù),用來初始化。

const set = new Set([1, 2, 3, 4, 4]);//{1, 2, 3, 4}

實例方法

add(value):添加某個值,返回 Set 結(jié)構(gòu)本身

delete(value):刪除某個值,返回一個布爾值,表示刪除是否成功

has(value):返回一個布爾值,表示該值是否為 Set 的成員

clear():清除所有成員,沒有返回值

const s = new Set();
s.add(1).add(2).add(3); // 向 set 結(jié)構(gòu)中添加值 s.delete(2) // 刪除 set 結(jié)構(gòu)中的2值 s.has(1) // 表示 set 結(jié)構(gòu)中是否有1這個值 返回布爾值 s.clear() // 清除 set 結(jié)構(gòu)中的所有值//注意:刪除的是元素的值,不是代表的索引

遍歷

Set 結(jié)構(gòu)的實例與數(shù)組一樣,也擁有forEach方法,用于對每個成員執(zhí)行某種操作,沒有返回值。

s.forEach(value => console.log(value))

讀到這里,這篇“es5和es6指的是什么”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領(lǐng)會,如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI