2013-04-20 3 views
0

Рассмотрим следующий примерпрототипирования с Javascript Конструкторы

Вопрос

В bar, как я могу получить переменную fooInstance? Есть ли способ для ребенка из Foo распознать его родителя как fooInstance? Например, как я могу создать функцию в bar, которая вернет fooInstance. Небольшой оговоркой является то, что бар должен быть создан с помощью команды prototype и не может быть просто вложен в Foo для доступа к любым Foo экземплярам таким образом.

Мои идеи и почему они не работают

можно было бы переписать такие функции, как так

var Foo = function(){ 
    this.identity = 'Foo'; 
}; 
Foo.prototype.createBar = function(){ 
    var parent = this; 
    function bar(){ 
     this.parent = parent; 
     this.identity = 'bar'; 
    }; 
    return new bar(); 
}; 
var fooInstance = new Foo(), 
    bar = fooInstance.createBar(); 

Однако для целей создания легко читаемого кода я предпочел бы не использовать этот подход, если не нужен.

Далее Разъяснение

Позвольте мне поставить вопрос в контексте. Я прототипируюсь на CanvasRenderingContext2D, так что все контексты для элемента canvas будут содержать мой новый метод. Давайте назовем этот метод foo и предположим, что контекст - это созданный контекст холста. Как создать переменную типа «new context.foo()» так, чтобы функция foo могла использовать переменную контекста?

+1

Что такое 'fooInstance'? Что такое «дети» и «родители» от «Foo»? Что это за метод 'bar', который вы вызываете, но не определяете? Что вы подразумеваете под «командой прототипов»? – Bergi

+0

Btw, [этот ответ] (http://stackoverflow.com/questions/13418669/javascript-do-i-need-to-put-this-var-for-every-variable-in-an-object/13418980# 13418980) может помочь вам понять различия между переменными и свойствами. – Bergi

+0

Позвольте мне задать вопрос в контексте. Я прототипируюсь на CanvasRenderingContext2D, так что все контексты для элемента canvas будут содержать мой новый метод. Давайте назовем этот метод foo и предположим, что контекст - это созданный контекст холста. Как создать переменную типа «new context.foo()» так, чтобы функция foo могла использовать переменную контекста? –

ответ

1

, как я мог бы создать функцию в баре, который будет возвращать fooInstance

Если эта функция вызывается как конструктор (с new), вы не можете это сделать. this keyword, единственная ссылка на «родительский» (объект, на который вы вызвали метод), устанавливается в новый экземпляр при вызове конструктора.Вы можете получить ссылку только с закрытием, например, создав конструктор в функции конструктора родителя (который не работает для вас) или вернув конструктор из закрытия на прототипе (который вы почти получили во втором примере):

Foo.prototype.getBarCoonstructor = function() { 
    var parentFoo = this; 
    return function Bar() { 
     // constructor things 
     // using "parentFoo" reference 
    }; 
}; 
// Usage: 
var bar = new (foo.getBarConstructor())(); // ugly. 

Вместо того, чтобы создавать новые конструкторы для каждого вызова getBarConstructor, то лучше должен поставить его вне метода и поставить parentFoo в качестве аргумента к нему. Ваша идея была уже неплохой.

function Bar(parent) { 
    // constructor things, referring "parent" 
} 
Bar.prototype.… = …; 

Foo.prototype.createBar = function() { 
    return new Bar(this); // passing the Foo instance 
}; 

(@plalx имеет такое же решение, но завернутые в затворе модуля)

+0

Спасибо, я думаю, проблема в том, что «это» является единственной восходящей связью между функциями и что использование конструктора эффективно удаляет ее. Это один из тех моментов, когда javascript расстраивает меня. –

0

Foo.prototype.bar - просто функция на прототипе объекта Foo. Для этой функции нет возможности знать ее «родительский», если вы явно не определяете ее в своей цепочке видимости.

I.e. если вы сделали бы

var Foo = function(){ 
    this.identity = 'Foo'; 
}; 
var fooInstance = new Foo(); 

Foo.prototype.bar = function(){ 
    console.log(fooInstance); // retrieve from scope 
    this.identity = 'bar'; 
}; 
bar = new foo.bar(); 

это будет работать.

+0

Да, но как только я создал более одного fooInstance, этот метод сломался. Код должен быть динамическим. Каждый fooInstance уникален, и каждый экземпляр бара должен иметь возможность получить его уникальный родитель. –

2

Если вам нужно ссылаться на fooInstance объект из bar объекта, вы можете использовать инъекции зависимостей, как это:

Foo.prototype.bar = function(fooInstance) { 
    this.identity = 'bar'; 
    this.fooInstance = fooInstance; 
}; 

var fooInstance = new Foo(), 
    bar = new foo.bar(fooInstance); 

Вы могли бы упростить процесс создания путем реализации функции заводскую на Foo.

Foo.prototype.createBar = (function() { 
    function Bar(parent){ 
     this.parent = parent; 
     this.identity = 'bar'; 
    }; 

    return function() { 
     return new Bar(this); 
    }; 
})(); 

var fooInstance = new Foo(), 
    bar = fooInstance.createBar(); 
+0

Это и моя идея, но я разрабатываю API и считаю это громоздким для использования в качестве пользователя. Однако, в то время как фабричный метод устраняет раздражающую необходимость передавать аргументы, в моей программе логически имеет смысл использовать новый префикс, и я предпочел бы сохранить логические для пользователей. Возможно ли, чтобы под-метод получал исходный объект динамически? Обычно привязки и использование этого могут выполняться именно так, но из-за природы конструктора, который здесь не применяется ... Есть ли другой способ? –