2010-08-24 4 views
16

у меня есть «класс» Javascript определяется следующим образом:Могу ли я «расширить» класс, определенный закрытием, в Javascript?

var Welcomer = function(name) { 
    var pName = name; 
    var pMessage = function() { 
    return "Hi, " + pName + "!"; 
    }; 

    return { 
    sayHi: function() { 
     alert(pMessage()); 
    } 
    }; 
}; 

new Welcomer('Sue').sayHi(); 

Есть ли способ «подкласс» Welcomer таким образом, что я могу переопределить открытые методы и иметь доступ к частным методам и переменным? Следующий даст мне доступ к публичным методам, но не в частных:

var UnhappyWelcomer = function(name) { 
    var pSadMessage = function() { 
    // won't work, b/c I don't have access to pMessage 
    return pMessage() + " Miserable day, innit?"; 
    }; 

    return { 
    sayHi: function() { 
     alert(pSadMessage()); 
    } 
    }; 
}; 
UnhappyWelcomer.prototype = Welcomer(); // failed attempt at inheritance 

new UnhappyWelcomer().sayHi(); 
+1

Возможно, вы захотите прочитать [эту статью] (http://mckoss.com/jscript/object.htm). –

+0

Закладка этой статьи. Thx –

ответ

10

Простой ответ на ваш вопрос: No.

Вы не можете ничего сделать, чтобы получить доступ к тем var определенным вещам, если только ваша функция не находится в том же объеме, или вы каким-либо образом публикуете эту информацию (возвращая ее или устанавливая ее на this).

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

var Welcomer = function(name) { 
    var _protected = { 
    name: name, 
    message: function() { 
     return "Hi, " + _protected.name + "!"; 
    } 
    }; 

    return { 
    extendWith: function(extender) { 
     extender.call(this, _protected); 
     return this; 
    }, 
    sayHi: function() { 
     alert(_protected.message()); 
    } 
    }; 
}; 

var UnhappyWelcomer = function(name) { 
    var self = Welcomer(name).extendWith(function(_protected) { 
    _protected.sadMessage = function() { 
     return _protected.message() + " Miserable day, innit?"; 
    }; 
    // extending the public while still having scope to _protected... 
    this.sayHi = function() { 
     alert(_protected.sadMessage()); 
    }; 
    }); 
    return self; 
}; 

UnhappyWelcomer('bob').sayHi(); 
+0

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

+0

Хотелось бы добавить, что это ОЧЕНЬ расточительно «пространства» пространства ... – gnarf

1

Если вам действительно нужно наследование, есть некоторые библиотеки там, которые помогут безмерно. Один из вариантов - trait.js, который в любом случае может стать стандартной частью javascript. Если это не плавает на вашей лодке, библиотеки, такие как jQuery и прототип, имеют помощники для наследования.

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

Чтобы более прямо обращаться к вашему вопросу, нет. У вас будет более легкое время, если вы создадите свои «классы», поэтому частные функции не понадобятся.

+0

Я попробовал 'return jQuery.extend ({}, Welcomer(), {sayHi: function() {alert (pSadMessage());});', но 'extend', по-видимому, копирует только элементы, определенные в объектном литерале (публичные методы), а не закрытие. –

+0

Да, как вы разработали свой «класс» с частными параметрами var/functions, определенными в конструкторе, они просто будут видны, поэтому я обязательно перейду к более стандартной структуре на основе прототипов. – jdc0589

9

Это «класс» модель не является «класс» шаблон, он известен как Module Pattern. Он возвращает объект, который не связан с функцией, создавшей ее, а затем доступность ее частных переменных. Возвращаемый объект НЕ является экземпляром функции, которая его создала.

Когда вы вызываете «новый класс()», он создает экземпляр этой функции, но также возвращает другой объект. Любые дальнейшие операции на самом деле находятся на возвращенном объекте, а не на экземпляре.

Для того, чтобы использовать наследование, вам действительно нужно использовать прототипичное наследование должным образом, я предлагаю вам прочитать:

Дополнительная информация:

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

Как только вы узнаете больше об этом, вы, скорее всего, проигнорируете частных членов alltogether и используете префикс _ и просто сделаете его публичным участником, как и все остальные;) Просто проще, а частные члены бессмысленны.

Смежные вопросы