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

Javascript:在给定对象问题中动态创建函数,javascript,function,scope,Javascript,Function,Scope,虽然这个问题以前有人问过,而且很多人已经回答了,但我的问题完全是关于新创建的函数的原型 如果你阅读了这段代码,你就会明白它是有效的。也在这里 //主对象 var Foo={}; //主要方法 Foo.render={};//要稍后填充的渲染函数 Foo.start=功能(el、ops){ 返回新动作(el、ops); } //辅助/实用功能 var动作=功能(el、ops){ this.el=document.querySelector(el); this.ops=ops |{}; this.

虽然这个问题以前有人问过,而且很多人已经回答了,但我的问题完全是关于新创建的函数的原型

如果你阅读了这段代码,你就会明白它是有效的。也在这里

//主对象
var Foo={};
//主要方法
Foo.render={};//要稍后填充的渲染函数
Foo.start=功能(el、ops){
返回新动作(el、ops);
}
//辅助/实用功能
var动作=功能(el、ops){
this.el=document.querySelector(el);
this.ops=ops |{};
this.prepare();//这将生成Foo.render函数
for(此.ops中的var p){
Foo.render[p](本);
}
}; 
//行动方法
Actions.prototype.prepare=函数(){
for(此.ops中的var p){
render[p]=函数(that){//或r[p]
that.el.style[p]=that.ops[p]+'px';
} 
}
}
//初始化
var action=newfoo.start('div',{left:15})
//检查
log(Foo.render['left'].prototype)

我想我找到了一种让它更好用的方法。下面应该可以,但是我仍然好奇是否有更好的解决方案

// 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
作为函数的第二个属性,比如so
Foo.render[p]=function(that,p){}
,我们开始:

//主对象
var Foo={};
//主要方法
Foo.render={};//要稍后填充的渲染函数
Foo.start=功能(el、ops){
返回新动作(el、ops);
}
//辅助/实用功能
var动作=功能(el、ops){
this.el=document.querySelector(el);
this.ops=ops |{};
this.prepare();//这将生成Foo.render函数
for(此.ops中的var p){
render[p](this,p);//我们在这里包括p
}
}; 
//行动方法
Actions.prototype.prepare=函数(){
for(此.ops中的var p){
render[p]=函数(that,p){//我们在这里也包括p
that.el.style[p]=that.ops[p]+'px';
}; 
}
};
//初始化
var action=newfoo.start('div',{left:15})
//检查
log(Foo.render['left'].prototype)

您需要在额外的闭包范围内捕获
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));
    } 
  }
};


所有函数的原型都是
函数.prototype
。这没什么错。你应该在这个循环中添加一个
if(!(Foo.render中的p))
,这样你就不会为每个新的
操作
实例重新创建函数。你似乎有足够的权限,但我真的看不出你想在这里做什么或为什么。@Bergi感谢你的宝贵评论和链接。我基本上是试图避免一个
Foo.render()
函数流30+
if
s,并用一个只包含真正需要的所有函数的漂亮对象来替换它。更少的代码,更高的性能模块化/可扩展性,通常是更优雅的解决方案。请看一下我下面的答案,似乎与您链接的检查答案很接近,您是否批准该答案,或者考虑到HTML4浏览器的支持,您是否知道更好的解决方案?我发现您试图避免使用
if
检查存在哪些属性。但是,在设置了多个
Foo.render[p]
函数之后,您仍然在
ops
上循环使用它们。我想知道为什么不简单地创建一个
render
方法,并将循环放在其中?除此之外,您的答案中的解决方案似乎很好(如“正确工作”,不一定是“精心设计”)。我希望您同意我编辑您的答案,而不是发布我自己的答案;如果没有,请随意回滚。我很高兴学习,请随意玩,谢谢:)我根据您的更改更新了我的代码,将
p
绑定到
(函数(p){})(p)
上下文不需要,正如
那样
是两个主要对象之间的链接,它似乎会稍微降低访问时间。绑定
p
是您首先添加闭包的原因,对吗?如果没有它,当您执行
新操作(…,{left:…,right:…})
时,调用
Foo.render.left(…)
将更新
right
属性。您可能是对的,但返回的函数体使用
p
,这是在用
p:“left”创建一个新的
Closure
对象
因此,您的绑定想法将创建一个额外的
闭包
,我不确定这是否好,我相信不是。在第二个版本中可能会有一些类型错误,但我将检查这两个,到目前为止,第一个似乎还可以。不管怎样,我都会记下你的问题,因为你太棒了。我需要一个
Foo.render[prop]=Foo.render[prop].prototype
或者一些东西来缩短这些函数的访问时间,因为
左边的
prototype
仍然是
Foo.render.(匿名函数)
,因此它似乎没有名称属性。@thednp:函数没有
name
属性对其速度没有任何影响现在,测试了您在所有情况下提供的两种解决方案,它们与您前面提到的所有其他解决方案都完全合理,如果不在上下文中绑定,它会混淆
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';
        };
      }
    }());
  }
}