在傳統的物件導向語言中,為物件添加功能常常使用繼承的方式,但繼承的方式會帶來問題:當父類別改變時,他的所有子類別都會隨之改變。
當JavaScript腳本運行時,在一個物件中(或他的原型上)增加行為會影響該物件的所有實例,
裝飾者是一種實現繼承的替代方案,它透過重載方法的形式添加新功能,該模式可以在被裝飾者前面(before)或後面(after)加上自己的行為以達到特定的目的。
裝飾者模式是為已有功能動態地添加更多功能的一種方式,把每個要裝飾的功能放在單獨的函數裡,然後用該函數包裝所要裝飾的已有函數對象,因此,當需要執行特殊行為的時候,呼叫程式碼就可以根據需要選擇性地、依序地使用裝飾功能來包裝物件。優點是把類別(函數)的核心職責和裝飾功能區分開了。
我們可以定義工具函數,如下:
Function.prototype.before = function (beforeFn) { var self = this; //保存原函数的引用 return function () { //返回包含了新函数和原函数的代理函数 beforeFn.apply(this,arguments); //执行新函数,且保证this不被劫持 return self.apply(this,arguments); //执行原函数,并返回原函数的执行结果,并保证this不被劫持 } }; Function.prototype.after = function (afterFn) { var self = this; return function () { var ret = self.apply(this,arguments); afterFn.apply(this,arguments); return ret; } };
這裡的參數beforeFn、afterFn即為要為原始函數擴展新功能的新函數(添加裝飾),它們的唯一區別是執行順序的不同。如果不想污染Function的原型,可以用下面的方法:
var before = function (fn, beforeFn) { return function () { beforeFn.apply(this,arguments); return fn.apply(this,arguments); } }; var after = function (fn, afterFn) { return function () { var ret = fn.apply(this,arguments); afterFn.apply(this,arguments); return ret; } };
例子:給HTTP請求中帶上一個參數來防止CSRF攻擊
var ajax = function (type, url, param) { console.log(param); //发送ajax请求代码略... }; var beforeFn = function (type, url, param) { param.Token = 'Token'; }; ajax = ajax.before(beforeFn); ajax('get','http://...com/userinfo',{name:'SuFa'}); //{ name: 'SuFa', Token: 'Token' }
透過給ajax函數動態裝飾上Token參數,而不是直接在原函數上修改參數,保證了ajax函數仍然是一個純淨的函數,提高了它的可復用性,它可在無需做任何修改的情況下直接拿到別的項目中使用。
範例:表單驗證(把驗證輸入和表單提交的程式碼分開離開來,然後動態的把驗證輸入功能裝飾到表單提交之前,這樣一來,我們就可以把驗證輸入部分寫成一個插件的形式,用在不同的項目)
//验证输入函数 var validata = function () { if(username.value === ''){ alert('用户名不能为空'); return false; } if(password.value === ''){ alert('密码不能为空'); return false; } }; //表单提交函数 var formSubmit = function () { var param = { username: username.value, password: password.value }; ajax('http://xxx.com/login',param); }; formSubmit = formSubmit.before(validata); submitBtn.onclick = function(){ formSubmit(); };
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持PHP中文網。
更多JavaScript裝飾者模式相關文章請關注PHP中文網!