function a(){ alert('A'); a = function(){ alert('B'); }; } function a(){ alert('A'); return function(){ alert('B'); }; }
該函數在第一次被呼叫後重寫自己,從而避免了每次呼叫時重複一些不必要的操作。這個具體怎麼理解呢?重寫函數前後函數執行緒不是一樣嗎?
舉個例子,不同瀏覽器有的API的名稱是不一樣的,然後你要封裝一個統一的接口,那你的程式碼就差不多是這樣
function fn(){ if(chrome){ fn = function(){}; }else if(firefox){ fn = function(){}; } fn(); }
在不使用額外變數的情況下,不使用if-else的情況下,區分了一個布林型的狀態。 例如有些行為,在初始化和未初始化的情況下邏輯不一樣,那麼可以這麼寫:
var initiated = false function action () { if (initiated) { // action 1 } else { // action 2 initiated = true } }
這裡很糟糕的,引入了全域變量,那可以將這個變數封裝在成一個內部狀態,可以這麼寫:
class Action { constructor () { this.initiated = false this._init() } _init () { // action 2 this.initiated = true } action () { // action 1 } } var myAction = new Action() myAction.action()
如果使用題主所說的方法的話:
function action () { // action 2 return function () { // action 1 } } var myAction = action() myAction()
另外,這樣的寫法感覺很函數式(個人對函數式了解不多,不敢絕對)。那麼這裡就是程式設計範式的問題了。 感受一下以下三種不同的寫法:
面向過程:
function logger (type, content) { var now = new Date() if (type === 'debug') { console.log('DEBUG::' + now + ' ' + content) } else if (type === 'info') { console.log('INFO::' + now + ' ' + content) } } logger('debug', 'xxx') logger('info', 'xxx')
面向對象:
class Logger { _now () { return new Date() } debug (content) { console.log('DEBUG::' + this._now() + ' ' + content) } info (content) { var now = new Date() console.log('INFO::' + this._now() + ' ' + content) } } var logger = new Logger() logger.debug('xxx') logger.info('xxx')
函數式:
function logger (type) { var prefix = '' if (type === 'debug') { prefix = 'DEBUG' } else if (type === 'info') { prefix = 'INFO' } return function (content) { var now = new Date() console.log(prefix + '::' + now + ' ' + content) } } var debugLogger = logger('debug') var infoLogger = logger('info') debugLogger('xxxx') infoLogger('xxxx')
那函數式的方法,是有很多自己的優點的,這個你要去了解函數式程式設計。
樓上那個瀏覽器API的例子是個很好的例子,總的來說,函數重寫更多的是為了規避某些不必要的操作,從而達到優化代碼性能的目的, 我再給你舉個更常用的:
//就比如说我们经常要通过addEventListener来绑定事件,但是在某些老版本浏览器可能用的是attachEvent和on,这时我们可以: var bindEvent = function(target,event,handle){ //下面就是针对性的重写 if(target.addEventListener){ bindEvent = function(target,event,handle){ target.addEventListener(event,handle,false); }; } else if( target.attachEvent ){ bindEvent = function(target,event,handle){ target.attachEvent("on"+event,handle); }; } else { bindEvent = function(target,event,handle){ target["on"+event] = handle; }; } bindEvent(target,event,handle); };
簡單來說
第一次執行a函數時執行的是alert('A'),第二次執行的是alert('B')。
與其說是避免重複不必要的操作,不如說是做了另外的操作。第一次運行時乾了A這件事,後面運行時幹的都是B這件事。
舉個例子,不同瀏覽器有的API的名稱是不一樣的,然後你要封裝一個統一的接口,那你的程式碼就差不多是這樣
在不使用額外變數的情況下,不使用if-else的情況下,區分了一個布林型的狀態。
例如有些行為,在初始化和未初始化的情況下邏輯不一樣,那麼可以這麼寫:
這裡很糟糕的,引入了全域變量,那可以將這個變數封裝在成一個內部狀態,可以這麼寫:
如果使用題主所說的方法的話:
另外,這樣的寫法感覺很函數式(個人對函數式了解不多,不敢絕對)。那麼這裡就是程式設計範式的問題了。
感受一下以下三種不同的寫法:
面向過程:
面向對象:
函數式:
那函數式的方法,是有很多自己的優點的,這個你要去了解函數式程式設計。
樓上那個瀏覽器API的例子是個很好的例子,總的來說,函數重寫更多的是為了規避某些不必要的操作,從而達到優化代碼性能的目的, 我再給你舉個更常用的:
簡單來說
第一次執行a函數時執行的是alert('A'),第二次執行的是alert('B')。
與其說是避免重複不必要的操作,不如說是做了另外的操作。第一次運行時乾了A這件事,後面運行時幹的都是B這件事。