Я не знаю как правильно сказать, но как сделать свойство, которое было бы не видно внешне, но было бы видно методам установленных через прототип? Вот типа -
var Class = function(){
var _array = []; // приватное или протектед свойство
};
Class.prototype.method = function(){
// как обратиться здесь к _array?
};
Возможно такое сделать из коробки?
Средства языка такого, насколько я знаю, не предоставляют. Поэтому javascript-еры договорились, что все свойства которые начинаются со знака нижнего подчеркивания '_' являются приватными. В вашем случае:
var Class = function(){
this._array = []; // приватное или протектед свойство
};
Class.prototype.method = function(){
// как обратиться здесь к _array?
this._array
};
var instance = new Class();
instance._array.push('string') // но мы то знаем, что так делать нельзя
Update
Появилась идея. Шифровать имя свойства и делать его enumerable. Костыль:
var prive = function (that, propName, newValue) {
var decodeStr = function (str) {
return Array.prototype.map.call(
str,
function (char, i) {
return String.fromCharCode(str.charCodeAt(i)-5)
}).join('');
},
decodedPropName = decodeStr(propName);
if (arguments.length >= 3) {
// set private property
Object.defineProperty(that, decodedPropName, {
enumerable: false,
writable: true,
value: newValue,
});
} else {
//get private property
return that[decodedPropName];
}
}
Демонстрация
Оберните класс в анонимную функцию, воспользовавшись ограниченной областью видимости для приватных свойств.
(function(){
var private_method = function(){}; // приватный метод не будет виден снаружи
var private_property = 'ololo'; // приватное свойство
var Class = function(){};
Class.prototype.public_method = function(){ // паблик метод
var x = private_method(private_property);
// приватные свойства и методы можно использовать здесь
};
window.Class = Class; // выносим класс в общую область видимости
})();
jsfiddle
Я этот вопрос решал вот так:
(function (exports) {
/*
* sample prototype,
*
* inherit @boolean if true - return privates object,
*
*/
function A(inherit) {
var privates = { //setup private vars, they could be also changed, added in method or children
a: 1,
b: 2,
c: 3
};
//setup public methods which uses privates
this.aPlus = bindPlus("aPlus", this, privates); //pass method name as string!
this.aGet = bindPlus("aGet", this, privates);
if (inherit) {
return privates;
}
}
A.prototype.aPlus = function () {
var args = getArgs(arguments),
//self is "this" here (applied/called too), object reference is still this
privates = args.shift(),
self = args.shift(),
//function real arguments
n = args.shift();
return privates.a += n;
};
A.prototype.aGet = function (n) {
var args = getArgs(arguments),
privates = args.shift(),
self = args.shift();
console.error(this, self,privates);
return privates.a;
};
exports.A = A;
exports.getArgs = getArgs; //should be hidden somehow, but this is out of the story
exports.bindPlus = bindPlus;
//utilites
function getArgs(arg) {
return Array.prototype.slice.call(arg);
}
//вот здесь в общем-то ядро идеи
function bindPlus(funct, self, privates) {
/**
* if uncomment here and comment same line later,
* it will be run faster, but it would be impossible
* to change prototype after constructor run (tests after ----- could be incorrect)
*/
//var func=Object.getPrototypeOf(self)[funct].bind(self, privates);
return function () {
var func=Object.getPrototypeOf(self)[funct].bind(self, privates);
var args=getArgs(arguments); //this could be changed to speedup, but need to change method itself
args.unshift(this); //called/applied this
return func.apply(null, args);
};
}
})(this);
//inherited
function B(inherit) {
var privates = Object.getPrototypeOf(this).constructor.call(this, true);
privates.d = 4;
this.dGet = bindPlus("dGet", this, privates);
if (inherit) {
return privates;
}
}
B.prototype = Object.create(A.prototype);
B.constructor = B;
B.prototype.aGet = function () {
var args = getArgs(arguments);
var privates = args.shift(),
self = args.shift();
console.warn("B.aGet",self, privates);
return privates.a;
};
B.prototype.dGet = function () {
var args = getArgs(arguments),
privates = args.shift();
self = args.shift(),
console.warn("B.dGet", self, privates);
return privates.d;
};
но это немного тормозно и неудобно, лучшего способа не нашел, чтобы работало.
http://jsfiddle.net/oceog/TJH9Q/
Ну раз тут уже толпа, внесу лепту, так сказать. Вкратце - из глобальной области видимости исключается один объект _this, который и содержит все приватные поля-методы. Плюсы - прозрачность и вроде даже удобство.
var MyClass = function() {
var _this = {}; // private container
_this.private1 = 0; // private var 1
_this.private2 = 1; // private var 2
_this.incPrivate = function() { // private function
_this.private1++;
_this.private2++;
};
this.public1 = 2; // public var 1
this.public2 = 3; // public var 2
this.logPrivate = function() { // public function
console.log(_this);
return this;
};
this.incPublic = function() { // public function
this.public1++;
this.public2++;
return this;
};
this.proxyIncPrivate = function() { // public function / proxy
_this.incPrivate();
return this;
};
this.logPublic = function() { // public function
console.log(this);
return this;
};
}
var MyInstance = new MyClass();
jsfiddle
UPDADE
Заморочился я тут и сделал реализацию для основных типов свойств в JS. не в курсе, что там с памятью, но по работе оно стало похоже на нормальные языки :)
(function() {
var _class = {
// доступно в объекте и прототипе,
// один экземпляр (изменяется отовсюду)
// недоступно из глобальной области видимости
privateStatic1: 0,
privateStatic2: 1,
privateStaticMethod: function() {
console.log('called private static method');
}
}
var MyClass = function() {
var _this = {
// доступно только из методов объекта,
// изменяется только объект
// недоступно из глобала и класса
private1: 2,
private2: 3,
privateMethod: function() {
console.log('called private method');
}
};
// доступно отовсюду после создания объекта,
// изменяется только объект
// недоступно из глобала и класса
this.public1 = 4;
this.public2 = 5;
this.publicMethod = function() {
console.log('called public method');
};
};
// доступно отовсюду,
// один экземпляр
// дублирование для возможности вызова через MyClass без создания объекта
MyClass.prototype.publicStatic1 = 6;
MyClass.publicStatic1 = MyClass.prototype.publicStatic1;
MyClass.prototype.publicStatic2 = 7;
MyClass.prototype.publicStatic2 = MyClass.prototype.publicStatic2;
MyClass.prototype.publicStaticMethod = function() {
console.log('called public static method');
}
MyClass.publicStaticMethod = MyClass.prototype.publicStaticMethod;
window.MyClass = MyClass;
})();
http://jsfiddle.net/ux95ub87/1/ + консольный вывод результатов всех вызовов.
Как развивать веб-проекты в 2026 году: технологии, контент E-E-A-T и факторы доверия
Современные инструменты для криптотрейдинга: как технологии помогают принимать решения
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники