2016-12-06 30 views
0

有一類對象需要在事實之後懶惰地添加一些函數作爲屬性。因爲這些函數必須引用實例變量才能將該函數配置爲屬性,所以我使用thunks創建函數並轉發第一個函數調用。爲一個簡化的例子:如何在JS中爲子對象屬性訪問調用一個thunk?

function Foo(val) { 
 
    this.val = val; 
 
} 
 

 
// simulates a library call which returns a complex object with methods 
 
// this library call requires access to some of the object information, 
 
// simulated by passing in `type` 
 
function buildWorkFunction(type) { 
 
    var f = function() { return this.val; }; 
 
    if (type === 'string') 
 
    f = function() { return this.val.length; }; 
 
    f.getType = function() { return type; }; 
 
    return f; 
 
} 
 

 
function addProperty(Base, prop) { 
 
    var thunk = function() { 
 
    // typeof is just a simple example of how buildWorkFunction could 
 
    // change based on this.val 
 
    this[prop] = buildWorkFunction(typeof this.val); 
 
    return this[prop].apply(this, arguments); 
 
    }; 
 
    thunk.getType = function() { 
 
    return 'TODO'; // <-- this is the part I need help with 
 
    }; 
 
    Base.prototype[prop] = thunk; 
 
} 
 

 
// simulates instances existing before the module load 
 
var foo = new Foo('foo'); 
 

 
// runs after user requests a module load, runs from the module 
 
setTimeout(function() { 
 
    // adding a module specific property to the non-module model 
 
    addProperty(Foo, 'getVal'); 
 

 
    console.log(foo.getVal()); 
 
    console.log(foo.getVal.getType()); 
 

 
    // simulates instances created after the module load 
 
    var bar = new Foo(17); 
 
    console.log(bar.getVal.getType()); // called before thunk - fails 
 
    console.log(bar.getVal()); 
 
    console.log(bar.getVal.getType()); // called after thunk - works 
 
}, 0);
我已經離開

的一個問題是該屬性的值本身具有的性質的應用程序代碼有時引用而不調用的屬性本身,與上述f.getType。如何在沒有先撥打foo.getVal()的情況下正確接收/代理/轉發諸如foo.getVal.getType()的呼叫?附加屬性的名稱已定義好,可以共享 - 但我看不到如何訪問正確的this或來自它們的數據。

+0

我不明白你爲什麼這些功能都需要偷懶的thunk,但我也有什麼不明白這跟'getType'做。即使該方法不是懶惰的,該「方法的方法」也不起作用。 – Bergi

+0

在這種情況下,他們沒有。在應用程序中,它們在用戶加載模塊並完成網絡呼叫後添加。 'getType'方法模擬從生成屬性的庫中提供排序和其他功能的方法。 – Iiridayn

+0

所以你說的thunk加載模塊,然後提供真正的實現?有趣... – Bergi

回答

1

如何正確捕獲/代理呼叫,如foo.getVal.getType()?如果foo.getVal()未先被調用,我看不到如何從它們訪問正確的數據或數據。

您可以使用與您已經做過的相同的方法,但是在屬性getter級別而不是方法調用級別。這使得可以懶洋洋地創建任意實例屬性:

function addProperty(Base, prop) { 
    Object.defineProperty(Base.prototype, prop, { 
    get: function thunk() { 
     var propertyValue = buildWorkFunction(typeof this.val); 
     //         ^^^^^^^^^^^^^^^ access the instance here 
     // overwrite (shadow) the prototype getter: 
     Object.defineProperty(this, prop, { 
     value: propertyValue, 
     writable: true, 
     enumerable: true, 
     configurable: true 
     }); 
     return this[prop]; 
    }, 
    enumerable: true, // dunno 
    configurable: true 
    }); 
}