2016-02-02 46 views
2

雖然這個問題之前已經有人問過,而且很多人已經回答了,但我的問題嚴格的是關於新創建函數的原型。Javascript:在給定對象中動態創建的函數問題

如果你閱讀這段代碼,你會明白它的工作原理。也在這裏codepen

// main object 
 
    var Foo = {}; 
 

 
    // main methods 
 
    Foo.render = {}; // the Render function to populate later 
 

 
    Foo.start = function(el,ops){ 
 
     return new Actions(el,ops); 
 
    } 
 

 
    // secondary/utility functions 
 
    var Actions = function(el,ops){ 
 
     this.el = document.querySelector(el); 
 
     this.ops = ops || {}; 
 
     this.prepare(); // this builds the Foo.render functions 
 
     for (var p in this.ops){ 
 
     Foo.render[p](this); 
 
     } 
 
    }; 
 

 

 
    // Action methods 
 
    Actions.prototype.prepare = function(){ 
 
     for (var p in this.ops) { 
 
     Foo.render[p] = function(that){ // or r[p] 
 
      that.el.style[p] = that.ops[p] + 'px'; 
 
     } 
 
     } 
 
    } 
 

 
    // init 
 
    var action = new Foo.start('div',{left:15}) 
 

 
    // check 
 
    console.log(Foo.render['left'].prototype);
<div></div>

的問題是新創建的功能Foo.render['left']的原型是這樣Foo.render.(anonymous function) {}而不是像Foo.render.left() {}或別的東西,和我遇到一些性能損失,因爲我無力非常快地訪問新創建的函數的原型。

任何人都可以請介紹一下如何在Foo範圍內調整.prepare()函數以創建準確/可訪問(我無法選擇正確的單詞)原型函數嗎?

謝謝。

+0

所有功能確實有'Function.prototype'作爲其prototoype。這沒什麼錯。 – Bergi

+0

您應該在該循環中添加一個'if(!(p in Foo.render))',這樣您就不會爲每個新的'Actions'實例重新創建函數。 – Bergi

+0

您似乎有[循環問題中的標準閉包](http://stackoverflow.com/q/750486/1048572),但我無法真正看到你想在這裏做什麼或爲什麼。 – Bergi

回答

1

您需要在額外的閉包範圍內捕獲p的值。此外,我會建議避免覆蓋已有的方法。

Actions.prototype.prepare = function() { 
    for (var p in this.ops) { 
    if (!(p in Foo.render)) { 
     Foo.render[p] = (function(prop) { 
     return function(that) { 
      that.el.style[prop] = that.ops[prop] + 'px'; 
     }; 
     }(p)); 
    } 
    } 
}; 

Actions.prototype.prepare = function() { 
    for (var p in this.ops) { 
    (function() { 
     var prop = p; 
     if (!(prop in Foo.render)) { 
     Foo.render[prop] = function(that) { 
      that.el.style[prop] = that.ops[prop] + 'px'; 
     }; 
     } 
    }()); 
    } 
} 
+0

在第二個版本中可能會出現一些類型錯誤,但我會檢查兩者,到目前爲止首先看起來沒問題。無論如何,我會標記你的問題,因爲你太棒了。 – thednp

+0

我需要一個'Foo.render [prop] = Foo.render [prop] .prototype'或其他的東西來改善這些函數的訪問時間,因爲'left.prototype'仍然是'Foo.render。(匿名函數)',所以它似乎沒有名稱屬性。 – thednp

+1

@thednp:沒有'name'屬性的函數對它的速度沒有任何影響 – Bergi

0

我想我找到了一種讓它工作得更好的方法。下面應該做,但我仍然很想知道是否有更好的解決方案。

// main object 
var Foo = {}; 

// main methods 
Foo.render = {}; // the Render function to populate later 

Foo.start = function(el,ops){ 
    return new Actions(el,ops); 
} 

// secondary/utility functions 
var Actions = function(el,ops){ 
    this.el = document.querySelector(el); 
    this.ops = ops || {}; 
    this.prepare(); // this builds the Foo.render functions 
    for (var p in this.ops){ 
    Foo.render[p](this); 
    } 
}; 


// Action methods 
Actions.prototype.prepare = function(){ 
    for (var p in this.ops) { 
     Foo.render[p] = (function(){ // or r[p] 
     return function(that){ 
      that.el.style[p] = that.ops[p] + 'px'; 
     } 
     })(); 
    } 
}; 

// init 
var action = new Foo.start('div',{left:15}) 

// check 
console.log(Foo.render['left'].prototype); 

更新:我想我找到了一種方法來消除封閉的一個,基本上都採用了p作爲函數的第二個屬性,像這樣Foo.render[p] = function(that,p){}在這裏我們去:

// main object 
 
var Foo = {}; 
 

 
// main methods 
 
Foo.render = {}; // the Render function to populate later 
 

 
Foo.start = function(el,ops){ 
 
    return new Actions(el,ops); 
 
} 
 

 
// secondary/utility functions 
 
var Actions = function(el,ops){ 
 
    this.el = document.querySelector(el); 
 
    this.ops = ops || {}; 
 
    this.prepare(); // this builds the Foo.render functions 
 
    for (var p in this.ops){ 
 
    Foo.render[p](this,p); // we include p here 
 
    } 
 
}; 
 

 

 
// Action methods 
 
Actions.prototype.prepare = function(){ 
 
    for (var p in this.ops) { 
 
     Foo.render[p] = function(that,p){ // we also include p here 
 
     that.el.style[p] = that.ops[p] + 'px'; 
 
     }; 
 
    } 
 
}; 
 

 
// init 
 
var action = new Foo.start('div',{left:15}) 
 

 
// check 
 
console.log(Foo.render['left'].prototype);
<div></div>

這消除了額外的閉包,並使函數更接近主線程的範圍。歡迎對此更新發表任何評論。

+0

我希望你能和我一起編輯你的答案,而不是張貼我自己的;如果沒有,請隨時將它回滾 – Bergi

+0

我很高興學習,請隨時參加並感謝您:) – thednp

+0

我根據您的更改更新了代碼,將'p'綁定到'(function(p) {})(p)'上下文是不需要的,因爲'that'是兩個主要對象之間的鏈接,並且它似乎稍微減慢了訪問時間。 – thednp