您好,登錄后才能下訂單哦!
本文小編為大家詳細(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之間的比較列表如下:
比較項 | ES5 | ES6 |
---|---|---|
定義 | 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中,有兩種定義let 和const 變量的新方法。 |
性能 | 由于ES5早于ES6,因此某些功能不存在,因此其性能比ES6低。 | 由于具有新功能和速記存儲實現(xiàn),因此ES6具有比ES5更高的性能。 |
支持 | 許多社區(qū)都支持它。 | 它也有很多社區(qū)支持,但是比ES5小。 |
對象操縱 | ES5比ES6耗時。 | 由于具有解構(gòu)和速度運(yùn)算符,因此可以在ES6中更平穩(wěn)地處理對象操縱。 |
箭頭函數(shù) | 在ES5中,function 和return 關(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常用特性:
(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),才可以獲取和使用。
const命令的用法和let相似,最大不同點就是:const聲明一個只讀的常量。一旦聲明,常量的值就不能改變。
Tips:這個不可改變的是指針,所以對于const聲明的對象和數(shù)組還是可以改變的。如果真的想將對象凍結(jié),應(yīng)該使用Object.freeze方法。
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
ES6 允許按照一定模式,從數(shù)組和對象中提取值,對變量進(jìn)行賦值,這被稱為解構(gòu)(Destructuring)。
(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];
(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});
字符串也可以解構(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
解構(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)賦值都會報錯。
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)值。
(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) {}
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)值才會生效。
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)普通字符串使用,也可以用來定義多行字符串,或者在字符串中嵌入變量。
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)都會被保留在輸出之中。
(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
ES6 允許使用 “箭頭” (=>)定義函數(shù)。
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;
}
})
});
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"
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]]
(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]
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ù)代替。
(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]) // 不會報錯
由于擴(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];
}
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
};
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']]]]);
擴(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è)資訊頻道。
免責(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)容。