创建一个带属性的函数

3

抱歉,我不知道这个的名字。

我想要在一个变量中同时拥有函数和对象属性。

以下是它的工作原理:

var obj = function() {
    return "foo";
};

obj.prop = "bar";

obj(); // => "foo"
obj.prop; // => "bar"

这个可以正常运行,但我想修改这个的顺序:
var obj = { prop: "bar" };
obj = function() {
    return "foo";
};

obj(); // => "foo"
obj.prop; // => undefined

有没有方法可以做到这一点?

我想这样做是因为我有很多属性要添加到对象中:

var obj = function() {
    return "foo";
};

obj.prop1 = "bar1";
obj.prop2 = "bar2";
obj.prop3 = "bar3";
obj.prop4 = "bar4";
obj.prop5 = "bar5";
obj.prop6 = "bar6";
obj.prop7 = "bar7";
//...

从技术角度来说,你是可以的,但这会需要比你目前所拥有的更多的代码。为了简单起见,我同意@Grundy的观点。你做不到。 - frosty
@aaronfrost你的意思是先定义属性(在创建函数之前),然后将它们复制到函数对象中吗? - Matt Browne
@Martin 看看我更新后的答案(回答你更新后的问题)。 - Matt Browne
@torazaburo 你说得对,我本应该这样做,但就像你在另一个评论中所说的那样,这并不重要,因为我只想分配大约20个属性。 - Martin
嘿,别打架。 :-) - Martin
显示剩余3条评论
3个回答

6
这是不可能的,因为当您执行以下操作时:
obj = function() {
    return "foo";
};

当你将变量obj赋值给新函数时,它不再指向你创建的原始对象({ prop: "bar" })。

因此,如果您想向函数对象添加属性,必须先创建函数,然后再添加属性。

或者,您可以尝试以下方法:

var props = {
    prop1: "bar1",
    prop2: "bar2"
};

var obj = function() {
    return "foo";
};

for (var key in props) {
    obj[key] = props[key];  
}

如果您有jQuery可用(并且没有Object.assign),也可以这样写:
jQuery.extend(obj, props);

(当然,对于Object.assign,也有可用的shim,这将允许@Pointy的答案在旧版浏览器中工作。)

在你的循环中,你应该检查 props.hasOwnProperty(key)。https://dev59.com/pXNA5IYBdhLWcg3wh-cC#921808 - blex
是的,这个方案可以用很少的代码实现。如果没有更好的解决方案(性能),我会接受这个答案。 - Martin
1
@blex 我认为在这种情况下这并不是必要的... OP没有提到props对象是某个原型的实例(即它是否具有继承的可枚举属性)。 - Matt Browne
2
@Martin 谢谢...我可能错了,但我不认为你能让它比这个表现更好,除非Object.assign的本地实现(在较新的浏览器中可用)有一些内部性能优化...无论如何,我不会担心它 - 更好的是关注那些实际上有显著差异的性能而不是像循环几十个属性这样的小事情... - Matt Browne

5
如果您想用一条语句来完成此操作,ES2015(以及一些库)可以让您这样做:
var obj = Object.assign(
  function() { /* ... */ },
  { "hello": "world" }
);

这将会给你一个名为“hello”的属性的函数obj。请注意,这实际上只是与单独赋值相同的事情,但它被封装为一个整体表达式,这很好,因为这意味着你可以这样做:

return Object.assign(function() { /* whatever */ }, {
  prop: whatever,
  // ...
});

是的,这样可以工作,但我需要一个也能在IE8中运行的解决方案。 - Martin
我同意@torazaburo的观点...他的答案或者我的答案都能够很好地为您服务。性能差异微不足道。避免过早优化。 - Matt Browne
@MattBrowne 对的。虽然不是我的答案,但无论如何。 - user663031

0

我也同意Grundy的观点,但你可以这样做:

var x = function(){
var obj = {};
  return {
    objToReturn: obj,
    objFunction: function(){return 'foo';},
    addItemsToObject: function (key, value) {
      obj[decodeURIComponent(key)] = value;
    }
   }
};    

我真的不确定那是否是你真正想要的,但如果是这样,你可以执行“x”函数,然后访问“objFunction”,“objToReturn”或“addItemsToObject”函数。

所以它会像这样:

var y = x();

for (propertie in yourProperties){      
  y.addItemsToObject
    (propertie, yourProperties[decodeURIComponent(propertie)]);
}

然后:

y.objFunction();

'foo'

希望这有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接