предпочитать наследование прототипа в общем-то кажется правильным, в общем
Ну ... это более естественная вещь в JavaScript, конечно. Но так много JavaScript делает неправильно, что это не обязательно комплимент!
Конечно, когда производительность не является проблемой, с объектами, которые получают свои собственные связанные копии каждого метода, легче справиться, чем с объектами, которые совместно используют их методы, потому что вы можете просто передать ссылку на object.method
без необходимости закрывающий делегат или function.bind.
Есть ли способ объединить наследование прототипа с шаблоном модуля, чтобы разрешить закрытые переменные при необходимости?
Что вы хотите от личных переменных? Если это какая-то идея безопасности в стиле Java с помощью инкапсуляции, я бы отказался от этого и просто сделал бы это на языке Python: поместите подчеркивание в начале имени члена, и любой, кто захочет использовать извне, будет соответственно предупрежден, что это не поддерживается и может испортить. Внутри кода JavaScript, выполняющегося на одной и той же странице, никогда не будет границы безопасности, которая гарантировала бы конфиденциальность ваших * .
Если вы хотите избежать поиска нужной копии this
при вызове метода, вы можете вручную связать методы методов в инициализаторе:
var Thing= makeClass();
Thing.prototype.init= function(a) {
this._a= a;
this.showA= this.showA.bind(this);
};
Thing.prototype.showA= function() {
alert(this._a);
};
thing= new Thing(3);
setTimeout(thing.showA, 1000); // will work as `thing` has its own bound copy of `showA`
(function.bind - это JavaScript-код для будущего, который вы можете взломать в Function.prototype сейчас, пока браузеры его не поддержат).
Это естественным образом утрачивает некоторые легковесные свойства объектов на основе прототипов, но, по крайней мере, вы все равно можете иметь их совместно использующие члены, которые не являются методами, и методы, которые никогда не будут использоваться в качестве делегатов, если это ясно и вы всегда можете вспомнить, какие методы вы можете использовать таким образом.
Если вы просто хотите иметь возможность вводить имя закрытой переменной без необходимости постоянно вводить this.
, тогда вам придется делать это с замыканием. Ваш примерный мир может быть немного более понятным из инициализатора, чем при первом написании:
var User= makeClass();
User.prototype.init= function(first, last){
this.name= first+' '+last;
this.method2= this._method2factory();
};
User.prototype._method2factory= function() {
var _v2= 0;
function inc() {
_v2++;
}
return function method2(a,b,c) {
/* ... */
inc();
WScript.echo('doOtherWork('+this.name+') v2= '+_v2);
return _v2;
};
};
Но я не совсем уверен, что это даст вам много преимуществ по сравнению с написанием this._v2
и this._inc()
.