koa中context能夠直接調用request和response屬性的重要緣由是使用了delegate將req和res的屬性代理到context,api
Delegator.prototype.getter = function(name){ var proto = this.proto; var target = this.target; this.getters.push(name); proto.__defineGetter__(name, function(){ return this[target][name]; }); return this; }; /** * Delegator setter `name`. * * @param {String} name * @return {Delegator} self * @api public */ Delegator.prototype.setter = function(name){ var proto = this.proto; var target = this.target; this.setters.push(name); proto.__defineSetter__(name, function(val){ return this[target][name] = val; }); return this; };
其中最核心的是__defineGetter__和__defineSetter__koa
在對象定義後給對象添加getter或setter方法要經過兩個特殊的方法__defineGetter__和__defineSetter__。這兩個函數要求第一個是getter或setter的名稱,以string給出,第二個參數是做爲getter或setter的函數。函數
例如咱們給Date對象添加一個year屬性:this
Date.prototype.__defineGetter__('year', function() {return this.getFullYear();}); Date.prototype.__defineSetter__('year', function(y) {this.setFullYear(y)}); var now = new Date; alert(now.year); now.year = 2006; alert(now);
第二個地方是在初始化的時候:spa
function Delegator(proto, target) { if (!(this instanceof Delegator)) return new Delegator(proto, target); this.proto = proto; this.target = target; this.methods = []; this.getters = []; this.setters = []; this.fluents = []; }
將proto和target保存起來,而後咱們看到prototype
proto.__defineSetter__(name, function(val){ return this[target][name] = val; });
當使用set設置屬性的時候 其實是設置了target的屬性代理