摘要:改動函數(shù)的改變不算太大,都是一些其他語言早就有的功能,而一直比較欠缺的,比如函數(shù)參數(shù)默認值,任意參數(shù)的表示法,最大的變化應該是支持箭頭函數(shù)其他語言稱之為表達式,一種對匿名函數(shù)的一種簡寫方式,以下來探討一下函數(shù)在中的一些改變默認參數(shù)任意參數(shù)操
ES6 functions改動
????ES6函數(shù)的改變不算太大,都是一些其他語言早就有的功能,而Javascript一直比較欠缺的,比如函數(shù)參數(shù)默認值,任意參數(shù)的表示法,最大的變化應該是支持箭頭函數(shù)(其他語言稱之為LAMBDA表達式),一種對匿名函數(shù)的一種簡寫方式,以下來探討一下函數(shù)在ES6中的一些改變:
1. 默認參數(shù)(default parameters) 2. 任意參數(shù)(rest parameters ...) 3. spread 操作符(...) 4. new.target 元屬性 5. 箭頭函數(shù)( => ) 6. 其他一些改動(miscellaneous)1.默認參數(shù)
????ES6之前一直是通過其他方法來模擬默認參數(shù)的,例如邏輯或||符號,ES6版本真正意義上支持這種便利的寫法。
// ES5模擬默認參數(shù) function person(name, age) { name = name || "James"; age = age || "18"; console.log(name + " " + age); } // 一般情況下這種寫法是沒問題的,當邏輯或前面的值為falsy值,整個表達式返回后面的值 // 例如: person("Louis"); // ok person(); // ok person(undefined, 20); // ok person("baby", 0); // "baby 18" error, 0為falsy值
上面可以看出這種寫法是有一定問題的,各種JS庫給出了另一種寫法
function person(name, age) { if (typeof name === "undefined") { name = name || "James"; } if (typeof age === "undefined") { age = age || "18"; } console.log(name + " " + age); } person(undefined, 0); // ok "James 0"
ES6寫法
function person(name = "James", age = 18) { console.log(name + " " + age); } // 1各種寫法 默認參數(shù)出現(xiàn)在中間 function getRequest(url, timeout = 2000, callback) { // do something } gerRequest("/foo", undefined, function() { }); // 2默認參數(shù)表達式 let value = 5; function getValue() { return value++; } function add(first, second = getValue()) { return first + second; } add(3); // 8 add(3); // 9 add(1, 1); // 2 // 3后面參數(shù)引用前面參數(shù) function add(first, second = first) { return first + second; } add(2); // 4 add(3, 4); // 7
默認參數(shù)TDZ(暫時死區(qū))情況:
// 上面的第三種寫法,若寫成第一個參數(shù)引用第二個參數(shù) function add(first = second, second) { return first + second; } add(1, 1); // ok 2 add(undefined, 4); // THROW AN ERROR 第二個參數(shù)未聲明就引用就會拋出錯誤 // 就相當于 let first = second; // error let second = 4;2.任意參數(shù)
????ES6任意參數(shù)用 ... 表示,任意參數(shù)和arguments之間的差別
ES5使用arguments參數(shù)來實現(xiàn)對象屬性拷貝:
function pick(object) { var result = Object.create(null); // 創(chuàng)建一個對象 // 從第二個參數(shù)開始 for (var i = 1, len = arguments.length; i < len; i++) { result[arguments[i]] = object[arguments[i]]; } return result; } // arguments將object也計入,所以除開第一個參數(shù)要減1 var book = { title: "understanding ES6", author: "Nicholas C.Zakes", year: 2016 }; var o = pick(book, "author", "year"); o.author; // "Nicholas C.Zakes" o.year; // 2016
上面的pick函數(shù)看上去不夠直觀,因為除第一個參數(shù)外不知道要添加幾個參數(shù),使用新語法
function pick(object, ...keys) { var result = Object.create(null); // 創(chuàng)建一個對象 for (var i = 0, len = keys.length; i < len; i++) { result[keys[i]] = object[keys[i]]; } return result; } // keys將object不計入在其內(nèi) var book = { title: "understanding ES6", author: "Nicholas C.Zakes", year: 2016 }; var o = pick(book, "author", "year"); o.author; // "Nicholas C.Zakes" o.year; // 2016
使用rest parameters注意事項:
1.要將任意參數(shù)放到函數(shù)的最后,不能放在中間位置
2.不能用于對象字面量setter中
function pick(object, ...keys, last) { //... } // 語法錯誤 let object = { set name(...value) { // do something } }; // 語法錯誤3.spread操作符
spread操作符和rest parameters一樣,都使用 ... 表示,spread操作符允許我們將數(shù)組中的參數(shù)一個一個傳入函數(shù)中
例如:
// Math.max()函數(shù), 一般可以加入任意個參數(shù) Math.max(12, 13, 14, 15); // 15 // 以數(shù)組的形式 var arr = [1, 2, 3, 4]; Math.max.apply(null, arr); // 4 // 使用 "..." Math.max(...arr); // 4 // 還可以加入其它的一些參數(shù) Math.max(...arr, 5, 10); // 10
將一個數(shù)組去重:
var arr = [1, 2, 2, 4, 4]; // 使用Set將重復的去掉,然后將set對象轉(zhuǎn)變?yōu)閿?shù)組 var mySet = new Set(arr); // mySet {1, 2, 4} // 方法1,使用Array.from轉(zhuǎn)變?yōu)閿?shù)組 // var arr = Array.from(mySet); // [1, 2, 4] // 方法2,使用spread操作符 var arr = [...arr]; // [1, 2, 4] // 方法3, 傳統(tǒng)forEach var arr2 = []; mySet.forEach(v => arr2.push(v));4.new.target元屬性
????函數(shù)內(nèi)部有兩個方法 [[call]] 和 [[construct]] (箭頭函數(shù)沒有這個方法),當使用new 操作符時, 函數(shù)內(nèi)部調(diào)用 [[construct]], 創(chuàng)建一個新實例,this指向這個實例; 不使用new 操作符時, 函數(shù)內(nèi)部調(diào)用 [[call]]。
????判斷一個函數(shù)是否使用new操作符,ES5的方法:
function Person(name) { if (this instanceof Person) { this.name = name; } else { throw new Error("You must use new operator"); } } var p = new Person("James"); // ok var p = Person("James"); // error // 但是可以通過其他方式繞過這種錯誤 var notPerson = Person.call(p, "Nicholas"); // works
ES6 通過new.target 來判斷是否使用new,元屬性 是指一個提供目標相關額外信息(比如new)的非對象屬性。
function Person(name) { if (typeof new.target !== "undefined") { this.name = name; } else { throw new Errow("You must use new operator"); } } var p = new Person("James"); // ok var notPerson = Person.call(p, "Louis"); // error5.箭頭函數(shù)
箭頭函數(shù)有以下幾個方面的特點:
this, super, arguments和arguments的值由最近一個包含它的非箭頭函數(shù)定義。(No this, superm arguments and new.target bindings);
箭頭函數(shù)內(nèi)部沒有 [[construct]]方法, 因此不能當作構(gòu)造器,使用new操作符;
不存在原型(No prototype);
不能改變this, 在整個箭頭函數(shù)生命周期this值保持不變;
不存在arguments對象,不過包含它的函數(shù)存在,箭頭函數(shù)依靠命名參數(shù)和rest parameters;
不能擁有重復的命名參數(shù),ES5只有嚴格模式下才不允許
1.箭頭函數(shù)語法
// 語法很簡單 let sum = (n1, n2) => n1 + n2; // 相當于 let sum = function(n1, n2) { return n1 + n2; }; let getTempItem = id => ({ id: id, name: "Temp" }); // 相當于 let getTempItem = function(id) { return { id: id, name: "Temp" }; };
2.沒有this綁定
let PageHandler = { id: "123456", init: function() { document.addEventListener("click", function(event) { this.doSomething(event.type); // error }, false); }, doSomething: function(type) { console.log("Handling " + type + " for " + this.id); } }; // init函數(shù)中的this.doSomething,this指向的是函數(shù)內(nèi)部document對象, // 而不是PageHandler對象
使用箭頭函數(shù)改寫:
let PageHandler = { id: "123456", init: function() { document.addEventListener("click", event => this.doSomething(evnet.type) }, false); }, doSomething: function(type) { console.log("Handling " + type + " for " + this.id); } }; // 此處箭頭函數(shù)this指向包含它的函數(shù),即init,init為PageHandler的方法, // this指向PageHandler對象實例
3.不能使用new
var MyType = () => {}; var obj = new MyType(); // Error
4.沒有arguments對象
箭頭函數(shù)沒有arguments對象,但是可以使用包含函數(shù)中的arguments對象
function createArrowFunctionReturningFirstArg() { // arguments 為 createArrowFunctionReturningFirstArg中的對象 return () => arguments[0]; } var arrowFunction = createArrowFunctionReturningFirstArg(10); arrFunction(); // 106.其他(misllanceous)
其他的一些變化:
添加name屬性用來判斷函數(shù)名,用于調(diào)試;
規(guī)范塊級別函數(shù)(block-level functions),當執(zhí)行流結(jié)束塊級別函數(shù)退出,塊級別函數(shù)提升變量到塊頂部;
對尾部調(diào)用(Tail call, 值一個函數(shù)返回另一個函數(shù)對象)性能進行優(yōu)化,尤其是都遞歸函數(shù)性能提升很大
總結(jié)
ES6對默認參數(shù)的支持;
任意參數(shù)和spread操作符
箭頭函數(shù)
????總體來說,這些改動都是為編寫程序提供了極大的便利,不用再使用workaround來解決語法存在的問題,整體來講,更加符合語言的書寫習慣。
文章版權歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/90988.html
摘要:明確規(guī)定,如果區(qū)塊中存在和命令,這個區(qū)塊對這些命令聲明的變量,從一開始就形成了封閉作用域。凡是在聲明之前就使用這些變量,就會報錯。暫時性死區(qū)意味著不再是一個百分百的安全操作了不允許重復聲明不允許在相同作用域內(nèi),重復聲明同一個變量。 let,const共同擁有的特點 提供了代碼塊級作用域;(代碼塊是用{}來實現(xiàn)的) 不存在變量提升,先聲明再使用; 存在暫時性死區(qū); 不允許重復聲明; ...
摘要:箭頭函數(shù)沒有綁定,意味著箭頭函數(shù)內(nèi)部的值只能通過查找作用域鏈來確定。無論此后箭頭函數(shù)在何處執(zhí)行,該對象都是可用的。 箭頭函數(shù) es6的箭頭函數(shù),顧名思義箭頭函數(shù)是使用一個箭頭( => )來定義的函數(shù),這很容易理解但是它有很多行為與傳統(tǒng)的js函數(shù)不同: 沒有 this 、 super 、 arguments 。 不能被使用 new 調(diào)用: 箭頭函數(shù)沒有 [[Construct]] 方法...
摘要:外層作用域不報錯正常輸出塊級作用域與函數(shù)聲明規(guī)定,函數(shù)只能在頂層作用域和函數(shù)作用域之中聲明,不能在塊級作用域聲明。規(guī)定,塊級作用域之中,函數(shù)聲明語句的行為類似于,在塊級作用域之外不可引用。同時,函數(shù)聲明還會提升到所在的塊級作用域的頭部。 前言:最近開始看阮一峰老師的《ECMAScript 6 入門》(以下簡稱原...
摘要:年月,的創(chuàng)造者公司,決定將提交給國際標準化組織,希望這種語言能夠成為國際標準。這表示外層代碼塊不受內(nèi)層代碼塊的影響。也可以運用于函數(shù)及其他文中就簡單介紹這么多,想更加了解新特性的可以自尋查看一下阮一峰的一本入門 ES6新特性 最近在項目中遇到了很多ES6的語法,遇到了不少坑坑洼洼,因此,在這里就簡單介紹一下ES6中的一些新特性 如果想真正的了解ES6和ES5有什么不同,這里推薦看一下...
閱讀 2650·2023-04-26 02:17
閱讀 1628·2021-11-24 09:39
閱讀 1087·2021-11-18 13:13
閱讀 2670·2021-09-02 15:11
閱讀 2786·2019-08-30 15:48
閱讀 3416·2019-08-30 14:00
閱讀 2451·2019-08-29 13:43
閱讀 669·2019-08-29 13:07