2016-02-02 44 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