摘要:返回空字符串,返回將一個具名函數賦值給一個變量,則和的屬性都返回這個具名函數原本的名字。不可以使用對象,該對象在函數體內不存在。等到運行結束,將結果返回到,的調用幀才會消失。
1 函數參數的默認值
ES6允許為函數的參數設置默認值,即直接寫在參數定義的后面:
function log(x = "message.",y = "duration infomation.") { console.log(x, y); } log(); //message. duration infomation. log("hello world.", "connecting."); //hello world. connecting.
參數變量是默認聲明的,所以不能用let和const再次聲明
function add(x = 0, y = 0) { let x; //報錯 const y; //報錯 console.log(x + y); } add();
與結構賦值默認值結合使用
function add({x = 0, y = 0}) { console.log(x + y); } add({}); //0 add({y: 1}); //1 //當add()時,則會報錯 add(); //報錯 //如何才能在add()時不報錯呢? //這就需要用到雙重默認值,即默認為函數傳入一個對象 function add({x = 0, y = 0} = {}) { console.log(x + y); } add({}); //0 add({y: 1}); //1 add(); //0
如下:
function add({name = "your name here", age = "your age here"} = {}) { console.log(`${name}, ${age}`); } add(); //your name here, your age here add({name: "Oliver"}); //Oliver, your age here add({name: "Troy", age: 18}); //Troy, 18
函數的length屬性
指定了默認值以后,函數的length屬性,將返回沒有指定默認值的參數個數。
function add(x,y = 0) { console.log(x + y); } console.log(add.length); //1 函數預期傳入1個參數,因為有一個參數已經有默認值了
作用域
如果參數默認值是一個變量,則該變量所處的作用域,與其他變量的作用域規則是一樣的,即先是當前函數的作用域,然后才是全局作用域。
var x = 10; function log(x, y = x) { //x已經在內部生成,使用的將是內部的x console.log(y); } log(2); //2 var x = 10; function log(y = x) { //x不存在,使用的將是外部的x console.log(y); } log(); //10
實際應用
省略參數拋出錯誤:
function throwIfMissing() { throw new Error("Missing parameter."); } function foo(x = throwIfMissing()) { return x; } console.log(foo(10)); //10 console.log(foo()); //Uncaught Error: Missing parameter.2 rest參數
rest參數(形式為“...變量名”),用于獲取函數的多余參數,這樣就不需要使用arguments對象了
function foo(...values) { let sum = 0; for(let val of values) sum += val; console.log(sum); } foo(1,2,3);
注意,rest參數之后不能再有其他參數(即只能是最后一個參數),否則會報錯。
function foo(x, ...values) { let sum = 0; for(let val of values) sum += val; console.log(x, sum); } foo(1,2,3); //x是1,sum是2+3 function foo(x, ...values, y) { let sum = 0; for(let val of values) sum += val; console.log(x, sum); } foo(1,2,3); //Rest parameter must be last formal parameter3 擴展運算符
擴展運算符(spread)是三個點(...)。它好比rest參數的逆運算,將一個數組轉為用逗號分隔的參數序列。
let a = [1,2,3,4,5,6,7]; console.log(...a); //1 2 3 4 5 6 7 a.push(...a); console.log(a); //[1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7]
該運算符主要用于函數的調用
let a = [1,2,3,4,5,6,7]; function add(...args) { let sum = 0; for (let val of args) console.log(sum += val); console.log(`done. final sum: ${sum}`); } add(...a); //依次傳入a數列中的值 //1 //3 //6 //10 //15 //21 //28 //done. final sum: 28
替代數組的apply方法
擴展運算符可以展開數組,所以不再需要apply方法
//ES5 let a = [1,2,3,4,5,6,7]; console.log(Math.max.apply(null,a)); //7 //ES6 console.log(Math.max(...a)); //7
又比如push函數
let a = []; let num = [1,2,3,4,5,6,7]; a.push(...num); console.log(a.toString()); //1,2,3,4,5,6
擴展運算符的應用
合并數組
let a = []; let a1 = [1,2,3]; let a2 = [4,5]; let a3 = [6,7,8,9,10]; a = [...a1, ...a2, ...a3]; console.log(a.toString()); //1,2,3,4,5,6,7,8,9,10
與解構賦值結合
let [...rest] = [1,2,3,4,5,6]; console.log(rest); //[1,2,3,4,5,6]
函數的返回值
var dateFields = readDateFields(database); var d = new Date(...dateFields);
字符串
console.log([..."hello"]); //["h", "e", "l", "l", "o"]
擴展運算符能夠識別32位Unicode字符
可以正確返回字符串長度:
console.log([..."hello"]); //["h", "e", "l", "l", "o"] function len(...args) { for (let val of args) console.log([...val].length); } len("hello", "another one 哈哈"); //14
類似數組的對象
var nodeList = document.getElementsByTagName("p"); var array = [...nodeList];
含有Iterator接口對象
只要具有Iterator接口的對象,都可以使用擴展運算符
Map,Set,Generator等
4 name屬性函數的name屬性,返回該函數的函數名。
如果將一個匿名函數賦值給一個變量,ES5的name屬性,會返回空字符串,而ES6的name屬性會返回實際的函數名。
var x = function() {}; console.log(x.name); //"" ES5返回空字符串,ES6返回x
將一個具名函數賦值給一個變量,則ES5和ES6的name屬性都返回這個具名函數原本的名字。
var x = function y() {}; console.log(x.name); //"y"
Function構造函數返回的函數實例,name屬性的值為“anonymous”。
console.log((new Function).name); //anonymous
bind返回的函數,name屬性值會加上“bound ”前綴。
function foo() {}; foo.bind({}).name // "bound foo" (function(){}).bind({}).name // "bound "5 箭頭函數
ES6允許使用“箭頭”(=>)定義函數。
let add = (x,y) => x + y; console.log(add(1,2)); //3 function add(x,y) { return x + y; } console.log(add(1,2)); //3
如果箭頭函數的代碼塊部分多于一條語句,就要使用大括號將它們括起來,并且使用return語句返回。
let add = (x, y) => { console.log("done"); return x + y; }; console.log(add(1, 2)); //3
如果箭頭函數直接返回一個對象,必須在對象外面加上括號。
let add = (x, y) => ({ result: x + y }); console.log(add(1, 2).result); //3
箭頭函數可以與變量解構結合使用。
let add = ({ name, age }) => ({ result: `${name},${age}` }); console.log(add({ name: "Oliver", age: 18 }).result); //Oliver,18
箭頭函數的一個用處是簡化回調函數
var arr = [1, 2, 3, 4, 5]; arr.map(function(item, index, array) { console.log(item); }); arr.map((item, index, array) => { console.log(item); }); //上面兩種函數寫法功能相同,下面的明顯較為簡潔
使用注意點
函數體內的this對象,就是定義時所在的對象,而不是使用時所在的對象。
不可以當作構造函數,也就是說,不可以使用new命令,否則會拋出一個錯誤。
不可以使用arguments對象,該對象在函數體內不存在。如果要用,可以用Rest參數代替。
不可以使用yield命令,因此箭頭函數不能用作Generator函數。
6 ES7函數綁定ES7中函數綁定運算符(::)作用是代替call、apply、bind調用。
7 尾調用優化尾調用
尾調用(Tail Call)就是指某個函數的最后一步是調用另一個函數:
function g() { console.log("done."); } function j() { console.log("almost done."); } function log(x) { if (x > 0) { return g(); } return j(); } log(10); //done. log(0); //almost done.
g()和j()的調用都屬于尾調用,因為都是函數的最后一步
尾調用優化
函數調用會在內存形成一個“調用記錄”,又稱“調用幀”(call frame),保存調用位置和內部變量等信息。如果在函數A的內部調用函數B,那么在A的調用幀上方,還會形成一個B的調用幀。等到B運行結束,將結果返回到A,B的調用幀才會消失。如果函數B內部還調用函數C,那就還有一個C的調用幀,以此類推。所有的調用幀,就形成一個“調用棧”(call stack)。
尾調用由于是函數的最后一步操作,所以不需要保留外層函數的調用幀,因為調用位置、內部變量等信息都不會再用到了,只要直接用內層函數的調用幀,取代外層函數的調用幀就可以了。
注意,只有不再用到外層函數的內部變量,內層函數的調用幀才會取代外層函數的調用幀,否則就無法進行“尾調用優化”。
function addOne(a) { var one = 1; function inner(b) { return b + one; } return inner(a); }
尾遞歸
遞歸非常耗費內存,因為需要同時保存成千上百個調用幀,很容易發生“棧溢出”錯誤。但對于尾遞歸來說,由于只存在一個調用幀,所以永遠不會發生“棧溢出”錯誤。
所以確保最后只調用自身就可以了,做法是將所有參數傳入要調用的函數中去:
// function log(n) { // if (n === 1) { // return 1 // }; // return n * log(n - 1); // } // console.log(log(5)); //120 function log(n, total) { if (n === 1) { return total }; return log(n - 1, n * total); } console.log(log(5, 1)); //1208 ES7函數參數的尾逗號
ES7提案允許函數的最后一個參數有尾逗號。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/79157.html
摘要:否則調用時依然需要傳參報錯注意這里不能用觸發默認值這里我們還需要單獨討論一下默認參數對的影響很明顯,默認參數并不能加到中。關于作用域集中在函數擴展的最后討論。那如果函數的默認參數是函數呢燒腦的要來了如果基礎好那就根本談不上不燒腦。 參數默認值 ES5中設置默認值非常不方便, 我們這樣寫: function fun(a){ a = a || 2; console.log(a); ...
摘要:基本用法所聲明的變量,只在命令所在的代碼塊內有效。在循環中適合使用不存在變量提升不像那樣會發生變量提升現象暫時性死區只要塊級作用域內存在命令,它所聲明的變量就綁定這個區域,不再受外部的影響。塊級作用域實際上為新增了塊級作用域。 1 let 基本用法 所聲明的變量,只在let命令所在的代碼塊內有效。 { let b = 100; console.log(b); //100...
摘要:第二個參數指定修飾符,如果存在則使用指定的修飾符。屬性表示是否設置了修飾符屬性的屬性返回正則表達式的正文的屬性返回正則表達式的修飾符字符串必須轉義,才能作為正則模式。 1 RegExp構造函數 ES6 允許RegExp構造函數接受正則表達式作為參數。第二個參數指定修飾符,如果存在則使用指定的修飾符。 var regexp = new RegExp(/xyz/i, ig); consol...
摘要:二進制和八進制表示法提供了二進制和八進制數值的新的寫法,分別用前綴或和或表示。用來檢查是否為有窮以及是否為這兩個新方法只對數值有效,非數值一律返回。引入了和這兩個常量,用來表示這個范圍的上下限。因為有精度限制,超過的次方的值無法精確表示。 1 二進制和八進制表示法 ES6提供了二進制和八進制數值的新的寫法,分別用前綴0b(或0B)和0o(或0O)表示。 console.log(0b10...
摘要:數組的解構賦值允許按照一定模式,從數組和對象中提取值,對變量進行賦值,這被稱為解構。如果變量名與屬性名不一致,必須寫成下面這樣。 1 數組的解構賦值 ES6允許按照一定模式,從數組和對象中提取值,對變量進行賦值,這被稱為解構(Destructuring)。 基本用法 { var [a,[b,c],d,,...f] = [1,[2,3],4,5,6,7]; console...
閱讀 3468·2021-11-25 09:43
閱讀 1073·2021-11-15 11:36
閱讀 3320·2021-11-11 16:54
閱讀 3988·2021-09-27 13:35
閱讀 4376·2021-09-10 11:23
閱讀 5759·2021-09-07 10:22
閱讀 3044·2021-09-04 16:40
閱讀 778·2021-08-03 14:03