首頁  >  文章  >  web前端  >  JavaScript裝飾者模式的功能和代理模式差異實例詳解

JavaScript裝飾者模式的功能和代理模式差異實例詳解

伊谢尔伦
伊谢尔伦原創
2017-07-24 14:36:012012瀏覽

裝飾著模式可以動態地為某個物件增加一些額外的職責,從而不影響這個類別中衍生的其他物件。 

裝飾著模式將一個物件嵌入另一個物件之中,實際上相當於這個物件被另一個物件包裝起來,形成一條包裝鏈。

不改動原函數的情況下,為函數增加一些額外的函數

1. 儲存原引用


window.onload = function() {
  console.log(1);
};

var _onload = window.onload || function() {};

window.onload = function() {
  _onload();
  console.log(2);
}

問題:
(1)必須維護中間變數
(2)可能遇到this被劫持問題
在window.onload的例子中沒有這個煩惱,是因為呼叫普通函數_onload時,this也指向window,跟呼叫window.onload時一樣。

2. this被劫持:


#
var _getElementById = document.getElementById;
document.getElementById = function(id) {
  console.log(1);
  return _getElementById(id);
}

return _getElementById(id); // 报错“Uncaught TypeError: Illegal invocation”

因為_getElementById是全域函數,當呼叫全域函數時,this是指向window的,而document.getElementById中this預期指向document。

3. 解決this被劫持:


#
var _getElementById = document.getElementById;
document.getElementById = function(id) {
  console.log(1);
  return _getElementById.call(document, id);
}

用AOP裝飾函數


/* 让新添加的函数在原函数之前执行(前置装饰)*/
Function.prototype.before = function(beforefn) {
  var _self = this;
  return function() {
    beforefn.apply(this, arguments);  // 新函数接收的参数会被原封不动的传入原函数
    return _self.apply(this, arguments);
  };
};


/* 让新添加的函数在原函数之后执行(后置装饰)*/
Function.prototype.after = function(afterfn) {
  var _self = this;
  return function() {
    var ret = _self.apply(this, arguments);
    afterfn.apply(this, arguments);
    return ret;
  };
};


#
document.getElementById = document.getElementById.before(function() {
  console.log(1);
});

##避免污染原型


##

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;
  };
};

document.getElementById = before(document.getElementById, function(){
  console.log(1);
});
裝飾者模式和代理模式


相同點:這兩種模式都描述了怎麼為物件提供一定程度上的間接引用,它們的實作部分都保留了對另外一個物件的引用,並且向那個物件發送請求。
區別:
(1)代理模式:當直接存取本地不方便或不符合需求時,為這個本體提供一個替代者。本地定義關鍵功能,而代理提供或拒絕對它的訪問,或在訪問本體之前走一些額外的事情。 (其做的事情還是跟本體一樣)

(2)裝飾者模式:為物件動態加入行為。 (一開始無法確定物件的全部功能,實實在在的為物件新增新的職責與行為)###

以上是JavaScript裝飾者模式的功能和代理模式差異實例詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn