Javascript:在给定的对象问题中动态创建函数

时间:2016-02-02 20:29:32

标签: javascript function scope

虽然之前已经提出过这个问题而且很多人已经回答了这个问题,但我的问题是严格关于新创建函数的原型。

如果您阅读了这段代码,您就会明白它只是有效。同样在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() {}或类似的东西,我遇到了一些性能损失,因为我是无法快速访问新创建的函数原型。

有人可以说明如何调整.prepare()函数以在Foo范围内创建准确/可访问(我无法选择正确的单词)原型函数吗?

谢谢。

2 个答案:

答案 0 :(得分: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';
        };
      }
    }());
  }
}

答案 1 :(得分: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>

这消除了额外的闭包,使函数更接近主线程的范围。欢迎对此更新发表任何评论。