I do not know how to correctly say, but how to make a property that would not be visible externally, but would it be visible to the methods established through the prototype? That type -

var Class = function(){ var _array = []; // приватное или протектед свойство }; Class.prototype.method = function(){ // как обратиться здесь к _array? }; 

Is it possible to do this out of the box?

    4 answers 4

    Means of language such, as far as I know, do not provide. Therefore, the javascript engines agreed that all properties that begin with the underscore character '_' are private. In your case:

     var Class = function(){ this._array = []; // приватное или протектед свойство }; Class.prototype.method = function(){ // как обратиться здесь к _array? this._array }; var instance = new Class(); instance._array.push('string') // но мы то знаем, что так делать нельзя 

    Update

    There was an idea. Encrypt the property name and make it enumerable. Crutch:

     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]; } } 

    Demonstration

    • 2
      @alvoro, thanks! The more I delve into js, ​​the more it seems to me that he was overestimated. I began to comprehend it from the creation of games, and I was told that it is ten times faster as3. In fact, it turned out that the games are normal, only those who speak in imagination and tools, compared to as3, can say no. Yes, and it seems to me that it is suitable for layout makers that are far from the PLO, but if the igrodels fit into it, then they will be terrified by the lack of PLO. And starting to do it, all the speed will come to naught. Doubtful in general "superiority". He's not a flash killer .. A flash killer is naive. - vas
    • 3
      It is, that is, but very much like a children's tea party.)) - vas
    • 2
      @vas I in your place would not make such loud statements, you can only criticize a language when you know it well and know how to use it. - Lookingfor
    • 2
      @vas, I agree with the previous comment. Moreover, it is necessary to program in js by abstracting from typical OOP and stop thinking with the style of other OOP languages ​​and not try to trim js with them, then yours is a success - likerRr
    • one
      @alvoro I globally did not agree with anyone about "private properties with _ " this is a crutch and it is not usually needed. in es6 there will be private properties, but not implemented anywhere else. - zb '

    Wrap the class in an anonymous function, using the limited scope for private properties.

     (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

    I solved this question like this:

     (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; }; 

    but it is a little slow and uncomfortable, I could not find a better way to work.

    http://jsfiddle.net/oceog/TJH9Q/

      Well, since there is already a crowd, I will contribute, so to speak. In short, a single _this object is excluded from the global scope, which contains all private field methods. Pluses - transparency and even convenience.

       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

      I got confused here and made an implementation for the main types of properties in JS. I do not know what is there with the memory, but by work it became like normal languages ​​:)

       (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/ + console output of all calls.

      • In such an implementation, there is no possibility to use "private" properties in the prototype, your methods for each instance will be stored in memory - likerRr
      • @likerRr, well, I do not pretend to universality, it’s generally difficult to offer something without cumbersomeness. Moreover, the use of private from a domain is, in fact, public static (php MyClass::method and $this->private1 ) and should not work. If we talk about private static , then in the answer @vldmir this is exactly what is implemented. Can be combined. - Sh4dow
      • What I actually did. I didn’t give a damn about the prototypes, but I realized how it should be public (+ static), private (+ static). This prototype in general is what the hell, to be honest. Update the answer. - Sh4dow
      • @ Sh4dow, you do not spare user resources :) - likerRr