Function與封裝
預設值
ES5
此種做法有個缺點,當param1或param2傳入的值對應的boolean值為false時,此種設定就會失效,如:param1為空字串或false時,就會被轉型成false則程式就會使用1當作預設值而失去本來傳入參數的意義。
1 2 3 4 5 6 7 8 9
| function testParams (param1, param2) { param1 = param1 || 1 param2 = param2 || 2 console.log(param1) console.log(param2) } testParams(3, 5)
|
ES6
1 2 3 4 5 6
| function testParams (param1 = 1, param2 = 2) { console.log(param1) console.log(param2) } testParams(3, 5)
|
Arrow Function
ES5
1 2 3 4 5 6 7
| var hook = function (callback) { callback(5) } hook(function (value) { console.log(value) })
|
ES6
1 2 3 4 5 6 7
| let hook = (callback) => { callback(5) } hook((value) => { console.log(value) })
|
Arrow Function與IIFE
IIFE (Immediately Invoked Function Expression),稱為立即函示
表示立即執行宣告的函式,常用在把功能獨立的程式碼給包裹起來
減少全域變數數量,建立模組化物件
ES5的IIFE
1 2 3
| (function () { console.log(this.constructor.name) }())
|
ES5中透過IIFE全域變數變為區域變數
JQuery和JQuery plugins常用這種技巧來減少變數在全域的污染
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| (function ($) { $.fn.greenify = function(options) { var settings = $.extend({ color: "#556b2f", backgroundColor: "white" }, options) return this.css({ color: settings.color, backgroundColor: settings.backgroundColor }) } }(jQuery)) $("div").greenify({ color: "orange" })
|
利用IIFE函式物件當作模組
獨體模式 (Singleton Pattern)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| var Singleton = (function () { var instance function createInstance () { var object = new Object("I am the instance") return object } return { getInstance: function () { if (!instance) { instance = createInstance() } return instance } } })()
|
ES6中的IIFE
1 2 3
| (() => { console.log(this.constructor.name) })()
|
如果沒有要傳入的context有更簡短的寫法
1 2 3
| { console.log(this.constructor.name) }
|
需要指定的話
1 2 3
| ((context) => { console.log(context) })({a: 'a'})
|
Arrow Function對this的影響
ES5
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| var Printer = function () { console.log(this.constructor.name) this.print = function () { var array = ['a'] array.forEach(function (el) { console.log(this.constructor.name) }) } setTimeout(function () { console.log(this.constructor.name) }, 0) } var p = new Printer() p.print()
|
ES6 + Arrow Function
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class Printer { constructor () { console.log(this.constructor.name) setTimeout(() => console.log(this.constructor.name), 0) } print () { var array = ['a'] array.forEach((el) => { console.log(this.constructor.name) }) } } let p = new Printer() p.print()
|
箭頭函數當中的 this 是定義時的對象,而不是使用時的對象
資料封裝
問題: 當一個方法參數太多時怎麼處理?
ES5的例子
參數太長,程式碼不好維護,參數順序不容易記憶
1 2 3 4 5 6 7 8 9 10 11 12 13
| var longParamsMethod = function (param1, param2, param3, param4) { param1 = param1 || 'defaultParam1' param2 = param2 || 'defaultParam2' param3 = param3 || 'defaultParam3' param4 = param4 || 'defaultParam4' console.log(param1) console.log(param2) console.log(param3) console.log(param4) } longParamsMethod('a', 'b', 'c', 'd')
|
ES5 利用arguments
解決參數太長
1 2 3 4 5 6 7 8 9 10 11 12 13
| var longParamsMethod = function () { param1 = arguments[0] || 'defaultParam1' param2 = arguments[1] || 'defaultParam2' param3 = arguments[2] || 'defaultParam3' param4 = arguments[3] || 'defaultParam4' console.log(param1) console.log(param2) console.log(param3) console.log(param4) } longParamsMethod('a', 'b', 'c', 'd')
|
但使用者仍然要記得參數的順序,當參數太長依然不方便使用,何解?
回想前面JQuery的作法,傳入options
物件當參數的集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| (function ($) { $.fn.greenify = function(options) { var settings = $.extend({ color: "#556b2f", backgroundColor: "white" }, options) return this.css({ color: settings.color, backgroundColor: settings.backgroundColor }) } }(jQuery)) $("div").greenify({ color: "orange" })
|
ES6能帶來什麼好處?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| (function ($) { $.fn.greenify = function(options) { let {color, backgroundColor} = $.extend({ color: "#556b2f", backgroundColor: "white" }, options) return this.css({ color: color, backgroundColor: backgroundColor }) } }(jQuery)) $("div").greenify({ color: "orange" })
|
使用Object destruction配合function預設值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| (function ($) { $.fn.greenify = function({ color = '#556b2A', backgroundColor = 'white' }) { return this.css({ color: color, backgroundColor: backgroundColor }) } }(jQuery)) $("div").greenify({ color: "orange" })
|
補充 $.extend(destination, source)的mixins如何實現
兩個物件的mixins
1 2 3 4 5 6 7 8 9 10
| function mixin (dest, src) { for (var key in src) { dest[key] = src[key] } return dest } var mix = mixin({a: 'a'}, {b: 'b'}) console.log(mix)
|
多個物件mixins,模擬多重繼承
1 2 3 4 5 6 7 8 9 10 11 12
| function mixin (...objs) { return objs.reduce((dest, src) => { for (var key in src) { dest[key] = src[key] } return dest }) } var dest = mixin({}, {a: 'a'}, {b: 'b'}, {c: 'c'}) console.log(dest)
|