『ES6』ES6 - 学习笔记
比較 var 和 let 關鍵字的作用域
使用 var 關鍵字聲明變量時,它是全局聲明的,如果在函數內部聲明則是局部聲明的。
let 關鍵字的行為類似,但有一些額外的功能。 在代碼塊、語句或表達式中使用 let 關鍵字聲明變量時,其作用域僅限于該代碼塊、語句或表達式。
例如:
var numArray = []; for (var i = 0; i < 3; i++) {numArray.push(i); } console.log(numArray); console.log(i);此處控制臺將顯示值 [0, 1, 2] 和 3。
使用 var 關鍵字,i 是全局聲明的。 所以當 i++ 被執行時,它會更新全局變量。 此代碼類似于以下內容:
var numArray = []; var i; for (i = 0; i < 3; i++) {numArray.push(i); } console.log(numArray); console.log(i);此處控制臺將顯示值 [0, 1, 2] 和 3。
如果你創建一個函數,將它存儲起來,稍后在使用 i 變量的 for 循環中使用。這么做可能會出現問題。 這是因為存儲的函數將始終引用更新后的全局 i 變量的值。
var printNumTwo; for (var i = 0; i < 3; i++) {if (i === 2) {printNumTwo = function() {return i;};} } console.log(printNumTwo());此處控制臺將顯示值 3。
可以看到,printNumTwo() 打印了 3 而不是 2。 這是因為賦值給 i 的值已經更新,printNumTwo() 返回全局的 i,而不是在 for 循環中創建函數時 i 的值。 let 關鍵字就不會出現這種現象:
let printNumTwo; for (let i = 0; i < 3; i++) {if (i === 2) {printNumTwo = function() {return i;};} } console.log(printNumTwo()); console.log(i);在這里控制臺將顯示值 2 和一個錯誤提示 i is not defined。
i 未定義,因為它沒有在全局范圍內聲明。 它只在 for 循環語句中被聲明。 printNumTwo() 返回了正確的值,因為 let 關鍵字創建了三個具有唯一值(0、1 和 2)的不同 i 變量在循環語句中。
Object.freeze 防止對象改變
const 聲明并不會真的保護數據不被改變。 為了確保數據不被改變,JavaScript 提供了一個函數 Object.freeze。
任何更改對象的嘗試都將被拒絕,如果腳本在嚴格模式下運行,將拋出錯誤。
let obj = {name:"FreeCodeCamp",review:"Awesome" }; Object.freeze(obj); obj.review = "bad"; obj.name = "Test"; console.log(obj);obj.review 和 obj.newProp 賦值將導致錯誤,因為我們的編輯器默認在嚴格模式下運行,控制臺將顯示值 { name: "FreeCodeCamp", review: "Awesome" }。
箭頭函數
在 JavaScript 和 TypeScript 里,我們會經常遇到不需要給函數命名的情況,尤其是在需要將一個函數作為參數傳給另外一個函數的時候。 這時,我們會創建 匿名函數 。 因為這些函數不會在其他地方復用,所以我們不需要給它們命名。
這種情況下,我們通常會使用以下語法:
const myFunc = function() {const myVar = "value";return myVar; }ES6 提供了其他寫匿名函數的方式的語法糖。 你可以使用 箭頭函數 :
const myFunc = () => {const myVar = "value";return myVar; }當不需要函數體,只返回一個值的時候 ,箭頭函數允許你省略 return 關鍵字和外面的大括號。 這樣就可以將一個簡單的函數簡化成一個單行語句。
const myFunc = () => "value";這段代碼默認會返回字符串 value。
帶參數的箭頭函數
和一般的函數一樣,你也可以給箭頭函數傳遞參數。
JavaScript:
const doubler = (item) => item * 2; doubler(4);TypeScript:
const doubler = (item: number) => item * 2; doubler(4);doubler(4) 將返回 8。
如果箭頭函數只有一個參數,則可以省略參數外面的括號。
const doubler = item => item * 2;注:在 TypeScript 里如果要進行類型注解的話,是不可以省略括號的,如省略了括號的話,則不進行類型注解,默認為 any 類型
可以給箭頭函數傳遞多個參數。
JavaScript:
const multiplier = (item, multi) => item * multi; multiplier(4, 2);TypeScript:
const multiplier = (item: number, multi: number) => item * multi; multiplier(4, 2);multiplier(4, 2) 將返回 8。參數的箭頭函數
和一般的函數一樣,你也可以給箭頭函數傳遞參數。
const doubler = (item) => item * 2; doubler(4);doubler(4) 將返回 8。
如果箭頭函數只有一個參數,則可以省略參數外面的括號。
const doubler = item => item * 2;可以給箭頭函數傳遞多個參數。
const multiplier = (item, multi) => item * multi; multiplier(4, 2);multiplier(4, 2) 將返回 8。
設置函數的默認參數
ES6 里允許給函數傳入默認參數,來構建更加靈活的函數。
請看以下代碼:
const greeting = (name = "Anonymous") => "Hello " + name;console.log(greeting("John")); console.log(greeting());控制臺將顯示字符串 Hello John 和 Hello Anonymous。
默認參數會在參數沒有被指定(值為 undefined)的時候起作用。 在上面的例子中,參數 name 會在沒有得到新的值的時候,默認使用值 Anonymous。 你還可以給多個參數賦予默認值。
rest 操作符
ES6 推出了用于函數參數的 rest 操作符幫助我們創建更加靈活的函數。 rest 操作符可以用于創建有一個變量來接受多個參數的函數。 這些參數被儲存在一個可以在函數內部讀取的數組中。
請看以下代碼:
function howMany(...args) {return "You have passed " + args.length + " arguments."; } console.log(howMany(0, 1, 2)); console.log(howMany("string", null, [1, 2, 3], { }));控制臺將顯示字符串 You have passed 3 arguments. 和 You have passed 4 arguments.。
使用 rest 參數,就不需要查看 args 數組,并且允許我們在參數數組上使用 map()、filter() 和 reduce()。
舉例:
/**** @returns {*}* @param args*/ const sum = (...args) => {return args.reduce((a, b) => a + b, 0); }console.log(sum(0, 1, 2))spread 運算符展開數組項
ES6 引入了展開操作符,可以展開數組以及需要多個參數或元素的表達式。
下面的 ES5 代碼使用了 apply() 來計算數組的最大值:
var arr = [6, 89, 3, 45]; var maximus = Math.max.apply(null, arr);maximus 的值為 89。
我們必須使用 Math.max.apply(null, arr),因為 Math.max(arr) 返回 NaN。 Math.max() 函數中需要傳入的是一系列由逗號分隔的參數,而不是一個數組。 展開操作符可以提升代碼的可讀性,使代碼易于維護。
const arr = [6, 89, 3, 45]; const maximus = Math.max(...arr);maximus 的值應該是 89。
...arr 返回一個解壓的數組。 也就是說,它展開數組。 然而,展開操作符只能夠在函數的參數中或者數組中使用。 下面的代碼將會報錯:
const spreaded = ...arr;使用解構賦值來獲取對象的值
解構賦值是 ES6 引入的新語法,用來從數組和對象中提取值,并優雅地對變量進行賦值。
有如下 ES5 代碼:
const user = { name: 'John Doe', age: 34 };const name = user.name; const age = user.age;name 的值應該是字符串 John Doe, age 的值應該是數字 34。
下面是使用 ES6 解構賦值語句,實現相同效果:
const { name, age } = user;同樣,name 的值應該是字符串 John Doe, age 的值應該是數字 34。
在這里,自動創建 name 和 age 變量,并將 user 對象相應屬性的值賦值給它們。 這個方法簡潔多了。
你可以從對象中提取盡可能多或很少的值。
使用解構賦值從對象中分配變量
可以給解構的值賦予一個新的變量名, 通過在賦值的時候將新的變量名放在冒號后面來實現。
還是以上個例子的對象來舉例:
const user = { name: 'John Doe', age: 34 };這是指定新的變量名的例子:
const { name: userName, age: userAge } = user;你可以這么理解這段代碼:獲取 user.name 的值,將它賦給一個新的變量 userName,等等。 userName 的值將是字符串 John Doe,userAge 的值將是數字 34。
使用解構賦值從嵌套對象中分配變量
使用與前面的例子中類似的對象:
const user = {johnDoe: { age: 34,email: 'johnDoe@freeCodeCamp.com'} };這是解構對象的屬性值賦值給具有相同名字的變量:
const { johnDoe: { age, email }} = user;這是將對象的屬性值賦值給具有不同名字的變量:
const { johnDoe: { age: userAge, email: userEmail }} = user;使用解構賦值從數組中分配變量
在 ES6 里面,解構數組可以如同解構對象一樣簡單。
與數組解構不同,數組的擴展運算會將數組里的所有內容分解成一個由逗號分隔的列表。 所以,你不能選擇哪個元素來給變量賦值。
而對數組進行解構卻可以讓我們做到這一點:
const [a, b] = [1, 2, 3, 4, 5, 6]; console.log(a, b);控制臺將顯示 a 和 b 的值為 1, 2。
數組的第一個值被賦值給變量 a,數組的第二個值被賦值給變量 b。 我們甚至能在數組解構中使用逗號分隔符,來獲取任意一個想要的值:
const [a, b,,, c] = [1, 2, 3, 4, 5, 6]; console.log(a, b, c);控制臺將顯示 a、b 和 c 的值為 1, 2, 5。
使用解構賦值配合 rest 操作符來重新分配數組元素
在解構數組的某些情況下,我們可能希望將剩下的元素放進另一個數組里面。
以下代碼的結果與使用 Array.prototype.slice() 類似:
const [a, b, ...arr] = [1, 2, 3, 4, 5, 7]; console.log(a, b); console.log(arr);控制臺將顯示 1, 2 和 [3, 4, 5, 7]。
變量 a 和 b 分別接收數組的第一個和第二個值。 之后,因為 rest 操作符的存在,arr 獲取了原數組剩余的元素的值。 rest 操作符 只能對數組列表最后的元素起作用。 這意味著你不能使用 rest 操作符 來截取原數組中間的元素作為子數組。
使用解構賦值將對象作為函數的參數傳遞
在某些情況下,你可以在函數的參數里直接解構對象。
請看以下代碼:
const profileUpdate = (profileData) => {const { name, age, nationality, location } = profileData;}上面的操作解構了傳給函數的對象。 這樣的操作也可以直接在參數里完成:
const profileUpdate = ({ name, age, nationality, location }) => {}當 profileData 被傳遞到上面的函數時,從函數參數中解構出值以在函數內使用。
簡單字段編寫簡潔的對象字面量聲明
ES6 添加了一些很棒的功能,用于更方便地定義對象。
請看以下代碼:
const getMousePosition = (x, y) => ({x: x,y: y });getMousePosition 簡單的函數,返回擁有兩個屬性的對象。 ES6 提供了一個語法糖,消除了類似 x: x 這種冗余的寫法。 你可以只寫一次 x,解釋器會自動將其轉換成 x: x(或效果相同的內容)。 下面是使用這種語法重寫的同樣的函數:
const getMousePosition = (x, y) => ({ x, y });ES6 編寫簡潔的函數聲明
在 ES5 中,當我們需要在對象中定義一個函數的時候,必須像這樣使用 function 關鍵字:
const person = {name: "Taylor",sayHello: function() {return `Hello! My name is ${this.name}.`;} };用 ES6 的語法在對象中定義函數的時候,可以刪除 function 關鍵詞和冒號。 請看以下例子:
const person = {name: "Taylor",sayHello() {return `Hello! My name is ${this.name}.`;} };使用 class 語法定義構造函數
ES6 提供了一個新的創建對象的語法,使用關鍵字 class。
值得注意的是,class 只是一個語法糖,它并不像 Java、Python 或者 Ruby 這一類的語言一樣,嚴格履行了面向對象的開發規范。
在 ES5 里面,我們通常會定義一個構造函數 constructor,然后使用 new 關鍵字來實例化一個對象:
var SpaceShuttle = function(targetPlanet){this.targetPlanet = targetPlanet; } var zeus = new SpaceShuttle('Jupiter');class 語法只是簡單地替換了構造函數 constructor 的寫法:
class SpaceShuttle {constructor(targetPlanet) {this.targetPlanet = targetPlanet;} } const zeus = new SpaceShuttle('Jupiter');應該注意 class 關鍵字聲明了一個新的函數,里面添加了一個構造函數。 當用 new 創建一個新的對象時,構造函數會被調用。
**注意:**首字母大寫駝峰命名法 UpperCamelCase 是 ES6 class 命名的慣例,就像上面的 SpaceShuttle。
constructor 方法是一個特殊方法,用于創建和初始化 class 創建的對象。
創建一個模塊腳本
起初,JavaScript 幾乎只在 HTML web 扮演一個很小的角色。 今天,一切不同了,很多網站幾乎全是用 JavaScript 所寫。 為了讓 JavaScript 更模塊化、更整潔以及更易于維護,ES6 引入了在多個 JavaScript 文件之間共享代碼的機制。 它可以導出文件的一部分供其它文件使用,然后在需要它的地方按需導入。 為了使用這一功能, 需要在 HTML 文檔里創建一個 type 為 module 的腳本。 例子如下:
<script type="module" src="filename.js"></script>使用了 module 類型的腳本可以使用 import 和 export 特性
用 export default 創建一個默認導出
在 export 的課程中,你學習了命名導出語法, 這可以在其他文件中引用一些函數或者變量。
還需要了解另外一種被稱為默認導出的 export 的語法。 在文件中只有一個值需要導出的時候,通常會使用這種語法。 它也常常用于給文件或者模塊創建返回值。
下面是使用 export default 的例子:
export default function add(x, y) {return x + y; }export default function(x, y) {return x + y; }第一個是命名函數,第二個是匿名函數。
export default 用于為模塊或文件聲明一個返回值,在每個文件或者模塊中應當只默認導出一個值。 此外,你不能將 export default 與 var、let 或 const 同時使用。
Promise
創建一個 JavaScript Promise
Promise 是異步編程的一種解決方案 - 它在未來的某時會生成一個值。 任務完成,分執行成功和執行失敗兩種情況。 Promise 是構造器函數,需要通過 new 關鍵字來創建。 構造器參數是一個函數,該函數有兩個參數 - resolve 和 reject。 通過它們來判斷 promise 的執行結果。 用法如下:
const myPromise = new Promise((resolve, reject) => {});通過 resolve 和 reject 完成 Promise
Promise 有三個狀態:pending、fulfilled 和 rejected。 上一個挑戰里創建的 promise 一直阻塞在 pending 狀態里,因為沒有調用 promise 的完成方法。 Promise 提供的 resolve 和 reject 參數就是用來結束 promise 的。 Promise 成功時調用 resolve,promise 執行失敗時調用 reject, 如下文所述,這些方法需要有一個參數。
const myPromise = new Promise((resolve, reject) => {if(condition here) {resolve("Promise was fulfilled");} else {reject("Promise was rejected");} });上面的示例使用字符串作為這些函數的參數,但參數實際上可以是任何格式。 通常,它可能是一個包含數據的對象,你可以將它放在網站或其他地方。
用 then 處理 Promise 完成的情況
當程序需要花費未知的時間才能完成時(比如一些異步操作),一般是服務器請求,promise 很有用。 服務器請求會花費一些時間,當結束時,需要根據服務器的響應執行一些操作。 這可以用 then 方法來實現, 當 promise 完成 resolve 時會觸發 then 方法。 例子如下:
myPromise.then(result => {});result 即傳入 resolve 方法的參數。
使用 catch 處理 Promise 失敗的情況
當 promise 失敗時會調用 catch 方法。 當 promise 的 reject 方法執行時會直接調用。 用法如下:
myPromise.catch(error => {});error 是傳入 reject 方法的參數。
總結
以上是生活随笔為你收集整理的『ES6』ES6 - 学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Sass】全面的 Sass 教程及学习
- 下一篇: 【Py面试题】找到数组或整数列表中连续子