2015-09-04 2 views
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"; 
//... 
+3

nope, вы не можете – Grundy

+0

Технически, вы могли бы, но было бы намного больше кода, что у вас здесь. Чтобы сделать это просто, я согласен с @Grundy. Вы не можете. – frosty

+0

@aaronfrost Что вы имеете в виду, определяя свойства сначала (до создания функции), а затем копируя их в объект функции позже? –

ответ

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, что позволило бы @ Pointy ответить на работу в старых браузерах.)

+0

В вашей петле вы должны проверить, что 'props.hasOwnProperty (key)' http://stackoverflow.com/a/921808/1913729 – blex

+0

Да, это будет работать с небольшим кодом. Я приму этот ответ, если нет лучших решений (производительности). – Martin

+1

@blex Я не думаю, что это необходимо в этом случае ... OP ничего не говорит о том, что объект 'props' будет экземпляром какого-то прототипа (т. Е. Что он унаследовал бы перечисляемые свойства). –

5

Если вы хотите сделать это с одной atement, ES2015 (и некоторые библиотеки) позволяют сделать:

var obj = Object.assign(
    function() { /* ... */ }, 
    { "hello": "world" } 
); 

Который даст вам obj как функция со свойством «привет». Обратите внимание, что это действительно только то же самое, как отдельное задания, но это все завернутые как одно общее выражение, что приятно, потому что это означает, что вы можете сделать что-то вроде

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

Да, это сработает, но мне нужно решение, которое также работает в IE8 – Martin

+0

Я думаю, что способ Мэтта Брауна был бы более результативным. – Martin

+0

Я согласен с @torazaburo ... либо его ответ, либо мой должны служить вам одинаково хорошо. Различия в производительности незначительны. Избегайте преждевременной оптимизации. –

0

Я также согласен с Гранди, но вы могли бы сделать что-то вроде этого:

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

честно, я не знаю, если это то, что вы действительно хотите, но в этом случае вы можете выполнить функцию «х» и после того, как вы можете получить доступ к «objFunction» , функция objToReturn или "addItemsToObject".

Так что это будет что-то вроде этого:

var y = x(); 

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

И потом:

y.objFunction(); 

'foo' 

Надежда, что помогает.