2012-04-03 2 views
1

Я пытаюсь создать функцию, которая будет принимать аргументы arg1, arg2..., а затем передать их в конструктор для нового объекта C так: new C(arg1, arg2...), поэтому для создания нового экземпляра C пользователю просто нужно будет позвоните по номеру C(arg) вместо new C(arg). Вот моя первая попытка:Программно создайте новый объект

var C = function(a){ this.a = a; } 

var Cn = function(){ 
    new C.apply(this, arguments); 
} 

Cn(0)  // Should make a new C with a property a equal to 0 
new C(0) // ie the same as this 

Edit: Обратите внимание, мне нужно, чтобы принимать произвольное число аргументов и не использовать Eval. Я делаю библиотеку, реализующую Algebraic Data Types в js.


Edit: Решение было принять Jeremy's Idea и адаптировать его принять неограниченное число аргументов:

var C = function() { 

    // A unique object so we can identify when we used the 'newless' constructor 
    var newlessConstructorObj = {} 

    // Check to see if C has been called with `new` 
    if(!(this instanceof C)) 
     // If not pass arguments as single arg back to C 
     return new C(newlessConstructorObj, arguments); 


    // Check to see if we got here from the line above, if so the arguments were passed in the second arg 
    var args = (arguments[0] === newlessConstructorObj) ? arguments[1] : arguments 

    // Do stuff with args 
    this.a = args[0]; 
} 

C(0); 
new C(0); 

ответ

2

Если вы хотите, чтобы иметь возможность вызвать функцию с или без нового ключевого слова, вы должны следовать этой схеме:

C = function(a) { 
    if (!(this instanceof C)) { 
    return new C(a); 
    } 

    this.a = a; 
} 

так, чтобы создать новый экземпляр «C»:

c = new C(a); 

и

c = C(a); 

оба возвращают правильно сформированный экземпляр с

+1

+1: кажется, хорошая адаптация одноэлементного рисунка ... правильно? – fcalderan

+0

Это выглядит очень красиво и решает одну из моих других проблем (это 'C'! =' Cn'). Я посмотрю, смогу ли я изменить свой код, чтобы работать так. –

+0

приятно, но он не передает аргументы. – c69

1

что-то вроде этого?

var C = function(obj){ 
    var a; 
    for (a in obj) { 
    this[a] = obj[a]; 
    } 
} 
var Cn = function(obj) { return new C(obj); } 

instance = Cn({ 
    a : 1, 
    b : 2 
}) 

instance.a //1 
instance.b //2 
instance.c //undefined 
+0

я думаю, что его не то, что ОП хочет .. – c69

+0

Это работает, но я думаю, ОП хотел напечатать меньше, а не больше. Рассмотрим замену объекта на массив (так как имена не нужны в любом случае). – RobG

+0

Я просто расширил пример, возвратив экземпляр объекта и сгруппировав все аргументы в качестве значений хэш-таблицы. – fcalderan

1

Если вы не заботитесь о том, правильно instanceof проверить, вы можете попробовать это:

var C = function(a){ this.a = a; } 

var Cn = function(){ 
    return C.apply({}, arguments); // notice an empty object here 
} 

Cn(0)  // Should make a new C with a property a equal to 0 
new C(0) // ie the same as this 
+0

Ошибка при запуске: «C.apply» не является конструктором – c69

+0

@ c69: Извините, забыл изменить новое, чтобы возвратить – qwertymk

+0

@ c69: Попробуйте сейчас. – qwertymk

1

Действовать с фиксированным количеством аргументов проста:

// assuming one arg 
function Cn(arg) { 
    return new C(arg); 
} 

// assuming two args 
function Cn(arg0, arg1) { 
    return new C(arg0, arg1); 
} 

и скоро. Вы даже можете сделать общую версию для любого количества параметров, итерации более аргументов для создания строки, затем eval. Crass, но эффективный.

Но в чем смысл? Просто чтобы сохранить ввод 4 символов?

+0

Ах, должно быть, это было мне нужно для общего количества аргументов и без использования 'eval'. Что касается причины, я пытаюсь создать функциональную библиотеку программирования для js, и мне нужно это реализовать [Алгебраические типы данных] (http://en.wikipedia.org/wiki/Algebraic_data_type). –

2

я бы выбрал решение Фабрицио Calderan в любой день, а потому, что вы хотите эту конкретную функциональность - вот что предшественники говорят нам:


можно применить аргументы prototype.constructor (но есть вопросы, когда делают это с нативные типы, такие как номер):

var Cn = function(){ 
    return C.prototype.constructor.apply(C, arguments); 
} 

Ссылка: Instantiating a JavaScript object by calling prototype.constructor.apply


или ..использовать eval:

function construct(Constructor) 
{ 
/* 
    * or Array.prototype.slice.call(arguments, 1).map(function() { ... }) 
    * in JavaScript 1.6+, compatibles, and with augmented Array.prototype 
    */ 
var args = []; 
for (var i = 1, len = arguments.length; i < len; i++) 
{ 
    args[i - 1] = "arguments[" + i + "]"; 
} 

/* or args.join(", ") if you need it pretty-printed */ 
return eval("new Constructor(" + args + ")"); 
} 

function Foo() 
{ 
    window.alert(Array.prototype.slice.call(arguments, 0).join(", ")); 
} 

var f = construct(Foo, /bar/g, {baz: 42}); 

Ссылка: http://groups.google.com/group/comp.lang.javascript/browse_thread/thread/ff1a104bdc33d5c8

+2

Я играл с 'prototype.constructor', прежде чем задал вопрос - в chrome' C.prototype.constructor.call (C, 0) 'возвращает' undefined'. –