摘要:函數的擴展函數參數的默認值之前,不能直接為函數的參數指定默認值,只能采用變通的方法。箭頭函數引入了一種新的函數,叫做箭頭函數。箭頭函數和普通函數的行為非常相似,但是在語法構成上非常不同。意味著函數內的的值是全局對象,不是對象。
函數的擴展 函數參數的默認值
ES6 之前,不能直接為函數的參數指定默認值,只能采用變通的方法。
function log(x, y) { y = y || "World"; console.log(x, y); }
上面代碼檢查函數log的參數y有沒有賦值,如果沒有,則指定默認值為World。這種寫法的缺點在于,如果參數y賦的值對應的布爾值為false,則該賦值不起作用。
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!
為了避免這個問題,通常需要先判斷一下參數y是否被賦值,如果沒有,再等于默認值。
if (typeof y === "undefined") { y = "World"; }
ES6 允許為函數的參數設置默認值,即直接寫在參數定義的后面。
function log(x, y = "World") { console.log(x, y); } log("Hello") // Hello World剩余參數
剩余參數也用三個連續的點 ( ... ) 表示,使你能夠將不定數量的元素表示為數組。與解構賦值結合
剩余參數可以與解構賦值結合起來,用于生成數組。
const [first, ...rest] = [1, 2, 3, 4, 5]; first // 1 rest // [2, 3, 4, 5]
可以將剩余參數看著展開運算符的對立面;如果展開運算符是拿出包裝盒中的所有物品,那么剩余參數就是將所有物品放回包裝盒中。
可變參數函數剩余參數的另一個用例是處理可變參數函數。可變參數函數是接受不定數量參數的函數。
例如,假設有一個叫做 sum() 的函數,它會計算不定數量的數字的和。在運行期間,如何調用 sum() 函數?
sum(1, 2); sum(10, 36, 7, 84, 90, 110); sum(-23, 3000, 575000);
實際上有無數種方式可以調用 sum() 函數。不管傳入函數的數字有多少個,應該始終返回數字的總和。
使用參數對象
在之前版本的 JavaScript 中,可以使用參數對象處理這種類型的函數。參數對象是像數組一樣的對象,可以當做本地變量在所有函數中使用。它針對傳入函數的每個參數都包含一個值,第一個參數從 0 開始,第二個參數為 1,以此類推。
function sum() { let total = 0; for(const argument of arguments) { total += argument; } return total; }
現在可以正常運行,但是存在問題:
如果查看 sum() 函數的定義,會發現它沒有任何參數。這容易引起誤導,因為我們知道 sum() 函數可以處理不定數量的參數。
難以理解。
如果你從未使用過參數對象,那么看了這段代碼后很可能會疑問參數對象來自何處。是不是憑空出現的?看起來肯定是這樣。
使用剩余參數
function sum(...nums) { let total = 0; for(const num of nums) { total += num; } return total; }
注意,rest 參數之后不能再有其他參數(即只能是最后一個參數),否則會報錯。箭頭函數
ES6 引入了一種新的函數,叫做箭頭函數。箭頭函數和普通函數的行為非常相似,但是在語法構成上非常不同。
普通函數可以是函數聲明或函數表達式,但是箭頭函數始終是表達式。實際上,它們的全稱是“箭頭函數表達式”
//普通函數 const upperizedNames = ["Farrin", "Kagure", "Asser"].map(function(name) { return name.toUpperCase(); }); //箭頭函數 const upperizedNames = ["Farrin", "Kagure", "Asser"].map( name => name.toUpperCase() );
如果箭頭函數不需要參數或需要多個參數,就使用一個圓括號代表參數部分。
var f = () => 5; // 等同于 var f = function () { return 5 }; var sum = (num1, num2) => num1 + num2; // 等同于 var sum = function(num1, num2) { return num1 + num2; };
如果箭頭函數的代碼塊部分多于一條語句,就要使用大括號將它們括起來,并且使用return語句返回。
var sum = (num1, num2) => { return num1 + num2; }箭頭函數中的this
對于普通函數,this 的值基于函數如何被調用。對于箭頭函數,this 的值基于函數周圍的上下文。換句話說,箭頭函數內的,this 的值與函數外面的 this 的值一樣。
我們先看一個普通函數中的 this 示例,再看一個箭頭函數是如何使用 this 的。
// constructor function IceCream() { this.scoops = 0; } // adds scoop to ice cream IceCream.prototype.addScoop = function() { setTimeout(function() { this.scoops++; console.log("scoop added!"); }, 500); }; const dessert = new IceCream(); dessert.addScoop();
運行上述代碼后,你會認為半毫秒之后,dessert.scoops 會是1。但并非這樣:結果是NaN
這是因為傳遞給 setTimeout() 的函數被調用時沒用到 new、call() 或 apply(),也沒用到上下文對象。意味著函數內的 this 的值是全局對象,不是 dessert 對象。實際上發生的情況是,創建了新的 scoops 變量(默認值為 undefined),然后遞增(undefined + 1 結果為 NaN)
// constructor function IceCream() { this.scoops = 0; } // adds scoop to ice cream IceCream.prototype.addScoop = function() { setTimeout(() => { // an arrow function is passed to setTimeout this.scoops++; console.log("scoop added!"); }, 0.5); }; const dessert = new IceCream(); console.log(dessert.scoops); //1
因為箭頭函數從周圍上下文繼承了 this 值,所以這段代碼可行!
如果我們將 addScoop() 方法也改為箭頭函數,你認為會發生什么?
// constructor function IceCream() { this.scoops = 0; } // adds scoop to ice cream IceCream.prototype.addScoop = () => { // addScoop is now an arrow function setTimeout(() => { this.scoops++; console.log("scoop added!"); }, 0.5); }; const dessert = new IceCream(); dessert.addScoop();
這段代碼因為同一原因而不起作用,即箭頭函數從周圍上下文中繼承了 this 值。在 addScoop() 方法外面,this 的值是全局對象。因此如果 addScoop() 是箭頭函數,addScoop() 中的 this 的值是全局對象。這樣的話,傳遞給 setTimeout() 的函數中的 this 的值也設為了該全局對象!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/90680.html
摘要:它是一個通用標準,奠定了的基本語法。年月發布了的第一個版本,正式名稱就是標準簡稱。結語的基本擴展還有一些沒有在這里詳細介紹。 前言 ES6標準以及頒布兩年了,但是,好像還沒有完全走進我們的日常開發。這篇文章從ES6的基本類型擴展入手,逐步展開對ES6的介紹。 ECMAScript和JavaScript JavaScript是由Netscape創造的,該公司1996年11月將JavaSc...
摘要:模板字符串連接符在之前,將字符串連接到一起的舊方法是使用字符串連接運算符。這樣更容易構建字符串。返回布爾值,表示參數字符串是否在原字符串的頭部。它針對前個字符,而其他兩個方法針對從第個位置直到字符串結束。 模板字符串 + 連接符 在 ES6 之前,將字符串連接到一起的舊方法是使用字符串連接運算符 (+)。 const student = { name: Richard Kaleho...
摘要:導入模塊的代碼執行后,實例化過的模塊被保存在內存中,只要另一個語句引用它就可以重復使用它和的一個重要的限制是它們必須在其它語句和函數之外使用,也就是說不允許出現在語句中,不能有條件導出或以任何方式動態導出。 什么是模塊 模塊是自動運行在嚴格模式下并且沒有辦法退出運行的Javascript代碼 在模塊的頂部this的值是undefined 其模塊不支持html風格的代碼注釋除非用def...
摘要:導入模塊的代碼執行后,實例化過的模塊被保存在內存中,只要另一個語句引用它就可以重復使用它和的一個重要的限制是它們必須在其它語句和函數之外使用,也就是說不允許出現在語句中,不能有條件導出或以任何方式動態導出。 什么是模塊 模塊是自動運行在嚴格模式下并且沒有辦法退出運行的Javascript代碼 在模塊的頂部this的值是undefined 其模塊不支持html風格的代碼注釋除非用def...
閱讀 2189·2021-11-15 11:38
閱讀 1151·2021-09-06 15:02
閱讀 3380·2021-08-27 13:12
閱讀 1353·2019-08-30 14:20
閱讀 2389·2019-08-29 15:08
閱讀 636·2019-08-29 14:08
閱讀 1723·2019-08-29 13:43
閱讀 1464·2019-08-26 12:11