ES6新特性
ES6語法
Tags: javascript
[TOC]
const 與 let 變量
使用var帶來的麻煩:
function getClothing(isCold) {if (isCold) {var freezing = 'Grab a jacket!';} else {var hot = 'It's a shorts kind of day.';console.log(freezing);} }運(yùn)行g(shù)etClothing(false)后輸出的是undefined,這是因?yàn)閳?zhí)行function函數(shù)之前,所有變量都會(huì)被提升, 提升到函數(shù)作用域頂部.
let與const聲明的變量解決了這種問題,因?yàn)樗麄兪菈K級(jí)作用域, 在代碼塊(用{}表示)中使用let或const聲明變量, 該變量會(huì)陷入暫時(shí)性死區(qū)直到該變量的聲明被處理.
function getClothing(isCold) {if (isCold) {const freezing = 'Grab a jacket!';} else {const hot = 'It's a shorts kind of day.';console.log(freezing);} }運(yùn)行g(shù)etClothing(false)后輸出的是ReferenceError: freezing is not defined,因?yàn)?freezing 沒有在 else 語句、函數(shù)作用域或全局作用域內(nèi)聲明,所以拋出 ReferenceError。
關(guān)于使用let與const規(guī)則:
- 使用let聲明的變量可以重新賦值,但是不能在同一作用域內(nèi)重新聲明
- 使用const聲明的變量必須賦值初始化,但是不能在同一作用域類重新聲明也無法重新賦值.
模板字面量
在ES6之前,將字符串連接到一起的方法是+或者concat()方法,如
const student = {name: 'Richard Kalehoff',guardian: 'Mr. Kalehoff' };const teacher = {name: 'Mrs. Wilson',room: 'N231' }let message = student.name + ' please see ' + teacher.name + ' in ' + teacher.room + ' to pick up your report card.';模板字面量本質(zhì)上是包含嵌入式表達(dá)式的字符串字面量.
模板字面量用倒引號(hào) ( `` )(而不是單引號(hào) ( '' ) 或雙引號(hào)( "" ))表示,可以包含用 ${expression} 表示的占位符
解構(gòu)
在ES6中,可以使用解構(gòu)從數(shù)組和對(duì)象提取值并賦值給獨(dú)特的變量
解構(gòu)數(shù)組的值:
const point = [10, 25, -34]; const [x, y, z] = point; console.log(x, y, z);Prints: 10 25 -34
[]表示被解構(gòu)的數(shù)組, x,y,z表示要將數(shù)組中的值存儲(chǔ)在其中的變量, 在解構(gòu)數(shù)組是, 還可以忽略值, 例如const[x,,z]=point,忽略y坐標(biāo).
解構(gòu)對(duì)象中的值:
const gemstone = {type: 'quartz',color: 'rose',karat: 21.29 }; const {type, color, karat} = gemstone; console.log(type, color, karat);花括號(hào) { } 表示被解構(gòu)的對(duì)象,type、color 和 karat 表示要將對(duì)象中的屬性存儲(chǔ)到其中的變量
對(duì)象字面量簡寫法
let type = 'quartz'; let color = 'rose'; let carat = 21.29;const gemstone = {type: type,color: color,carat: carat };console.log(gemstone);使用和所分配的變量名稱相同的名稱初始化對(duì)象時(shí)如果屬性名稱和所分配的變量名稱一樣,那么就可以從對(duì)象屬性中刪掉這些重復(fù)的變量名稱。
let type = 'quartz'; let color = 'rose'; let carat = 21.29; const gemstone = {type,color,carat}; console.log(gemstone);簡寫方法的名稱:
const gemstone = {type,color,carat,calculateWorth: function() {// 將根據(jù)類型(type),顏色(color)和克拉(carat)計(jì)算寶石(gemstone)的價(jià)值} };匿名函數(shù)被分配給屬性 calculateWorth,但是真的需要 function 關(guān)鍵字嗎?在 ES6 中不需要!
let gemstone = {type,color,carat,calculateWorth() { ... } };for...of循環(huán)
for...of循環(huán)是最新添加到 JavaScript 循環(huán)系列中的循環(huán)。
它結(jié)合了其兄弟循環(huán)形式 for 循環(huán)和 for...in 循環(huán)的優(yōu)勢,可以循環(huán)任何可迭代(也就是遵守可迭代協(xié)議)類型的數(shù)據(jù)。默認(rèn)情況下,包含以下數(shù)據(jù)類型:String、Array、Map 和 Set,注意不包含 Object 數(shù)據(jù)類型(即 {})。默認(rèn)情況下,對(duì)象不可迭代。
for循環(huán)
const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; for (let i = 0; i < digits.length; i++) {console.log(digits[i]); }for 循環(huán)的最大缺點(diǎn)是需要跟蹤計(jì)數(shù)器和退出條件。
雖然 for 循環(huán)在循環(huán)數(shù)組時(shí)的確具有優(yōu)勢,但是某些數(shù)據(jù)結(jié)構(gòu)不是數(shù)組,因此并非始終適合使用 loop 循環(huán)。
for...in循環(huán)
const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];for (const index in digits) {console.log(digits[index]); }依然需要使用 index 來訪問數(shù)組的值
當(dāng)你需要向數(shù)組中添加額外的方法(或另一個(gè)對(duì)象)時(shí),for...in 循環(huán)會(huì)帶來很大的麻煩。因?yàn)?for...in 循環(huán)循環(huán)訪問所有可枚舉的屬性,意味著如果向數(shù)組的原型中添加任何其他屬性,這些屬性也會(huì)出現(xiàn)在循環(huán)中。
forEach 循環(huán) 是另一種形式的 JavaScript 循環(huán)。但是,forEach() 實(shí)際上是數(shù)組方法,因此只能用在數(shù)組中。也無法停止或退出 forEach 循環(huán)。如果希望你的循環(huán)中出現(xiàn)這種行為,則需要使用基本的 for 循環(huán)。
for...of循環(huán)
for...of 循環(huán)用于循環(huán)訪問任何可迭代的數(shù)據(jù)類型。
for...of 循環(huán)的編寫方式和 for...in 循環(huán)的基本一樣,只是將 in 替換為 of,可以忽略索引。
建議使用復(fù)數(shù)對(duì)象名稱來表示多個(gè)值的集合。這樣,循環(huán)該集合時(shí),可以使用名稱的單數(shù)版本來表示集合中的單個(gè)值。例如,for (const button of buttons) {…}。
for...of 循環(huán)還具有其他優(yōu)勢,解決了 for 和 for...in 循環(huán)的不足之處。你可以隨時(shí)停止或退出 for...of 循環(huán)。
for (const digit of digits) {if (digit % 2 === 0) {continue;}console.log(digit); }不用擔(dān)心向?qū)ο笾刑砑有碌膶傩浴?strong>for...of 循環(huán)將只循環(huán)訪問對(duì)象中的值。
Array.prototype.decimalfy = function() {for (i = 0; i < this.length; i++) {this[i] = this[i].toFixed(2);} };const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];for (const digit of digits) {console.log(digit); }展開運(yùn)算符
展開運(yùn)算符(用三個(gè)連續(xù)的點(diǎn) (...) 表示)是 ES6 中的新概念,使你能夠?qū)⒆置媪繉?duì)象展開為多個(gè)元素
const books = ["Don Quixote", "The Hobbit", "Alice in Wonderland", "Tale of Two Cities"]; console.log(...books);Prints: Don Quixote The Hobbit Alice in Wonderland Tale of Two Cities
展開運(yùn)算符的一個(gè)用途是結(jié)合數(shù)組。
如果你需要結(jié)合多個(gè)數(shù)組,在有展開運(yùn)算符之前,必須使用 Array的 concat() 方法。
const fruits = ["apples", "bananas", "pears"]; const vegetables = ["corn", "potatoes", "carrots"]; const produce = fruits.concat(vegetables); console.log(produce);Prints: ["apples", "bananas", "pears", "corn", "potatoes", "carrots"]
使用展開符來結(jié)合數(shù)組
const fruits = ["apples", "bananas", "pears"]; const vegetables = ["corn", "potatoes", "carrots"]; const produce = [...fruits,...vegetables]; console.log(produce);剩余參數(shù)(可變參數(shù))
使用展開運(yùn)算符將數(shù)組展開為多個(gè)元素, 使用剩余參數(shù)可以將多個(gè)元素綁定到一個(gè)數(shù)組中.
剩余參數(shù)也用三個(gè)連續(xù)的點(diǎn) ( ... ) 表示,使你能夠?qū)⒉欢〝?shù)量的元素表示為數(shù)組.
用途1: 將變量賦數(shù)組值時(shí):
const order = [20.17, 18.67, 1.50, "cheese", "eggs", "milk", "bread"]; const [total, subtotal, tax, ...items] = order; console.log(total, subtotal, tax, items);用途2: 可變參數(shù)函數(shù)
對(duì)于參數(shù)不固定的函數(shù),ES6之前是使用參數(shù)對(duì)象(arguments)處理:
在ES6中使用剩余參數(shù)運(yùn)算符則更為簡潔,可讀性提高:
function sum(...nums) {let total = 0; for(const num of nums) {total += num;}return total; }ES6箭頭函數(shù)
ES6之前,使用普通函數(shù)把其中每個(gè)名字轉(zhuǎn)換為大寫形式:
const upperizedNames = ['Farrin', 'Kagure', 'Asser'].map(function(name) { return name.toUpperCase(); });箭頭函數(shù)表示:
const upperizedNames = ['Farrin', 'Kagure', 'Asser'].map(name => name.toUpperCase() );普通函數(shù)可以是函數(shù)聲明或者函數(shù)表達(dá)式, 但是箭頭函數(shù)始終都是表達(dá)式, 全程是箭頭函數(shù)表達(dá)式, 因此因此僅在表達(dá)式有效時(shí)才能使用,包括:
- 存儲(chǔ)在變量中,
- 當(dāng)做參數(shù)傳遞給函數(shù),
- 存儲(chǔ)在對(duì)象的屬性中。
可以如下調(diào)用:
greet('Asser');如果函數(shù)的參數(shù)只有一個(gè),不需要使用()包起來,但是只有一個(gè)或者多個(gè), 則必須需要將參數(shù)列表放在圓括號(hào)內(nèi):
// 空參數(shù)列表需要括號(hào) const sayHi = () => console.log('Hello Udacity Student!');// 多個(gè)參數(shù)需要括號(hào) const orderIceCream = (flavor, cone) => console.log(`Here's your ${flavor} ice cream in a ${cone} cone.`); orderIceCream('chocolate', 'waffle');一般箭頭函數(shù)都只有一個(gè)表達(dá)式作為函數(shù)主題:
const upperizedNames = ['Farrin', 'Kagure', 'Asser'].map(name => name.toUpperCase() );這種函數(shù)表達(dá)式形式稱為簡寫主體語法:
- 在函數(shù)主體周圍沒有花括號(hào),
- 自動(dòng)返回表達(dá)式
但是如果箭頭函數(shù)的主體內(nèi)需要多行代碼, 則需要使用常規(guī)主體語法:
- 它將函數(shù)主體放在花括號(hào)內(nèi)
- 需要使用 return 語句來返回內(nèi)容。
javascript標(biāo)準(zhǔn)函數(shù)this
sundae這個(gè)構(gòu)造函數(shù)內(nèi)的this的值是實(shí)例對(duì)象, 因?yàn)樗褂胣ew被調(diào)用.
函數(shù)使用call/apply被調(diào)用,this的值指向指定的obj2,因?yàn)閏all()第一個(gè)參數(shù)明確設(shè)置this的指向
函數(shù)是對(duì)象的方法, this指向就是那個(gè)對(duì)象,此處this就是指向data.
此處是this指向全局對(duì)象,在嚴(yán)格模式下,指向undefined.
javascript中this是很復(fù)雜的概念, 要詳細(xì)判斷this,請(qǐng)參考this豁然開朗
箭頭函數(shù)和this
對(duì)于普通函數(shù), this的值基于函數(shù)如何被調(diào)用, 對(duì)于箭頭函數(shù),this的值基于函數(shù)周圍的上下文, 換句話說,this的值和函數(shù)外面的this的值是一樣的.
function IceCream() {this.scoops = 0; }// 為 IceCream 添加 addScoop 方法 IceCream.prototype.addScoop = function() {setTimeout(function() {this.scoops++;console.log('scoop added!');console.log(this.scoops); // undefined+1=NaNconsole.log(dessert.scoops); //0}, 500); };----------標(biāo)題const dessert = new IceCream(); dessert.addScoop();傳遞給 setTimeout() 的函數(shù)被調(diào)用時(shí)沒用到 new、call() 或 apply(),也沒用到上下文對(duì)象。意味著函數(shù)內(nèi)的 this 的值是全局對(duì)象,不是 dessert 對(duì)象。實(shí)際上發(fā)生的情況是,創(chuàng)建了新的 scoops 變量(默認(rèn)值為 undefined),然后遞增(undefined + 1 結(jié)果為 NaN);
解決此問題的方式之一是使用閉包(closure):
// 構(gòu)造函數(shù) function IceCream() {this.scoops = 0; }// 為 IceCream 添加 addScoop 方法 IceCream.prototype.addScoop = function() {const cone = this; // 設(shè)置 `this` 給 `cone`變量setTimeout(function() {cone.scoops++; // 引用`cone`變量console.log('scoop added!'); console.log(dessert.scoops);//1}, 0.5); };const dessert = new IceCream(); dessert.addScoop();箭頭函數(shù)的作用正是如此, 將setTimeOut()的函數(shù)改為剪頭函數(shù):
// 構(gòu)造函數(shù) function IceCream() {this.scoops = 0; }// 為 IceCream 添加 addScoop 方法 IceCream.prototype.addScoop = function() {setTimeout(() => { // 一個(gè)箭頭函數(shù)被傳遞給setTimeoutthis.scoops++;console.log('scoop added!');console.log(dessert.scoops);//1}, 0.5); };const dessert = new IceCream(); dessert.addScoop();默認(rèn)參數(shù)函數(shù)
function greet(name, greeting) {name = (typeof name !== 'undefined') ? name : 'Student';greeting = (typeof greeting !== 'undefined') ? greeting : 'Welcome';return `${greeting} ${name}!`; }greet(); // Welcome Student! greet('James'); // Welcome James! greet('Richard', 'Howdy'); // Howdy Richard!greet() 函數(shù)中混亂的前兩行的作用是什么?它們的作用是當(dāng)所需的參數(shù)未提供時(shí),為函數(shù)提供默認(rèn)的值。但是看起來很麻煩, ES6引入一種新的方式創(chuàng)建默認(rèn)值, 他叫默認(rèn)函數(shù)參數(shù):
function greet(name = 'Student', greeting = 'Welcome') {return `${greeting} ${name}!`; }greet(); // Welcome Student! greet('James'); // Welcome James! greet('Richard', 'Howdy'); // Howdy Richard!默認(rèn)值與解構(gòu)
createGrid() 函數(shù)預(yù)期傳入的是數(shù)組。它通過解構(gòu)將數(shù)組中的第一項(xiàng)設(shè)為 width,第二項(xiàng)設(shè)為 height。如果數(shù)組為空,或者只有一項(xiàng),那么就會(huì)使用默認(rèn)參數(shù),并將缺失的參數(shù)設(shè)為默認(rèn)值 5。
但是存在一個(gè)問題:
createGrid(); // throws an errorUncaught TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined
出現(xiàn)錯(cuò)誤,因?yàn)?createGrid() 預(yù)期傳入的是數(shù)組,然后對(duì)其進(jìn)行解構(gòu)。因?yàn)楹瘮?shù)被調(diào)用時(shí)沒有傳入數(shù)組,所以出現(xiàn)問題。但是,我們可以使用默認(rèn)的函數(shù)參數(shù)!
function createGrid([width = 5, height = 5] = []) {return `Generating a grid of ${width} by ${height}`; } createGrid(); // Generates a 5 x 5 gridReturns: Generates a 5 x 5 grid
就像使用數(shù)組默認(rèn)值解構(gòu)數(shù)組一樣,函數(shù)可以讓對(duì)象成為一個(gè)默認(rèn)參數(shù),并使用對(duì)象解構(gòu):
function createSundae({scoops = 1, toppings = ['Hot Fudge']}={}) {const scoopText = scoops === 1 ? 'scoop' : 'scoops';return `Your sundae has ${scoops} ${scoopText} with ${toppings.join(' and ')} toppings.`; }createSundae({}); // Your sundae has 1 scoop with Hot Fudge toppings. createSundae({scoops: 2}); // Your sundae has 2 scoops with Hot Fudge toppings. createSundae({scoops: 2, toppings: ['Sprinkles']}); // Your sundae has 2 scoops with Sprinkles toppings. createSundae({toppings: ['Cookie Dough']}); // Your sundae has 1 scoop with Cookie Dough toppings. createSundae(); // Your sundae has 1 scoop with Hot Fudge toppings.默認(rèn)函數(shù)參數(shù)只是個(gè)簡單的添加內(nèi)容,但是卻帶來很多便利!與數(shù)組默認(rèn)值相比,對(duì)象默認(rèn)值具備的一個(gè)優(yōu)勢是能夠處理跳過的選項(xiàng)??纯聪旅娴拇a:
function createSundae({scoops = 1, toppings = ['Hot Fudge']} = {}) { … }在 createSundae() 函數(shù)使用對(duì)象默認(rèn)值進(jìn)行解構(gòu)時(shí),如果你想使用 scoops 的默認(rèn)值,但是更改 toppings,那么只需使用 toppings 傳入一個(gè)對(duì)象:
createSundae({toppings: ['Hot Fudge', 'Sprinkles', 'Caramel']});將上述示例與使用數(shù)組默認(rèn)值進(jìn)行解構(gòu)的同一函數(shù)相對(duì)比。
function createSundae([scoops = 1, toppings = ['Hot Fudge']] = []) { … }對(duì)于這個(gè)函數(shù),如果想使用 scoops 的默認(rèn)數(shù)量,但是更改 toppings,則必須以這種奇怪的方式調(diào)用你的函數(shù):
createSundae([undefined, ['Hot Fudge', 'Sprinkles', 'Caramel']]);因?yàn)閿?shù)組是基于位置的,我們需要傳入 undefined 以跳過第一個(gè)參數(shù)(并使用默認(rèn)值)來到達(dá)第二個(gè)參數(shù)。
Javascript類
ES5創(chuàng)建類:
function Plane(numEngines) {this.numEngines = numEngines;this.enginesActive = false; }// 由所有實(shí)例 "繼承" 的方法 Plane.prototype.startEngines = function () {console.log('starting engines...');this.enginesActive = true; };ES6類只是一個(gè)語法糖,原型繼續(xù)實(shí)際上在底層隱藏起來, 與傳統(tǒng)類機(jī)制語言有些區(qū)別.
class Plane {//constructor方法雖然在類中,但不是原型上的方法,只是用來生成實(shí)例的.constructor(numEngines) {this.numEngines = numEngines;this.enginesActive = false;}//原型上的方法, 由所有實(shí)例對(duì)象共享.startEngines() {console.log('starting engines…');this.enginesActive = true;} }console.log(typeof Plane); //functionjavascript中類其實(shí)只是function, 方法之間不能使用,,不用逗號(hào)區(qū)分屬性和方法.
靜態(tài)方法
要添加靜態(tài)方法,請(qǐng)?jiān)诜椒Q前面加上關(guān)鍵字 static
- 關(guān)鍵字class帶來其他基于類的語言的很多思想,但是沒有向javascript中添加此功能
- javascript類實(shí)際上還是原型繼承
- 創(chuàng)建javascript類的新實(shí)例時(shí)必須使用new關(guān)鍵字
super 和 extends
使用新的super和extends關(guān)鍵字?jǐn)U展類:
class Tree {constructor(size = '10', leaves = {spring: 'green', summer: 'green', fall: 'orange', winter: null}) {this.size = size;this.leaves = leaves;this.leafColor = null;}changeSeason(season) {this.leafColor = this.leaves[season];if (season === 'spring') {this.size += 1;}} }class Maple extends Tree {constructor(syrupQty = 15, size, leaves) {super(size, leaves); //super用作函數(shù)this.syrupQty = syrupQty;}changeSeason(season) {super.changeSeason(season);//super用作對(duì)象if (season === 'spring') {this.syrupQty += 1;}}gatherSyrup() {this.syrupQty -= 3;} }使用ES5編寫同樣功能的類:
function Tree(size, leaves) {this.size = size || 10;this.leaves = leaves || {spring: 'green', summer: 'green', fall: 'orange', winter: null};this.leafColor; }Tree.prototype.changeSeason = function(season) {this.leafColor = this.leaves[season];if (season === 'spring') {this.size += 1;} }function Maple (syrupQty, size, leaves) {Tree.call(this, size, leaves);this.syrupQty = syrupQty || 15; }Maple.prototype = Object.create(Tree.prototype); Maple.prototype.constructor = Maple;Maple.prototype.changeSeason = function(season) {Tree.prototype.changeSeason.call(this, season);if (season === 'spring') {this.syrupQty += 1;} }Maple.prototype.gatherSyrup = function() {this.syrupQty -= 3; }super 必須在 this 之前被調(diào)用
在子類構(gòu)造函數(shù)中,在使用 this 之前,必須先調(diào)用超級(jí)類。
class Apple {} class GrannySmith extends Apple {constructor(tartnessLevel, energy) {this.tartnessLevel = tartnessLevel; // 在 'super' 之前會(huì)拋出一個(gè)錯(cuò)誤!super(energy); } }ES6語法
Tags: javascript
[TOC]
const 與 let 變量
使用var帶來的麻煩:
function getClothing(isCold) {if (isCold) {var freezing = 'Grab a jacket!';} else {var hot = 'It's a shorts kind of day.';console.log(freezing);} }運(yùn)行g(shù)etClothing(false)后輸出的是undefined,這是因?yàn)閳?zhí)行function函數(shù)之前,所有變量都會(huì)被提升, 提升到函數(shù)作用域頂部.
let與const聲明的變量解決了這種問題,因?yàn)樗麄兪菈K級(jí)作用域, 在代碼塊(用{}表示)中使用let或const聲明變量, 該變量會(huì)陷入暫時(shí)性死區(qū)直到該變量的聲明被處理.
function getClothing(isCold) {if (isCold) {const freezing = 'Grab a jacket!';} else {const hot = 'It's a shorts kind of day.';console.log(freezing);} }運(yùn)行g(shù)etClothing(false)后輸出的是ReferenceError: freezing is not defined,因?yàn)?freezing 沒有在 else 語句、函數(shù)作用域或全局作用域內(nèi)聲明,所以拋出 ReferenceError。
關(guān)于使用let與const規(guī)則:
- 使用let聲明的變量可以重新賦值,但是不能在同一作用域內(nèi)重新聲明
- 使用const聲明的變量必須賦值初始化,但是不能在同一作用域類重新聲明也無法重新賦值.
模板字面量
在ES6之前,將字符串連接到一起的方法是+或者concat()方法,如
const student = {name: 'Richard Kalehoff',guardian: 'Mr. Kalehoff' };const teacher = {name: 'Mrs. Wilson',room: 'N231' }let message = student.name + ' please see ' + teacher.name + ' in ' + teacher.room + ' to pick up your report card.';模板字面量本質(zhì)上是包含嵌入式表達(dá)式的字符串字面量.
模板字面量用倒引號(hào) ( `` )(而不是單引號(hào) ( '' ) 或雙引號(hào)( "" ))表示,可以包含用 ${expression} 表示的占位符
解構(gòu)
在ES6中,可以使用解構(gòu)從數(shù)組和對(duì)象提取值并賦值給獨(dú)特的變量
解構(gòu)數(shù)組的值:
const point = [10, 25, -34]; const [x, y, z] = point; console.log(x, y, z);Prints: 10 25 -34
[]表示被解構(gòu)的數(shù)組, x,y,z表示要將數(shù)組中的值存儲(chǔ)在其中的變量, 在解構(gòu)數(shù)組是, 還可以忽略值, 例如const[x,,z]=point,忽略y坐標(biāo).
解構(gòu)對(duì)象中的值:
const gemstone = {type: 'quartz',color: 'rose',karat: 21.29 }; const {type, color, karat} = gemstone; console.log(type, color, karat);花括號(hào) { } 表示被解構(gòu)的對(duì)象,type、color 和 karat 表示要將對(duì)象中的屬性存儲(chǔ)到其中的變量
對(duì)象字面量簡寫法
let type = 'quartz'; let color = 'rose'; let carat = 21.29;const gemstone = {type: type,color: color,carat: carat };console.log(gemstone);使用和所分配的變量名稱相同的名稱初始化對(duì)象時(shí)如果屬性名稱和所分配的變量名稱一樣,那么就可以從對(duì)象屬性中刪掉這些重復(fù)的變量名稱。
let type = 'quartz'; let color = 'rose'; let carat = 21.29; const gemstone = {type,color,carat}; console.log(gemstone);簡寫方法的名稱:
const gemstone = {type,color,carat,calculateWorth: function() {// 將根據(jù)類型(type),顏色(color)和克拉(carat)計(jì)算寶石(gemstone)的價(jià)值} };匿名函數(shù)被分配給屬性 calculateWorth,但是真的需要 function 關(guān)鍵字嗎?在 ES6 中不需要!
let gemstone = {type,color,carat,calculateWorth() { ... } };for...of循環(huán)
for...of循環(huán)是最新添加到 JavaScript 循環(huán)系列中的循環(huán)。
它結(jié)合了其兄弟循環(huán)形式 for 循環(huán)和 for...in 循環(huán)的優(yōu)勢,可以循環(huán)任何可迭代(也就是遵守可迭代協(xié)議)類型的數(shù)據(jù)。默認(rèn)情況下,包含以下數(shù)據(jù)類型:String、Array、Map 和 Set,注意不包含 Object 數(shù)據(jù)類型(即 {})。默認(rèn)情況下,對(duì)象不可迭代。
for循環(huán)
const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; for (let i = 0; i < digits.length; i++) {console.log(digits[i]); }for 循環(huán)的最大缺點(diǎn)是需要跟蹤計(jì)數(shù)器和退出條件。
雖然 for 循環(huán)在循環(huán)數(shù)組時(shí)的確具有優(yōu)勢,但是某些數(shù)據(jù)結(jié)構(gòu)不是數(shù)組,因此并非始終適合使用 loop 循環(huán)。
for...in循環(huán)
const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];for (const index in digits) {console.log(digits[index]); }依然需要使用 index 來訪問數(shù)組的值
當(dāng)你需要向數(shù)組中添加額外的方法(或另一個(gè)對(duì)象)時(shí),for...in 循環(huán)會(huì)帶來很大的麻煩。因?yàn)?for...in 循環(huán)循環(huán)訪問所有可枚舉的屬性,意味著如果向數(shù)組的原型中添加任何其他屬性,這些屬性也會(huì)出現(xiàn)在循環(huán)中。
forEach 循環(huán) 是另一種形式的 JavaScript 循環(huán)。但是,forEach() 實(shí)際上是數(shù)組方法,因此只能用在數(shù)組中。也無法停止或退出 forEach 循環(huán)。如果希望你的循環(huán)中出現(xiàn)這種行為,則需要使用基本的 for 循環(huán)。
for...of循環(huán)
for...of 循環(huán)用于循環(huán)訪問任何可迭代的數(shù)據(jù)類型。
for...of 循環(huán)的編寫方式和 for...in 循環(huán)的基本一樣,只是將 in 替換為 of,可以忽略索引。
建議使用復(fù)數(shù)對(duì)象名稱來表示多個(gè)值的集合。這樣,循環(huán)該集合時(shí),可以使用名稱的單數(shù)版本來表示集合中的單個(gè)值。例如,for (const button of buttons) {…}。
for...of 循環(huán)還具有其他優(yōu)勢,解決了 for 和 for...in 循環(huán)的不足之處。你可以隨時(shí)停止或退出 for...of 循環(huán)。
for (const digit of digits) {if (digit % 2 === 0) {continue;}console.log(digit); }不用擔(dān)心向?qū)ο笾刑砑有碌膶傩浴?strong>for...of 循環(huán)將只循環(huán)訪問對(duì)象中的值。
Array.prototype.decimalfy = function() {for (i = 0; i < this.length; i++) {this[i] = this[i].toFixed(2);} };const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];for (const digit of digits) {console.log(digit); }展開運(yùn)算符
展開運(yùn)算符(用三個(gè)連續(xù)的點(diǎn) (...) 表示)是 ES6 中的新概念,使你能夠?qū)⒆置媪繉?duì)象展開為多個(gè)元素
const books = ["Don Quixote", "The Hobbit", "Alice in Wonderland", "Tale of Two Cities"]; console.log(...books);Prints: Don Quixote The Hobbit Alice in Wonderland Tale of Two Cities
展開運(yùn)算符的一個(gè)用途是結(jié)合數(shù)組。
如果你需要結(jié)合多個(gè)數(shù)組,在有展開運(yùn)算符之前,必須使用 Array的 concat() 方法。
const fruits = ["apples", "bananas", "pears"]; const vegetables = ["corn", "potatoes", "carrots"]; const produce = fruits.concat(vegetables); console.log(produce);Prints: ["apples", "bananas", "pears", "corn", "potatoes", "carrots"]
使用展開符來結(jié)合數(shù)組
const fruits = ["apples", "bananas", "pears"]; const vegetables = ["corn", "potatoes", "carrots"]; const produce = [...fruits,...vegetables]; console.log(produce);剩余參數(shù)(可變參數(shù))
使用展開運(yùn)算符將數(shù)組展開為多個(gè)元素, 使用剩余參數(shù)可以將多個(gè)元素綁定到一個(gè)數(shù)組中.
剩余參數(shù)也用三個(gè)連續(xù)的點(diǎn) ( ... ) 表示,使你能夠?qū)⒉欢〝?shù)量的元素表示為數(shù)組.
用途1: 將變量賦數(shù)組值時(shí):
const order = [20.17, 18.67, 1.50, "cheese", "eggs", "milk", "bread"]; const [total, subtotal, tax, ...items] = order; console.log(total, subtotal, tax, items);用途2: 可變參數(shù)函數(shù)
對(duì)于參數(shù)不固定的函數(shù),ES6之前是使用參數(shù)對(duì)象(arguments)處理:
在ES6中使用剩余參數(shù)運(yùn)算符則更為簡潔,可讀性提高:
function sum(...nums) {let total = 0; for(const num of nums) {total += num;}return total; }ES6箭頭函數(shù)
ES6之前,使用普通函數(shù)把其中每個(gè)名字轉(zhuǎn)換為大寫形式:
const upperizedNames = ['Farrin', 'Kagure', 'Asser'].map(function(name) { return name.toUpperCase(); });箭頭函數(shù)表示:
const upperizedNames = ['Farrin', 'Kagure', 'Asser'].map(name => name.toUpperCase() );普通函數(shù)可以是函數(shù)聲明或者函數(shù)表達(dá)式, 但是箭頭函數(shù)始終都是表達(dá)式, 全程是箭頭函數(shù)表達(dá)式, 因此因此僅在表達(dá)式有效時(shí)才能使用,包括:
- 存儲(chǔ)在變量中,
- 當(dāng)做參數(shù)傳遞給函數(shù),
- 存儲(chǔ)在對(duì)象的屬性中。
可以如下調(diào)用:
greet('Asser');如果函數(shù)的參數(shù)只有一個(gè),不需要使用()包起來,但是只有一個(gè)或者多個(gè), 則必須需要將參數(shù)列表放在圓括號(hào)內(nèi):
// 空參數(shù)列表需要括號(hào) const sayHi = () => console.log('Hello Udacity Student!');// 多個(gè)參數(shù)需要括號(hào) const orderIceCream = (flavor, cone) => console.log(`Here's your ${flavor} ice cream in a ${cone} cone.`); orderIceCream('chocolate', 'waffle');一般箭頭函數(shù)都只有一個(gè)表達(dá)式作為函數(shù)主題:
const upperizedNames = ['Farrin', 'Kagure', 'Asser'].map(name => name.toUpperCase() );這種函數(shù)表達(dá)式形式稱為簡寫主體語法:
- 在函數(shù)主體周圍沒有花括號(hào),
- 自動(dòng)返回表達(dá)式
但是如果箭頭函數(shù)的主體內(nèi)需要多行代碼, 則需要使用常規(guī)主體語法:
- 它將函數(shù)主體放在花括號(hào)內(nèi)
- 需要使用 return 語句來返回內(nèi)容。
javascript標(biāo)準(zhǔn)函數(shù)this
sundae這個(gè)構(gòu)造函數(shù)內(nèi)的this的值是實(shí)例對(duì)象, 因?yàn)樗褂胣ew被調(diào)用.
函數(shù)使用call/apply被調(diào)用,this的值指向指定的obj2,因?yàn)閏all()第一個(gè)參數(shù)明確設(shè)置this的指向
函數(shù)是對(duì)象的方法, this指向就是那個(gè)對(duì)象,此處this就是指向data.
此處是this指向全局對(duì)象,在嚴(yán)格模式下,指向undefined.
javascript中this是很復(fù)雜的概念, 要詳細(xì)判斷this,請(qǐng)參考this豁然開朗
箭頭函數(shù)和this
對(duì)于普通函數(shù), this的值基于函數(shù)如何被調(diào)用, 對(duì)于箭頭函數(shù),this的值基于函數(shù)周圍的上下文, 換句話說,this的值和函數(shù)外面的this的值是一樣的.
function IceCream() {this.scoops = 0; }// 為 IceCream 添加 addScoop 方法 IceCream.prototype.addScoop = function() {setTimeout(function() {this.scoops++;console.log('scoop added!');console.log(this.scoops); // undefined+1=NaNconsole.log(dessert.scoops); //0}, 500); };----------標(biāo)題const dessert = new IceCream(); dessert.addScoop();傳遞給 setTimeout() 的函數(shù)被調(diào)用時(shí)沒用到 new、call() 或 apply(),也沒用到上下文對(duì)象。意味著函數(shù)內(nèi)的 this 的值是全局對(duì)象,不是 dessert 對(duì)象。實(shí)際上發(fā)生的情況是,創(chuàng)建了新的 scoops 變量(默認(rèn)值為 undefined),然后遞增(undefined + 1 結(jié)果為 NaN);
解決此問題的方式之一是使用閉包(closure):
// 構(gòu)造函數(shù) function IceCream() {this.scoops = 0; }// 為 IceCream 添加 addScoop 方法 IceCream.prototype.addScoop = function() {const cone = this; // 設(shè)置 `this` 給 `cone`變量setTimeout(function() {cone.scoops++; // 引用`cone`變量console.log('scoop added!'); console.log(dessert.scoops);//1}, 0.5); };const dessert = new IceCream(); dessert.addScoop();箭頭函數(shù)的作用正是如此, 將setTimeOut()的函數(shù)改為剪頭函數(shù):
// 構(gòu)造函數(shù) function IceCream() {this.scoops = 0; }// 為 IceCream 添加 addScoop 方法 IceCream.prototype.addScoop = function() {setTimeout(() => { // 一個(gè)箭頭函數(shù)被傳遞給setTimeoutthis.scoops++;console.log('scoop added!');console.log(dessert.scoops);//1}, 0.5); };const dessert = new IceCream(); dessert.addScoop();默認(rèn)參數(shù)函數(shù)
function greet(name, greeting) {name = (typeof name !== 'undefined') ? name : 'Student';greeting = (typeof greeting !== 'undefined') ? greeting : 'Welcome';return `${greeting} ${name}!`; }greet(); // Welcome Student! greet('James'); // Welcome James! greet('Richard', 'Howdy'); // Howdy Richard!greet() 函數(shù)中混亂的前兩行的作用是什么?它們的作用是當(dāng)所需的參數(shù)未提供時(shí),為函數(shù)提供默認(rèn)的值。但是看起來很麻煩, ES6引入一種新的方式創(chuàng)建默認(rèn)值, 他叫默認(rèn)函數(shù)參數(shù):
function greet(name = 'Student', greeting = 'Welcome') {return `${greeting} ${name}!`; }greet(); // Welcome Student! greet('James'); // Welcome James! greet('Richard', 'Howdy'); // Howdy Richard!默認(rèn)值與解構(gòu)
createGrid() 函數(shù)預(yù)期傳入的是數(shù)組。它通過解構(gòu)將數(shù)組中的第一項(xiàng)設(shè)為 width,第二項(xiàng)設(shè)為 height。如果數(shù)組為空,或者只有一項(xiàng),那么就會(huì)使用默認(rèn)參數(shù),并將缺失的參數(shù)設(shè)為默認(rèn)值 5。
但是存在一個(gè)問題:
createGrid(); // throws an errorUncaught TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined
出現(xiàn)錯(cuò)誤,因?yàn)?createGrid() 預(yù)期傳入的是數(shù)組,然后對(duì)其進(jìn)行解構(gòu)。因?yàn)楹瘮?shù)被調(diào)用時(shí)沒有傳入數(shù)組,所以出現(xiàn)問題。但是,我們可以使用默認(rèn)的函數(shù)參數(shù)!
function createGrid([width = 5, height = 5] = []) {return `Generating a grid of ${width} by ${height}`; } createGrid(); // Generates a 5 x 5 gridReturns: Generates a 5 x 5 grid
就像使用數(shù)組默認(rèn)值解構(gòu)數(shù)組一樣,函數(shù)可以讓對(duì)象成為一個(gè)默認(rèn)參數(shù),并使用對(duì)象解構(gòu):
function createSundae({scoops = 1, toppings = ['Hot Fudge']}={}) {const scoopText = scoops === 1 ? 'scoop' : 'scoops';return `Your sundae has ${scoops} ${scoopText} with ${toppings.join(' and ')} toppings.`; }createSundae({}); // Your sundae has 1 scoop with Hot Fudge toppings. createSundae({scoops: 2}); // Your sundae has 2 scoops with Hot Fudge toppings. createSundae({scoops: 2, toppings: ['Sprinkles']}); // Your sundae has 2 scoops with Sprinkles toppings. createSundae({toppings: ['Cookie Dough']}); // Your sundae has 1 scoop with Cookie Dough toppings. createSundae(); // Your sundae has 1 scoop with Hot Fudge toppings.默認(rèn)函數(shù)參數(shù)只是個(gè)簡單的添加內(nèi)容,但是卻帶來很多便利!與數(shù)組默認(rèn)值相比,對(duì)象默認(rèn)值具備的一個(gè)優(yōu)勢是能夠處理跳過的選項(xiàng)??纯聪旅娴拇a:
function createSundae({scoops = 1, toppings = ['Hot Fudge']} = {}) { … }在 createSundae() 函數(shù)使用對(duì)象默認(rèn)值進(jìn)行解構(gòu)時(shí),如果你想使用 scoops 的默認(rèn)值,但是更改 toppings,那么只需使用 toppings 傳入一個(gè)對(duì)象:
createSundae({toppings: ['Hot Fudge', 'Sprinkles', 'Caramel']});將上述示例與使用數(shù)組默認(rèn)值進(jìn)行解構(gòu)的同一函數(shù)相對(duì)比。
function createSundae([scoops = 1, toppings = ['Hot Fudge']] = []) { … }對(duì)于這個(gè)函數(shù),如果想使用 scoops 的默認(rèn)數(shù)量,但是更改 toppings,則必須以這種奇怪的方式調(diào)用你的函數(shù):
createSundae([undefined, ['Hot Fudge', 'Sprinkles', 'Caramel']]);因?yàn)閿?shù)組是基于位置的,我們需要傳入 undefined 以跳過第一個(gè)參數(shù)(并使用默認(rèn)值)來到達(dá)第二個(gè)參數(shù)。
Javascript類
ES5創(chuàng)建類:
function Plane(numEngines) {this.numEngines = numEngines;this.enginesActive = false; }// 由所有實(shí)例 "繼承" 的方法 Plane.prototype.startEngines = function () {console.log('starting engines...');this.enginesActive = true; };ES6類只是一個(gè)語法糖,原型繼續(xù)實(shí)際上在底層隱藏起來, 與傳統(tǒng)類機(jī)制語言有些區(qū)別.
class Plane {//constructor方法雖然在類中,但不是原型上的方法,只是用來生成實(shí)例的.constructor(numEngines) {this.numEngines = numEngines;this.enginesActive = false;}//原型上的方法, 由所有實(shí)例對(duì)象共享.startEngines() {console.log('starting engines…');this.enginesActive = true;} }console.log(typeof Plane); //functionjavascript中類其實(shí)只是function, 方法之間不能使用,,不用逗號(hào)區(qū)分屬性和方法.
靜態(tài)方法
要添加靜態(tài)方法,請(qǐng)?jiān)诜椒Q前面加上關(guān)鍵字 static
- 關(guān)鍵字class帶來其他基于類的語言的很多思想,但是沒有向javascript中添加此功能
- javascript類實(shí)際上還是原型繼承
- 創(chuàng)建javascript類的新實(shí)例時(shí)必須使用new關(guān)鍵字
super 和 extends
使用新的super和extends關(guān)鍵字?jǐn)U展類:
class Tree {constructor(size = '10', leaves = {spring: 'green', summer: 'green', fall: 'orange', winter: null}) {this.size = size;this.leaves = leaves;this.leafColor = null;}changeSeason(season) {this.leafColor = this.leaves[season];if (season === 'spring') {this.size += 1;}} }class Maple extends Tree {constructor(syrupQty = 15, size, leaves) {super(size, leaves); //super用作函數(shù)this.syrupQty = syrupQty;}changeSeason(season) {super.changeSeason(season);//super用作對(duì)象if (season === 'spring') {this.syrupQty += 1;}}gatherSyrup() {this.syrupQty -= 3;} }使用ES5編寫同樣功能的類:
function Tree(size, leaves) {this.size = size || 10;this.leaves = leaves || {spring: 'green', summer: 'green', fall: 'orange', winter: null};this.leafColor; }Tree.prototype.changeSeason = function(season) {this.leafColor = this.leaves[season];if (season === 'spring') {this.size += 1;} }function Maple (syrupQty, size, leaves) {Tree.call(this, size, leaves);this.syrupQty = syrupQty || 15; }Maple.prototype = Object.create(Tree.prototype); Maple.prototype.constructor = Maple;Maple.prototype.changeSeason = function(season) {Tree.prototype.changeSeason.call(this, season);if (season === 'spring') {this.syrupQty += 1;} }Maple.prototype.gatherSyrup = function() {this.syrupQty -= 3; }super 必須在 this 之前被調(diào)用
在子類構(gòu)造函數(shù)中,在使用 this 之前,必須先調(diào)用超級(jí)類。
class Apple {} class GrannySmith extends Apple {constructor(tartnessLevel, energy) {this.tartnessLevel = tartnessLevel; // 在 'super' 之前會(huì)拋出一個(gè)錯(cuò)誤!super(energy); } }作者:Showdy
鏈接:https://www.jianshu.com/p/87008f4f8513
來源:簡書
簡書著作權(quán)歸作者所有,任何形式的轉(zhuǎn)載都請(qǐng)聯(lián)系作者獲得授權(quán)并注明出處。
轉(zhuǎn)載于:https://www.cnblogs.com/zhanghuajie/p/11093878.html
總結(jié)
- 上一篇: 让你一分钟认识电子身份验证系统EID
- 下一篇: Python爬虫-京东商品到货自动邮件通