Frage

Um eine JavaScript-Klasse mit einer öffentlichen Methode zu erstellen, würde ich so etwas tun:

function Restaurant() {}

Restaurant.prototype.buy_food = function(){
   // something here
}

Restaurant.prototype.use_restroom = function(){
   // something here
}

Auf diese Weise können Benutzer meiner Klasse:

var restaurant = new Restaurant();
restaurant.buy_food();
restaurant.use_restroom();

Wie erstelle ich eine private Methode, die von aufgerufen werden kann? buy_food Und use_restroom Methoden, aber nicht extern durch Benutzer der Klasse?

Mit anderen Worten, ich möchte, dass meine Methodenimplementierung Folgendes kann:

Restaurant.prototype.use_restroom = function() {
   this.private_stuff();
}

Aber das sollte nicht funktionieren:

var r = new Restaurant();
r.private_stuff();

Wie definiere ich private_stuff als private Methode, also gilt beides?

Ich habe gelesen Doug Crockfords Artikel ein paar Mal, aber es scheint nicht, dass „private“ Methoden von öffentlichen Methoden aufgerufen werden können und „privilegierte“ Methoden extern aufgerufen werden können.

War es hilfreich?

Lösung

Sie können es tun, aber der Nachteil ist, dass es nicht Teil des Prototyps sein kann:

function Restaurant() {
    var myPrivateVar;

    var private_stuff = function() {  // Only visible inside Restaurant()
        myPrivateVar = "I can set this here!";
    }

    this.use_restroom = function() {  // use_restroom is visible to all
        private_stuff();
    }

    this.buy_food = function() {   // buy_food is visible to all
        private_stuff();
    }
}

Andere Tipps

Sie können private Methoden wie folgt simulieren:

function Restaurant() {
}

Restaurant.prototype = (function() {
    var private_stuff = function() {
        // Private code here
    };

    return {

        constructor:Restaurant,

        use_restroom:function() {
            private_stuff();
        }

    };
})();

var r = new Restaurant();

// This will work:
r.use_restroom();

// This will cause an error:
r.private_stuff();

Weitere Informationen über diese Technik hier: http: // webreflection .blogspot.com / 2008/04 / natural-Javascript-private-methods.html

Mit Selbst rufenden Funktion und rufen Sie

JavaScript verwendet Prototypen und haben Klassen (oder Methoden für diese Angelegenheit) does wie objektorientierte Sprachen. Ein JavaScript-Entwickler müssen in JavaScript denken.

Wikipedia-Zitat:

  

Im Gegensatz zu vielen objektorientierten Sprachen, gibt es keinen Unterschied zwischen   eine Funktionsdefinition und eine Methodendefinition. Vielmehr ist die Unterscheidung   tritt während der Funktionsaufruf; wenn eine Funktion als eine Methode aufgerufen   ein Objekt, wird die Funktion der lokale dieses Schlüsselwort zu, dass gebunden   Objekt für diesen Aufruf.

Lösung einer Selbst rufenden Funktion und die Anruffunktion die private nennen":

var MyObject = (function () {

    // Constructor
    function MyObject (foo) {
        this._foo = foo;
    }

    function privateFun (prefix) {
        return prefix + this._foo;
    }

    MyObject.prototype.publicFun = function () {
        return privateFun.call(this, '>>');
    }

    return MyObject;
})();


var myObject = new MyObject('bar');
myObject.publicFun();      // Returns '>>bar'
myObject.privateFun('>>'); // ReferenceError: private is not defined

Die Anruffunktion uns die private aufrufen können Funktion mit dem entsprechenden Kontext (this).


Einfachere mit Node.js

Wenn Sie mit node.js , Sie brauchen nicht die IIFE weil Sie die Vorteile des Modul-Ladesystem nehmen kann:

function MyObject (foo) {
    this._foo = foo;
}

function privateFun (prefix) {
    return prefix + this._foo;
}

MyObject.prototype.publicFun = function () {
    return privateFun.call(this, '>>');
}

exports.MyObject = MyObject;

Laden Sie die Datei:

var MyObject = require('./MyObject').MyObject;

var myObject = new MyObject('bar');
myObject.publicFun();      // Returns '>>bar'
myObject.privateFun('>>'); // ReferenceError: private is not defined


(experimentell) ES7 mit dem Bind Operator

Der Operator bind :: ist ein ECMAScript Vorschlag und ist in Babel implementiert ( Stufe 0 ).

export default class MyObject {
  constructor (foo) {
    this._foo = foo;
  }

  publicFun () {
    return this::privateFun('>>');
  }
}

function privateFun (prefix) {
  return prefix + this._foo;
}

Laden Sie die Datei:

import MyObject from './MyObject';

let myObject = new MyObject('bar');
myObject.publicFun();      // Returns '>>bar'
myObject.privateFun('>>'); // TypeError: myObject.privateFun is not a function

In diesen Situationen, wenn Sie eine öffentliche API haben, und Sie mögen, dass private und öffentliche Methoden / Eigenschaften, verwende ich immer das Modul-Muster. Dieses Muster wurde populär in der YUI-Bibliothek, und die Details finden Sie hier:

http://yuiblog.com/blog/2007/06/12 / Modul-Muster /

Es ist wirklich einfach und leicht für andere Entwickler zu verstehen. Ein einfaches Beispiel:

var MYLIB = function() {  
    var aPrivateProperty = true;
    var aPrivateMethod = function() {
        // some code here...
    };
    return {
        aPublicMethod : function() {
            aPrivateMethod(); // okay
            // some code here...
        },
        aPublicProperty : true
    };  
}();

MYLIB.aPrivateMethod() // not okay
MYLIB.aPublicMethod() // okay

Hier ist die Klasse, die ich geschaffen, um zu verstehen, was Douglas Crockford in seiner Website Private Members in JavaScript

function Employee(id, name) { //Constructor
    //Public member variables
    this.id = id;
    this.name = name;
    //Private member variables
    var fName;
    var lName;
    var that = this;
    //By convention, we create a private variable 'that'. This is used to     
    //make the object available to the private methods. 

    //Private function
    function setFName(pfname) {
        fName = pfname;
        alert('setFName called');
    }
    //Privileged function
    this.setLName = function (plName, pfname) {
        lName = plName;  //Has access to private variables
        setFName(pfname); //Has access to private function
        alert('setLName called ' + this.id); //Has access to member variables
    }
    //Another privileged member has access to both member variables and private variables
    //Note access of this.dataOfBirth created by public member setDateOfBirth
    this.toString = function () {
        return 'toString called ' + this.id + ' ' + this.name + ' ' + fName + ' ' + lName + ' ' + this.dataOfBirth; 
    }
}
//Public function has access to member variable and can create on too but does not have access to private variable
Employee.prototype.setDateOfBirth = function (dob) {
    alert('setDateOfBirth called ' + this.id);
    this.dataOfBirth = dob;   //Creates new public member note this is accessed by toString
    //alert(fName); //Does not have access to private member
}
$(document).ready()
{
    var employee = new Employee(5, 'Shyam'); //Create a new object and initialize it with constructor
    employee.setLName('Bhaskar', 'Ram');  //Call privileged function
    employee.setDateOfBirth('1/1/2000');  //Call public function
    employee.id = 9;                     //Set up member value
    //employee.setFName('Ram');  //can not call Private Privileged method
    alert(employee.toString());  //See the changed object

}

beschwören ich auf diese: EDIT: Eigentlich jemand zu einer identischen Lösung verknüpft ist. Duh!

var Car = function() {
}

Car.prototype = (function() {
    var hotWire = function() {
        // Private code *with* access to public properties through 'this'
        alert( this.drive() ); // Alerts 'Vroom!'
    }

    return {
        steal: function() {
            hotWire.call( this ); // Call a private method
        },
        drive: function() {
            return 'Vroom!';
        }
    };
})();

var getAwayVechile = new Car();

hotWire(); // Not allowed
getAwayVechile.hotWire(); // Not allowed
getAwayVechile.steal(); // Alerts 'Vroom!'

Ich denke, solche Fragen kommen immer wieder, weil der Mangel an Verständnis für die Verschlüsse. Сlosures ist Wichtigste in JS. Jeder JS-Programmierer haben die Essenz davon zu spüren.

1. Zu allererst müssen wir separate Rahmen (Verschluss) machen.

function () {

}

2. In diesem Bereich können wir tun, was wir wollen. Und niemand wird es wissen.

function () {
    var name,
        secretSkills = {
            pizza: function () { return new Pizza() },
            sushi: function () { return new Sushi() }
        }

    function Restaurant(_name) {
        name = _name
    }
    Restaurant.prototype.getFood = function (name) {
        return name in secretSkills ? secretSkills[name]() : null
    }
}

3. Für die Welt über unser Restaurant Klasse wissen, wir müssen sie von der Schließung zurück.

var Restaurant = (function () {
    // Restaurant definition
    return Restaurant
})()

4 Am Ende haben wir:.

var Restaurant = (function () {
    var name,
        secretSkills = {
            pizza: function () { return new Pizza() },
            sushi: function () { return new Sushi() }
        }

    function Restaurant(_name) {
        name = _name
    }
    Restaurant.prototype.getFood = function (name) {
        return name in secretSkills ? secretSkills[name]() : null
    }
    return Restaurant
})()

5. Auch dieser Ansatz hat Potenzial für die Vererbung und Templating

// Abstract class
function AbstractRestaurant(skills) {
    var name
    function Restaurant(_name) {
        name = _name
    }
    Restaurant.prototype.getFood = function (name) {
        return skills && name in skills ? skills[name]() : null
    }
    return Restaurant
}

// Concrete classes
SushiRestaurant = AbstractRestaurant({ 
    sushi: function() { return new Sushi() } 
})

PizzaRestaurant = AbstractRestaurant({ 
    pizza: function() { return new Pizza() } 
})

var r1 = new SushiRestaurant('Yo! Sushi'),
    r2 = new PizzaRestaurant('Dominos Pizza')

r1.getFood('sushi')
r2.getFood('pizza')

Ich hoffe, das hilft jemand besser, dieses Thema zu verstehen

Ich persönlich bevorzuge das folgende Muster für Klassen in JavaScript zu erstellen:

var myClass = (function() {
    // Private class properties go here

    var blueprint = function() {
        // Private instance properties go here
        ...
    };

    blueprint.prototype = { 
        // Public class properties go here
        ...
    };

    return  {
         // Public class properties go here
        create : function() { return new blueprint(); }
        ...
    };
})();

Wie Sie sehen können, ermöglicht es Ihnen, beide Klasse Eigenschaften und Instanzeigenschaften zu definieren, von denen jede öffentliche und private sein kann.


Demo

var Restaurant = function() {
    var totalfoodcount = 0;        // Private class property
    var totalrestroomcount  = 0;   // Private class property
    
    var Restaurant = function(name){
        var foodcount = 0;         // Private instance property
        var restroomcount  = 0;    // Private instance property
        
        this.name = name
        
        this.incrementFoodCount = function() {
            foodcount++;
            totalfoodcount++;
            this.printStatus();
        };
        this.incrementRestroomCount = function() {
            restroomcount++;
            totalrestroomcount++;
            this.printStatus();
        };
        this.getRestroomCount = function() {
            return restroomcount;
        },
        this.getFoodCount = function() {
            return foodcount;
        }
    };
   
    Restaurant.prototype = {
        name : '',
        buy_food : function(){
           this.incrementFoodCount();
        },
        use_restroom : function(){
           this.incrementRestroomCount();
        },
        getTotalRestroomCount : function() {
            return totalrestroomcount;
        },
        getTotalFoodCount : function() {
            return totalfoodcount;
        },
        printStatus : function() {
           document.body.innerHTML
               += '<h3>Buying food at '+this.name+'</h3>'
               + '<ul>' 
               + '<li>Restroom count at ' + this.name + ' : '+ this.getRestroomCount() + '</li>'
               + '<li>Food count at ' + this.name + ' : ' + this.getFoodCount() + '</li>'
               + '<li>Total restroom count : '+ this.getTotalRestroomCount() + '</li>'
               + '<li>Total food count : '+ this.getTotalFoodCount() + '</li>'
               + '</ul>';
        }
    };

    return  { // Singleton public properties
        create : function(name) {
            return new Restaurant(name);
        },
        printStatus : function() {
          document.body.innerHTML
              += '<hr />'
              + '<h3>Overview</h3>'
              + '<ul>' 
              + '<li>Total restroom count : '+ Restaurant.prototype.getTotalRestroomCount() + '</li>'
              + '<li>Total food count : '+ Restaurant.prototype.getTotalFoodCount() + '</li>'
              + '</ul>'
              + '<hr />';
        }
    };
}();

var Wendys = Restaurant.create("Wendy's");
var McDonalds = Restaurant.create("McDonald's");
var KFC = Restaurant.create("KFC");
var BurgerKing = Restaurant.create("Burger King");

Restaurant.printStatus();

Wendys.buy_food();
Wendys.use_restroom();
KFC.use_restroom();
KFC.use_restroom();
Wendys.use_restroom();
McDonalds.buy_food();
BurgerKing.buy_food();

Restaurant.printStatus();

BurgerKing.buy_food();
Wendys.use_restroom();
McDonalds.buy_food();
KFC.buy_food();
Wendys.buy_food();
BurgerKing.buy_food();
McDonalds.buy_food();

Restaurant.printStatus();

Siehe auch dieses Fiddle .

Alle diese Schließung kostet. Stellen Sie sicher, dass Sie die Geschwindigkeit Auswirkungen vor allem in IE testen. Sie werden feststellen, Sie sind besser mit einer Namenskonvention ab. Es gibt immer noch viele Firmen-Web-Nutzer gibt, die gezwungen sind, IE6 zu verwenden ...

Nehmen Sie eine der Lösungen, die Crockford privat oder priviledged Muster folgen. Zum Beispiel:

function Foo(x) {
    var y = 5;
    var bar = function() {
        return y * x;
    };

    this.public = function(z) {
        return bar() + x * z;
    };
}

In jedem Fall, in dem der Angreifer hat keine „execute“ direkt am JS Kontext er keine Möglichkeit hat, den Zugriff auf alle „öffentliche“ oder „private“ Felder oder Methoden. Falls der Angreifer, dass der Zugang haben kann er ausführen diese Einzeiler:

eval("Foo = " + Foo.toString().replace(
    /{/, "{ this.eval = function(code) { return eval(code); }; "
));

Beachten Sie, dass der obige Code für alle Konstruktor-Typ-privacy generisch ist. Es wird hier mit einigen der Lösungen scheitern, aber es sollte klar sein, dass so ziemlich alle der Schließung basierte Lösungen kann so mit unterschiedlichen replace() Parametern gebrochen werden.

Danach ausgeführt wird jedes Objekt erstellt mit new Foo() wird eine eval Methode haben, die genannt werden können, um in dem Konstruktor der Schließung definierte Werte oder Methoden geben oder zu ändern, z.

f = new Foo(99);
f.eval("x");
f.eval("y");
f.eval("x = 8");

Das einzige Problem, das ich mit diesem sehen kann, dass es nicht für die Fälle funktionieren, wo es nur eine Instanz ist und es auf Last erzeugt. Aber dann gibt es keinen Grund, um tatsächlich einen Prototyp zu definieren und in diesem Fall kann der Angreifer einfach erstellen Sie das Objekt anstelle des Konstrukteurs, solange er einen Weg hat die gleichen Parameter vorbei (zB sind sie konstant oder aus dem verfügbaren Werten berechnet).

Meiner Meinung nach, das macht so ziemlich Crockford Lösung nutzlos. Da die „Privatsphäre“ ist leicht die negativen Seiten seiner Lösung (reduzierten Lesbarkeit und Wartbarkeit, verminderte Leistung, mehr Speicher) macht die gebrochen " keine Privatsphäre“Prototyp basierte Methode die bessere Wahl.

Ich verwende in die Regel führende Unterstrichen __private und _protected Methoden und Felder (Perl-Stil), aber die Idee, die Privatsphäre in JavaScript markieren zeigt nur, wie es ist eine falsch verstandene Sprache.

Deshalb stimme ich mit Crockford mit Ausnahme seines ersten Satz.

So wie Sie echte Privatsphäre in JS bekommen? Setzen Sie alles auf der Server-Seite als privat erforderlich ist, und verwenden JS AJAX-Aufrufe zu tun.

Die Apotheose des Moduls Muster: Das Aufdecken Modul Muster

Eine nette kleine Erweiterung zu einem sehr robusten Mustern.

Wenn Sie das gesamte Spektrum von öffentlichen und privaten Funktionen mit der Fähigkeit für öffentliche Funktionen wollen privaten Funktionen zuzugreifen, Layout-Code für ein Objekt wie folgt aus:

function MyObject(arg1, arg2, ...) {
  //constructor code using constructor arguments...
  //create/access public variables as 
  // this.var1 = foo;

  //private variables

  var v1;
  var v2;

  //private functions
  function privateOne() {
  }

  function privateTwon() {
  }

  //public functions

  MyObject.prototype.publicOne = function () {
  };

  MyObject.prototype.publicTwo = function () {
  };
}

Hier ist, was ich am meisten bisher in Bezug auf private / öffentliche Methoden / Mitglieder und Instantiierung in Javascript genossen:

Hier ist der Artikel: http://www.sefol.com/?p=1090

und hier ist das Beispiel:

var Person = (function () {

    //Immediately returns an anonymous function which builds our modules 
    return function (name, location) {

        alert("createPerson called with " + name);

        var localPrivateVar = name;

        var localPublicVar = "A public variable";

        var localPublicFunction = function () {
            alert("PUBLIC Func called, private var is :" + localPrivateVar)
        };

        var localPrivateFunction = function () {
            alert("PRIVATE Func called ")
        };

        var setName = function (name) {

            localPrivateVar = name;

        }

        return {

            publicVar: localPublicVar,

            location: location,

            publicFunction: localPublicFunction,

            setName: setName

        }

    }
})();


//Request a Person instance - should print "createPerson called with ben"
var x = Person("ben", "germany");

//Request a Person instance - should print "createPerson called with candide"
var y = Person("candide", "belgium");

//Prints "ben"
x.publicFunction();

//Prints "candide"
y.publicFunction();

//Now call a public function which sets the value of a private variable in the x instance
x.setName("Ben 2");

//Shouldn't have changed this : prints "candide"
y.publicFunction();

//Should have changed this : prints "Ben 2"
x.publicFunction();

JSFiddle: http://jsfiddle.net/northkildonan/kopj3dt3/1/

Das Modul Muster ist in den meisten Fällen richtig. Aber wenn Sie Tausende von Fällen haben, speichern Klassen Speicher. Wenn der Speicher sparend ist ein Anliegen und Ihre Objekte eine geringe Menge an privaten Daten enthalten, aber eine Menge öffentlicher Funktionen haben, dann werden Sie alle öffentlichen Funktionen wollen im .prototype leben zu speichern.

Das ist, was ich kam mit:

var MyClass = (function () {
    var secret = {}; // You can only getPriv() if you know this
    function MyClass() {
        var that = this, priv = {
            foo: 0 // ... and other private values
        };
        that.getPriv = function (proof) {
            return (proof === secret) && priv;
        };
    }
    MyClass.prototype.inc = function () {
        var priv = this.getPriv(secret);
        priv.foo += 1;
        return priv.foo;
    };
    return MyClass;
}());
var x = new MyClass();
x.inc(); // 1
x.inc(); // 2

Das Objekt priv enthält private Eigenschaften. Es ist zugänglich über die öffentliche Funktion getPriv(), aber diese Funktion gibt false, wenn Sie es die secret passieren, und dies ist nur innerhalb des Hauptverschlusses bekannt.

Was ist das?

var Restaurant = (function() {

 var _id = 0;
 var privateVars = [];

 function Restaurant(name) {
     this.id = ++_id;
     this.name = name;
     privateVars[this.id] = {
         cooked: []
     };
 }

 Restaurant.prototype.cook = function (food) {
     privateVars[this.id].cooked.push(food);
 }

 return Restaurant;

})();

Private-Variable-Lookup ist außerhalb des Anwendungsbereichs der unmittelbaren Funktion unmöglich. Es gibt keine Duplizierung von Funktionen, Speicher zu speichern.

Der Nachteil ist, dass die Suche von privaten Variablen ist klobig privateVars[this.id].cooked ist lächerlich zu geben. Es gibt auch ein extra "id" Variable.

var TestClass = function( ) {

    var privateProperty = 42;

    function privateMethod( ) {
        alert( "privateMethod, " + privateProperty );
    }

    this.public = {
        constructor: TestClass,

        publicProperty: 88,
        publicMethod: function( ) {
            alert( "publicMethod" );
            privateMethod( );
        }
    };
};
TestClass.prototype = new TestClass( ).public;


var myTestClass = new TestClass( );

alert( myTestClass.publicProperty );
myTestClass.publicMethod( );

alert( myTestClass.privateMethod || "no privateMethod" );

Ähnlich wie georgebrock aber etwas weniger ausführlich (IMHO) Etwaige Probleme mit ihm auf diese Weise zu tun? (Ich habe es nicht überall gesehen)

edit: Ich erkennen dies irgendwie nutzlos ist, da jeder unabhängig Instanziierung seine eigene Kopie der öffentlichen Methoden hat, wodurch die Verwendung des Prototyps zu untergraben

.

Wickeln Sie den gesamten Code in Anonymous Funktion: Dann werden alle Funktionen privat sein wird, funktioniert nur angebracht Objekt window:

(function(w,nameSpacePrivate){
     w.Person=function(name){
         this.name=name;   
         return this;
     };

     w.Person.prototype.profilePublic=function(){
          return nameSpacePrivate.profile.call(this);
     };  

     nameSpacePrivate.profile=function(){
       return 'My name is '+this.name;
     };

})(window,{});

verwenden:

  var abdennour=new Person('Abdennour');
  abdennour.profilePublic();

FIDDLE

Seien Sie nicht so umfangreich sein. Es ist Javascript. Verwenden Sie Naming Convention .

Nach Jahren in es6 Klassen arbeiten, begann ich vor kurzem der Arbeit an einem Projekt ES5 (requireJS mit der bereits sehr ausführlich schau). Ich war hier über und über alle Strategien erwähnt und es läuft alles im Grunde auf verwendet eine Namenskonvention :

  1. Javascript nicht Umfang Schlüsselwörter wie private haben. Andere Entwickler Javascript Eingabe wird diese im Voraus wissen. Daher ist eine einfache Namenskonvention mehr als ausreichend. Eine einfache Namenskonvention mit einem Unterstrich voranzustellen löst das Problem der privaten Eigenschaften und privater Methoden.
  2. Lassen Sie uns aus Geschwindigkeitsgründen Vorteil der Prototype nehmen, aber als das lässt nicht mehr ausführliche erhalten. Lassen Sie uns versuchen, die ES5 „Klasse“ halten suchen so genau zu dem, was wir in anderen Backend-Sprachen erwarten könnte (und jede Datei als Klasse zu behandeln, auch wenn wir eine Instanz nicht zurückgeben müssen).
  3. Lassen Sie sich mit einer realistischeren Modul Situation zeigen (wir verwenden alten ES5 und alte requireJs).

my-tooltip.js

    define([
        'tooltip'
    ],
    function(
        tooltip
    ){

        function MyTooltip() {
            // Later, if needed, we can remove the underscore on some
            // of these (make public) and allow clients of our class
            // to set them.
            this._selector = "#my-tooltip"
            this._template = 'Hello from inside my tooltip!';
            this._initTooltip();
        }

        MyTooltip.prototype = {
            constructor: MyTooltip,

            _initTooltip: function () {
                new tooltip.tooltip(this._selector, {
                    content: this._template,
                    closeOnClick: true,
                    closeButton: true
                });
            }
        }

        return {
            init: function init() {
               new MyTooltip();  // <-- Our constructor adds our tooltip to the DOM so not much we need to do after instantiation.
            }

            // You could instead return a new instantiation, 
            // if later you do more with this class.
            /* 
            create: function create() {
               return new MyTooltip();
            }
            */
        }
    });

Privat Funktionen nicht die öffentlichen Variablen zugreifen können Modulmuster mit

Da jeder aufhängte hier seinen eigenen Code, ich werde das auch tun ...

Ich mag Crockford, weil er echte objektorientierte Muster in Javascript eingeführt. Aber er kam auch mit einem neuen Missverständnis auf, das „die“ ein.

Warum nutzt er, „daß = diese“? Es hat nichts mit privaten Funktionen überhaupt zu tun. Es hat mit inneren Funktionen zu tun!

Da nach Crockford dies fehlerhaftem Code:

Function Foo( ) {
    this.bar = 0; 
    var foobar=function( ) {
        alert(this.bar);
    }
} 

So schlug er vor, dies zu tun:

Function Foo( ) {
    this.bar = 0;
    that = this; 
    var foobar=function( ) {
        alert(that.bar);
    }
}

Also wie gesagt, ich bin ziemlich sicher, dass Crockford falsch war seine Erklärung darüber, und diese (aber sein Code ist sicher richtig). Oder täuscht er einfach die Javascript Welt, zu wissen, wer seinen Code kopiert? Ich weiß nicht ... Ich bin kein Browser-Aussenseiter; D

Bearbeiten

Ach, das ist, was geht: Was bedeutet ‚var dass = this;‘ bedeuten in JavaScript?

So Crockie mit seiner Erklärung wirklich falsch war .... aber richtig mit seinem Code, also ist er immer noch ein großer Kerl. :))

In der Regel habe ich die private Object _ vorübergehend zum Objekt. Sie haben die Privatsphäre exlipcitly in dem „Power-Konstruktor“ öffnen für das Verfahren. Wenn Sie die Methode vom Prototyp aufrufen, werden Sie Lage sein, die Prototyp-Methode

zu überschreiben
  • Erstellen Sie eine öffentliche Methode zugänglich im "Power-Konstruktor": (CTX ist das Objekt, Kontext)

    ctx.test = GD.Fabric.open('test', GD.Test.prototype, ctx, _); // is a private object
    
  • Jetzt habe ich dieses openPrivacy:

    GD.Fabric.openPrivacy = function(func, clss, ctx, _) {
        return function() {
            ctx._ = _;
            var res = clss[func].apply(ctx, arguments);
            ctx._ = null;
            return res;
        };
    };
    

Das ist, was ich herausgearbeitet:

Anforderungen einer Klasse von Zucker-Code, der Sie hier finden. Unterstützt auch geschützt, Vererbung, virtuell, statisch Material ...

;( function class_Restaurant( namespace )
{
    'use strict';

    if( namespace[ "Restaurant" ] ) return    // protect against double inclusions

        namespace.Restaurant = Restaurant
    var Static               = TidBits.OoJs.setupClass( namespace, "Restaurant" )


    // constructor
    //
    function Restaurant()
    {
        this.toilets = 3

        this.Private( private_stuff )

        return this.Public( buy_food, use_restroom )
    }

    function private_stuff(){ console.log( "There are", this.toilets, "toilets available") }

    function buy_food     (){ return "food"        }
    function use_restroom (){ this.private_stuff() }

})( window )


var chinese = new Restaurant

console.log( chinese.buy_food()      );  // output: food
console.log( chinese.use_restroom()  );  // output: There are 3 toilets available
console.log( chinese.toilets         );  // output: undefined
console.log( chinese.private_stuff() );  // output: undefined

// and throws: TypeError: Object #<Restaurant> has no method 'private_stuff'
Class({  
    Namespace:ABC,  
    Name:"ClassL2",  
    Bases:[ABC.ClassTop],  
    Private:{  
        m_var:2  
    },  
    Protected:{  
        proval:2,  
        fight:Property(function(){  
            this.m_var--;  
            console.log("ClassL2::fight (m_var)" +this.m_var);  
        },[Property.Type.Virtual])  
    },  
    Public:{  
        Fight:function(){  
            console.log("ClassL2::Fight (m_var)"+this.m_var);  
            this.fight();  
        }  
    }  
});  

https://github.com/nooning/JSClass

Ich habe ein neues Werkzeug geschaffen, damit Sie echte private Methoden auf dem Prototyp haben https://github.com/TremayneChrist/ProtectJS

Beispiel:

var MyObject = (function () {

  // Create the object
  function MyObject() {}

  // Add methods to the prototype
  MyObject.prototype = {

    // This is our public method
    public: function () {
      console.log('PUBLIC method has been called');
    },

    // This is our private method, using (_)
    _private: function () {
      console.log('PRIVATE method has been called');
    }
  }

  return protect(MyObject);

})();

// Create an instance of the object
var mo = new MyObject();

// Call its methods
mo.public(); // Pass
mo._private(); // Fail

Sie haben einen Verschluss um die tatsächliche Konstruktor-Funktion zu setzen, wo Sie Ihre privaten Methoden definieren können. Um die Daten der Instanzen durch diese privaten Methoden zu ändern, müssen Sie geben ihnen „das“ mit ihnen, entweder als Funktionsargument oder durch diese Funktion mit .apply Aufruf (this):

var Restaurant = (function(){
    var private_buy_food = function(that){
        that.data.soldFood = true;
    }
    var private_take_a_shit = function(){
        this.data.isdirty = true;   
    }
    // New Closure
    function restaurant()
    {
        this.data = {
            isdirty : false,
            soldFood: false,
        };
    }

    restaurant.prototype.buy_food = function()
    {
       private_buy_food(this);
    }
    restaurant.prototype.use_restroom = function()
    {
       private_take_a_shit.call(this);
    }
    return restaurant;
})()

// TEST:

var McDonalds = new Restaurant();
McDonalds.buy_food();
McDonalds.use_restroom();
console.log(McDonalds);
console.log(McDonalds.__proto__);

Ich weiß, es ist ein bisschen zu spät, aber wie wäre das?

var obj = function(){
    var pr = "private";
    var prt = Object.getPrototypeOf(this);
    if(!prt.hasOwnProperty("showPrivate")){
        prt.showPrivate = function(){
            console.log(pr);
        }
    }    
}

var i = new obj();
i.showPrivate();
console.log(i.hasOwnProperty("pr"));

Es gibt viele Antworten auf diese Frage schon, aber nichts gepasst meine Bedürfnisse. So kam ich mit meiner eigenen Lösung, ich hoffe, dass es nützlich ist für jemanden:

function calledPrivate(){
    var stack = new Error().stack.toString().split("\n");
    function getClass(line){
        var i = line.indexOf(" ");
        var i2 = line.indexOf(".");
        return line.substring(i,i2);
    }
    return getClass(stack[2])==getClass(stack[3]);
}

class Obj{
    privateMethode(){
        if(calledPrivate()){
            console.log("your code goes here");
        }
    }
    publicMethode(){
        this.privateMethode();
    }
}

var obj = new Obj();
obj.publicMethode(); //logs "your code goes here"
obj.privateMethode(); //does nothing

Wie Sie dieses System sehen können funktioniert, wenn diese Art von Klassen in Javascript. Soweit ich die Methoden herausgefunden keiner kommentiert oben hat.

Siehe diese Antwort für aa sauber und einfach ‚Klasse‘ Lösung mit einer privaten und öffentlichen Schnittstelle und Unterstützung für die Zusammensetzung

Ich ziehe private Daten in einem zugehörigen WeakMap zu speichern. Auf diese Weise können Sie Ihre öffentlichen Methoden auf dem Prototyp halten, wo sie hingehören. Dies scheint der effizienteste Weg, um dieses Problem für eine große Anzahl von Objekten zu handhaben.

const data = new WeakMap();

function Foo(value) {
    data.set(this, {value});
}

// public method accessing private value
Foo.prototype.accessValue = function() {
    return data.get(this).value;
}

// private 'method' accessing private value
function accessValue(foo) {
    return data.get(foo).value;
}

export {Foo};
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top