दिलचस्प पोस्ट
क्या JSON पुस्तकालय आपके लिए अच्छी तरह से काम करता है। NET? एंड्रॉइड – एक उरी से एक इनटस्टस्ट्रीम को एक बाइट सरणी में ले जा रहा है? प्रस्तुत करने के लिए फार्म ताज़ा पृष्ठ रोकें jQuery – एक स्ट्रिंग में एक अक्षर के सभी उदाहरणों की जगह सी भाषा में अस्थिर खोजशब्द? मेरे रूबी पथ पर वर्तमान निर्देशिका क्यों नहीं है? QueueUserWorkItem () और BeginInvoke () के बीच अंतर क्या है, कोई अत्याधुनिक गतिविधि नहीं करने के लिए कोई वापसी प्रकार की आवश्यकता के साथ क्या है वादा डिस्पोजर पैटर्न क्या है? खुले विंडो और विशिष्ट आकार को चालू करें ओपनएलजी रोटेशन के लिए क्वाटरनियन का उपयोग करना फ्लोट और डबल के बीच printf और सह अंतर कैसे होता है कॉल कीवर्ड VB6 में क्या करता है? मैं jQuery की वास्तविक छवि चौड़ाई और ऊंचाई कैसे प्राप्त करूं? ओपनसीवी में पायथन का इस्तेमाल करते हुए एक छवि कैसे क्रॉप करें ggplot2 हीटमैप्स: श्रेणियों के लिए अलग-अलग ग्रेडिएंट्स का उपयोग करना

प्रोटोटाइप-परिभाषित कार्यों से निजी सदस्य चर को एक्सेस करना

क्या प्रोटोटाइप-परिभाषित विधियों के लिए उपलब्ध "निजी" चर (निर्माता में परिभाषित) बनाने का कोई तरीका है?

TestClass = function(){ var privateField = "hello"; this.nonProtoHello = function(){alert(privateField)}; }; TestClass.prototype.prototypeHello = function(){alert(privateField)}; 

यह काम:

 t.nonProtoHello() 

लेकिन यह नहीं है:

 t.prototypeHello() 

मैं निर्माता के अंदर मेरे तरीकों को परिभाषित करने के लिए उपयोग किया जाता हूं, लेकिन कुछ कारणों से उसमें से दूर जा रहा हूं।

Solutions Collecting From Web of "प्रोटोटाइप-परिभाषित कार्यों से निजी सदस्य चर को एक्सेस करना"

नहीं, ऐसा करने का कोई तरीका नहीं है यह अनिवार्य रूप से रिवर्स में खुल जाएगा।

कन्स्ट्रक्टर के अंदर परिभाषित विधियां निजी चर का उपयोग कर सकती हैं क्योंकि सभी फ़ंक्शन के पास उस क्षेत्र तक पहुंच होती है जिसमें उन्हें परिभाषित किया गया था।

प्रोटोटाइप पर परिभाषित विधियों को कन्स्ट्रक्टर के दायरे में परिभाषित नहीं किया जाता है, और कन्स्ट्रक्टर के स्थानीय चर तक पहुंच नहीं होगी।

आपके पास अभी भी निजी चर हो सकते हैं, लेकिन यदि आप प्रोटोटाइप पर परिभाषित तरीकों को उन तक पहुंचने के लिए परिभाषित करना चाहते हैं, तो आपको this ऑब्जेक्ट पर गेटर्स और सेटर्स को परिभाषित करना चाहिए, जो प्रोटोटाइप विधियों (अन्य सभी के साथ) को एक्सेस होगा । उदाहरण के लिए:

 function Person(name, secret) { // public this.name = name; // private var secret = secret; // public methods have access to private members this.setSecret = function(s) { secret = s; } this.getSecret = function() { return secret; } } // Must use getters/setters Person.prototype.spillSecret = function() { alert(this.getSecret()); }; 

अद्यतन: ES6 के साथ, एक बेहतर तरीका है:

लंबी कहानी छोटी, निजी क्षेत्र बनाने के लिए आप नए Symbol का उपयोग कर सकते हैं।
यहां एक महान वर्णन है: https://curiosity-driven.org/private-properties-in-javascript

उदाहरण:

 var Person = (function() { // Only Person can access nameSymbol var nameSymbol = Symbol('name'); function Person(name) { this[nameSymbol] = name; } Person.prototype.getName = function() { return this[nameSymbol]; }; return Person; }()); 

ES5 के साथ सभी आधुनिक ब्राउज़रों के लिए:

आप बस क्लोज़र्स का उपयोग कर सकते हैं

ऑब्जेक्ट्स का निर्माण करने का सबसे आसान तरीका है प्रोटोटाइप एग्रीमेंट से पूरी तरह से बचने के लिए। बस बंद के भीतर निजी चर और सार्वजनिक कार्यों को परिभाषित करें, और सभी सार्वजनिक विधियों के लिए चर का निजी उपयोग होगा।

या आप सिर्फ प्रोटोटाइप का उपयोग कर सकते हैं

जावास्क्रिप्ट में, प्रोटोटाइप विरासत प्राथमिक रूप से एक अनुकूलन है । यह प्रत्येक उदाहरण के अपने स्वयं के तरीके होने के बजाय कई उदाहरणों को प्रोटोटाइप पद्धतियों को साझा करने की अनुमति देता है।
दोष यह है कि this एकमात्र ऐसी चीज है जो प्रत्येक समय एक प्रोटोटाइप फ़ंक्शन को कहा जाता है।
इसलिए, किसी भी निजी क्षेत्र को इसके माध्यम से सुलभ होना चाहिए, जिसका अर्थ है कि वे सार्वजनिक होने जा रहे हैं इसलिए हम सिर्फ _private फ़ील्ड के लिए नामकरण सम्मेलनों का पालन करना चाहते हैं।

प्रोटोटाइप के साथ क्लोज़र्स को मिलाकर परेशान मत करो

मुझे लगता है कि आपको प्रोटोटाइप के तरीकों के साथ क्लोजर वेरिएबल का मिश्रण नहीं करना चाहिए । आपको एक या दूसरे का उपयोग करना चाहिए

जब आप किसी निजी चर तक पहुंचने के लिए बंद का उपयोग करते हैं, तो प्रोटोटाइप विधि वेरिएबल तक पहुंच नहीं सकते हैं। इसलिए, आपको this पर बंद होने का खुलासा करना this , जिसका मतलब है कि आप इसे सार्वजनिक रूप से एक तरफ या किसी अन्य को उजागर कर रहे हैं इस दृष्टिकोण से हासिल करने में बहुत कम है

मैं कौन से चयन करता हूं?

वास्तव में सरल वस्तुओं के लिए, बस बंद के साथ एक सादा ऑब्जेक्ट का उपयोग करें

यदि आपको प्रोटोटाइप विरासत की ज़रूरत है – उत्तराधिकार, प्रदर्शन, आदि के लिए – फिर "_private" नामकरण सम्मेलन के साथ रहें और क्लोजर के साथ परेशान न करें।

मुझे समझ में नहीं आ रहा है कि जेएस डेवलपर्स क्षेत्र को सचमुच निजी बनाने के लिए इतनी मेहनत क्यों करते हैं

जब मैंने इसे पढ़ा, तो यह एक मुश्किल चुनौती की तरह लग रहा था, इसलिए मैंने एक रास्ता निकालने का फैसला किया। मैं किसके साथ आया था क्रैज़ैज़ी, लेकिन यह पूरी तरह से काम करता है।

सबसे पहले, मैंने एक तत्काल कार्य में वर्ग को परिभाषित करने की कोशिश की ताकि आप उस समारोह के कुछ निजी गुणों तक पहुंच सकें। यह काम करता है और आपको कुछ निजी डेटा प्राप्त करने की अनुमति देता है, हालांकि, यदि आप निजी डेटा सेट करने का प्रयास करते हैं तो आपको जल्द ही पता चल जाएगा कि सभी ऑब्जेक्ट समान मूल्य साझा करेंगे।

 var SharedPrivateClass = (function(){ // use immediate function // our private data var private = "Default"; // create the constructor function SharedPrivateClass () {} // add to the prototype SharedPrivateClass.prototype.getPrivate = function () { // It has access to private vars from the immediate function! return private; } SharedPrivateClass.prototype.setPrivate = function (value) { private = value; } return SharedPrivateClass; })(); var a = new SharedPrivateClass(); console.log("a:", a.getPrivate()); // "a: Default" var b = new SharedPrivateClass(); console.log("b:", b.getPrivate()); // "b: Default" a.setPrivate("foo"); // a Sets private to 'foo' console.log("a:", a.getPrivate()); // "a: foo" console.log("b:", b.getPrivate()); // oh no, b.getPrivate() is 'foo'! console.log(a.hasOwnProperty("getPrivate")); // false. belongs to the prototype console.log(a.private); // undefined 

ऐसे कई मामले हैं जहां यह पर्याप्त होगा जैसे कि आप निरंतर मान प्राप्त करना चाहते हैं जैसे ईवेंट नाम जो उदाहरणों के बीच साझा किए जाते हैं लेकिन अनिवार्य रूप से, वे निजी स्थिर चर की तरह काम करते हैं

यदि प्रोटोटाइप पर परिभाषित आपके तरीकों के भीतर से आपको एक निजी नामस्थान में चर का उपयोग करने की आवश्यकता है, तो आप इस पैटर्न को आज़मा सकते हैं।

 var PrivateNamespaceClass = (function(){ // immediate function var instance = 0, // counts the number of instances defaultName = "Default Name", p = []; // an array of private objects // careate the constructor function PrivateNamespaceClass () { // Increment the instance count and save it to the instance. // This will become your key to your private space. this.i = instance++; // Create a new object in the private space. p[this.i] = {}; // Define properties or methods in the private space. p[this.i].name = defaultName; console.log("New instance " + this.i); } PrivateNamespaceClass.prototype.getPrivateName = function () { // It has access to the private space and it's children! return p[this.i].name; } PrivateNamespaceClass.prototype.setPrivateName = function (value) { // Because you use the instance number assigned to the object (this.i) // as a key, the values set will not change in other instances. p[this.i].name = value; return "Set " + p[this.i].name; } return PrivateNamespaceClass; })(); var a = new PrivateNamespaceClass(); console.log(a.getPrivateName()); // Default Name var b = new PrivateNamespaceClass(); console.log(b.getPrivateName()); // Default Name console.log(a.setPrivateName("A")); console.log(b.setPrivateName("B")); console.log(a.getPrivateName()); // A console.log(b.getPrivateName()); // B console.log(a.privateNamespace); // undefined 

मुझे उस किसी भी व्यक्ति से कुछ प्रतिक्रिया पसंद है जो इसे करने की इस तरह से त्रुटि देखती है

इस पर डग क्रॉकफोर्ड का पेज देखें आपको इसे अप्रत्यक्ष रूप से कुछ ऐसा करना होगा जो निजी चर के दायरे तक पहुंच सकता है।

एक और उदाहरण:

 Incrementer = function(init) { var counter = init || 0; // "counter" is a private variable this._increment = function() { return counter++; } this._set = function(x) { counter = x; } } Incrementer.prototype.increment = function() { return this._increment(); } Incrementer.prototype.set = function(x) { return this._set(x); } 

उदाहरण:

 js>i = new Incrementer(100); [object Object] js>i.increment() 100 js>i.increment() 101 js>i.increment() 102 js>i.increment() 103 js>i.set(-44) js>i.increment() -44 js>i.increment() -43 js>i.increment() -42 

मेरा सुझाव है कि यह संभवतः "कन्स्ट्रक्टर में एक प्रोटोटाइप असाइनमेंट होने पर" जावास्क्रिप्ट एंटी-पैटर्न के रूप में वर्णन करने के लिए एक अच्छा विचार होगा। इसके बारे में सोचो। यह बहुत जोखिम भरा तरीका है

दूसरी ऑब्जेक्ट के निर्माण पर आप वास्तव में क्या कर रहे हैं (यानी बी) उस प्रोटोटाइप का उपयोग करने वाले सभी ऑब्जेक्ट्स के लिए प्रोटोटाइप फ़ंक्शन को रीडिफाईंग कर रहा है। यह आपके उदाहरण में ऑब्जेक्ट के लिए मूल्य प्रभावी ढंग से रीसेट करेगा। यह काम करेगा यदि आप साझा किए गए वेरिएबल चाहते हैं और यदि आप सभी ऑब्जेक्ट उदाहरणों को सामने रखते हैं, लेकिन यह बहुत जोखिम भरा लगता है

मुझे हालिया में कुछ जावास्क्रिप्ट में काम करना पड़ा था जो इस सटीक विरोधी-पैटर्न के कारण था। यह विशेष ऑब्जेक्ट पर एक खींचें और ड्रॉप हैंडलर सेट करने की कोशिश कर रहा था लेकिन सभी उदाहरणों के लिए यह करना था। अच्छा नही।

डौग क्रॉकफोर्ड का समाधान सबसे अच्छा है

@Kai

यह काम नहीं करेगा यदि तुम करो

 var t2 = new TestClass(); 

तो टी t2.prototypeHello टी के निजी अनुभाग तक पहुंच जाएगा।

@AnglesCrimes

नमूना कोड ठीक काम करता है, लेकिन यह वास्तव में सभी उदाहरणों द्वारा साझा एक "स्थिर" निजी सदस्य बनाता है यह समाधान मॉर्गनोड के लिए नहीं देखा जा सकता है।

अब तक मुझे निजी हेश और अतिरिक्त सफाई कार्यों के बिना यह करने का एक आसान और साफ तरीका नहीं मिला है। एक निजी सदस्य समारोह कुछ हद तक नकल किया जा सकता है:

 (function() { function Foo() { ... } Foo.prototype.bar = function() { privateFoo.call(this, blah); }; function privateFoo(blah) { // scoped to the instance by passing this to call } window.Foo = Foo; }()); 

हाँ, यह मुमकिन है। पीपीएफ डिजाइन पैटर्न सिर्फ यह हल करता है

पीपीएफ निजी प्रोटोटाइप कार्य के लिए खड़ा है। मूल पीपीएफ इन मुद्दों को हल करता है:

  1. प्रोटोटाइप फ़ंक्शन निजी इंस्टेंस डेटा तक पहुंच प्राप्त करते हैं।
  2. प्रोटोटाइप फ़ंक्शंस निजी बना सकते हैं

पहले के लिए, बस:

  1. सभी निजी इंस्टेंस वेरिएबल्स रखें जिन्हें आप एक अलग डेटा कंटेनर के अंदर प्रोटोटाइप फ़ंक्शन से एक्सेस करना चाहते हैं, और
  2. पैरामीटर के रूप में सभी प्रोटोटाइप फ़ंक्शंस में डेटा कंटेनर का एक संदर्भ पास करें

यह इत्ना आसान है। उदाहरण के लिए:

 // Helper class to store private data. function Data() {}; // Object constructor function Point(x, y) { // container for private vars: all private vars go here // we want x, y be changeable via methods only var data = new Data; data.x = x; data.y = y; ... } // Prototype functions now have access to private instance data Point.prototype.getX = function(data) { return data.x; } Point.prototype.getY = function(data) { return data.y; } 

पूरी कहानी यहां पढ़ें:

पीपीएफ डिजाइन पैटर्न

आप वास्तव में एक्सेसर सत्यापन का उपयोग कर इसे प्राप्त कर सकते हैं:

 (function(key, global) { // Creates a private data accessor function. function _(pData) { return function(aKey) { return aKey === key && pData; }; } // Private data accessor verifier. Verifies by making sure that the string // version of the function looks normal and that the toString function hasn't // been modified. NOTE: Verification can be duped if the rogue code replaces // Function.prototype.toString before this closure executes. function $(me) { if(me._ + '' == _asString && me._.toString === _toString) { return me._(key); } } var _asString = _({}) + '', _toString = _.toString; // Creates a Person class. var PersonPrototype = (global.Person = function(firstName, lastName) { this._ = _({ firstName : firstName, lastName : lastName }); }).prototype; PersonPrototype.getName = function() { var pData = $(this); return pData.firstName + ' ' + pData.lastName; }; PersonPrototype.setFirstName = function(firstName) { var pData = $(this); pData.firstName = firstName; return this; }; PersonPrototype.setLastName = function(lastName) { var pData = $(this); pData.lastName = lastName; return this; }; })({}, this); var chris = new Person('Chris', 'West'); alert(chris.setFirstName('Christopher').setLastName('Webber').getName()); 

यह उदाहरण प्रोटोटाइप फ़ंक्शंस और निजी डेटा के बारे में मेरी पोस्ट से आता है और इसे और अधिक विस्तार से समझाया गया है।

वर्तमान जावास्क्रिप्ट में, मैं निश्चित रूप से यह निश्चित है कि निजी राज्य का एकमात्र तरीका है, प्रोटोटाइप कार्यों से सुलभ है, बिना कुछ भी जनता को जोड़ता है जवाब "कमजोर नक्शा" पैटर्न का उपयोग करना है

इसे एकत्र करने के लिए: Person वर्ग के पास एक कमजोर मानचित्र है, जहां कुंजी व्यक्ति के उदाहरण हैं, और मान सादे ऑब्जेक्ट हैं जो निजी स्टोरेज के लिए उपयोग किए जाते हैं।

यहां एक पूर्ण कार्यात्मक उदाहरण है: ( http://jsfiddle.net/ScottRippey/BLNVr/ पर खेलते हैं)

 var Person = (function() { var _ = weakMap(); // Now, _(this) returns an object, used for private storage. var Person = function(first, last) { // Assign private storage: _(this).firstName = first; _(this).lastName = last; } Person.prototype = { fullName: function() { // Retrieve private storage: return _(this).firstName + _(this).lastName; }, firstName: function() { return _(this).firstName; }, destroy: function() { // Free up the private storage: _(this, true); } }; return Person; })(); function weakMap() { var instances=[], values=[]; return function(instance, destroy) { var index = instances.indexOf(instance); if (destroy) { // Delete the private state: instances.splice(index, 1); return values.splice(index, 1)[0]; } else if (index === -1) { // Create the private state: instances.push(instance); values.push({}); return values[values.length - 1]; } else { // Return the private state: return values[index]; } }; } 

जैसे मैंने कहा, यह वास्तव में सभी 3 भागों को प्राप्त करने का एकमात्र तरीका है।

हालांकि, दो चेतावनियां हैं सबसे पहले, यह लागत प्रदर्शन – हर बार जब आप निजी डेटा का उपयोग करते हैं, तो यह एक O(n) ऑपरेशन है, जहां n उदाहरणों की संख्या है तो आप ऐसा नहीं करना चाहेंगे, अगर आपके पास बड़ी संख्या में उदाहरण हैं दूसरा, जब आप एक उदाहरण के साथ कर लेंगे, तो आपको destroy करना चाहिए; अन्यथा, उदाहरण और डेटा एकत्र कचरा नहीं होगा, और आप मेमोरी रिसाव के साथ समाप्त होंगे I

और यही कारण है कि मेरा मूल जवाब, "आपको नहीं करना चाहिए" , कुछ ऐसा है जिसे मैं छड़ी करना चाहता हूं

bind और call पद्धतियों के उपयोग का लाभ उठाने का एक आसान तरीका है।

किसी वस्तु में निजी चर को सेट करके, आप उस ऑब्जेक्ट के दायरे का लाभ उठा सकते हैं।

उदाहरण

 function TestClass (value) { // The private value(s) var _private = { value: value }; // `bind` creates a copy of `getValue` when the object is instantiated this.getValue = TestClass.prototype.getValue.bind(_private); // Use `call` in another function if the prototype method will possibly change this.getValueDynamic = function() { return TestClass.prototype.getValue.call(_private); }; }; TestClass.prototype.getValue = function() { return this.value; }; 

इस विधि में कमियां नहीं हैं चूंकि दायरे के संदर्भ को प्रभावी रूप से ओवरराइड किया जा रहा है, इसलिए आपके पास _private वस्तु के बाहर का उपयोग नहीं है। हालांकि, यह अभी भी असंभव नहीं है, हालांकि अभी भी उदाहरण ऑब्जेक्ट के दायरे तक पहुंच प्रदान करते हैं। आप ऑब्जेक्ट के संदर्भ में ( this ) दूसरे आर्गेंट के रूप में bind कर सकते bind या फिर प्रोटोटाइप फ़ंक्शन में सार्वजनिक मानों तक पहुँच प्राप्त करने के लिए call कर सकते हैं।

सार्वजनिक मूल्यों तक पहुंच

 function TestClass (value) { var _private = { value: value }; this.message = "Hello, "; this.getMessage = TestClass.prototype.getMessage.bind(_private, this); } TestClass.prototype.getMessage = function(_public) { // Can still access passed in arguments // eg – test.getValues('foo'), 'foo' is the 2nd argument to the method console.log([].slice.call(arguments, 1)); return _public.message + this.value; }; var test = new TestClass("World"); test.getMessage(1, 2, 3); // [1, 2, 3] (console.log) // => "Hello, World" (return value) test.message = "Greetings, "; test.getMessage(); // [] (console.log) // => "Greetings, World" (return value) 

कोशिश करो!

  function Potatoe(size) { var _image = new Image(); _image.src = 'potatoe_'+size+'.png'; function getImage() { if (getImage.caller == null || getImage.caller.owner != Potatoe.prototype) throw new Error('This is a private property.'); return _image; } Object.defineProperty(this,'image',{ configurable: false, enumerable: false, get : getImage }); Object.defineProperty(this,'size',{ writable: false, configurable: false, enumerable: true, value : size }); } Potatoe.prototype.draw = function(ctx,x,y) { //ctx.drawImage(this.image,x,y); console.log(this.image); } Potatoe.prototype.draw.owner = Potatoe.prototype; var pot = new Potatoe(32); console.log('Potatoe size: '+pot.size); try { console.log('Potatoe image: '+pot.image); } catch(e) { console.log('Oops: '+e); } pot.draw(); 

यहाँ है जो मैं साथ आया था।

 (function () { var staticVar = 0; var yrObj = function () { var private = {"a":1,"b":2}; var MyObj = function () { private.a += staticVar; staticVar++; }; MyObj.prototype = { "test" : function () { console.log(private.a); } }; return new MyObj; }; window.YrObj = yrObj; }()); var obj1 = new YrObj; var obj2 = new YrObj; obj1.test(); // 1 obj2.test(); // 2 

इस क्रियान्वयन के साथ मुख्य समस्या यह है कि यह हर instanciation पर प्रोटोटाइप को फिर से परिभाषित करता है।

ऐसा करने का एक बहुत आसान तरीका है

 function SharedPrivate(){ var private = "secret"; this.constructor.prototype.getP = function(){return private} this.constructor.prototype.setP = function(v){ private = v;} } var o1 = new SharedPrivate(); var o2 = new SharedPrivate(); console.log(o1.getP()); // secret console.log(o2.getP()); // secret o1.setP("Pentax Full Frame K1 is on sale..!"); console.log(o1.getP()); // Pentax Full Frame K1 is on sale..! console.log(o2.getP()); // Pentax Full Frame K1 is on sale..! o2.setP("And it's only for $1,795._"); console.log(o1.getP()); // And it's only for $1,795._ 

जावास्क्रिप्ट प्रोटोटाइप गोल्डन हैं

मैं पार्टी में देर कर रहा हूं, लेकिन मुझे लगता है कि मैं योगदान कर सकता हूं। यहां, इसे देखें:

 // 1. Create closure var SomeClass = function() { // 2. Create `key` inside a closure var key = {}; // Function to create private storage var private = function() { var obj = {}; // return Function to access private storage using `key` return function(testkey) { if(key === testkey) return obj; // If `key` is wrong, then storage cannot be accessed console.error('Cannot access private properties'); return undefined; }; }; var SomeClass = function() { // 3. Create private storage this._ = private(); // 4. Access private storage using the `key` this._(key).priv_prop = 200; }; SomeClass.prototype.test = function() { console.log(this._(key).priv_prop); // Using property from prototype }; return SomeClass; }(); // Can access private property from within prototype var instance = new SomeClass(); instance.test(); // `200` logged // Cannot access private property from outside of the closure var wrong_key = {}; instance._(wrong_key); // undefined; error logged 

इस समस्या के लिए सबसे आसान समाधान खोजने की कोशिश करते हुए मैं यहाँ कुछ आया हूं, शायद यह किसी के लिए उपयोगी हो सकता है मैं जावास्क्रिप्ट के लिए नया हूँ, इसलिए कोड के साथ कुछ समस्याएं हो सकती हैं।

 // pseudo-class definition scope (function () { // this is used to identify 'friend' functions defined within this scope, // while not being able to forge valid parameter for GetContext() // to gain 'private' access from outside var _scope = new (function () { })(); // ----------------------------------------------------------------- // pseudo-class definition this.Something = function (x) { // 'private' members are wrapped into context object, // it can be also created with a function var _ctx = Object.seal({ // actual private members Name: null, Number: null, Somefunc: function () { console.log('Something(' + this.Name + ').Somefunc(): number = ' + this.Number); } }); // ----------------------------------------------------------------- // function below needs to be defined in every class // to allow limited access from prototype this.GetContext = function (scope) { if (scope !== _scope) throw 'access'; return _ctx; } // ----------------------------------------------------------------- { // initialization code, if any _ctx.Name = (x !== 'undefined') ? x : 'default'; _ctx.Number = 0; Object.freeze(this); } } // ----------------------------------------------------------------- // prototype is defined only once this.Something.prototype = Object.freeze({ // public accessors for 'private' field get Number() { return this.GetContext(_scope).Number; }, set Number(v) { this.GetContext(_scope).Number = v; }, // public function making use of some private fields Test: function () { var _ctx = this.GetContext(_scope); // access 'private' field console.log('Something(' + _ctx.Name + ').Test(): ' + _ctx.Number); // call 'private' func _ctx.Somefunc(); } }); // ----------------------------------------------------------------- // wrap is used to hide _scope value and group definitions }).call(this); function _A(cond) { if (cond !== true) throw new Error('assert failed'); } // ----------------------------------------------------------------- function test_smth() { console.clear(); var smth1 = new Something('first'), smth2 = new Something('second'); //_A(false); _A(smth1.Test === smth2.Test); smth1.Number = 3; smth2.Number = 5; console.log('smth1.Number: ' + smth1.Number + ', smth2.Number: ' + smth2.Number); smth1.Number = 2; smth2.Number = 6; smth1.Test(); smth2.Test(); try { var ctx = smth1.GetContext(); } catch (err) { console.log('error: ' + err); } } test_smth(); 

आज मुझे एक ही सवाल का सामना करना पड़ा और स्कॉट रिप्पी प्रथम श्रेणी की प्रतिक्रिया पर विस्तार के बाद, मैं एक बहुत ही सरल समाधान (आईएमएचओ) के साथ आया जो ईएस 5 और कुशल दोनों के साथ संगत है, यह भी नाम संघर्ष है (_private का प्रयोग करना असुरक्षित लगता है) ।

 /*jslint white: true, plusplus: true */ /*global console */ var a, TestClass = (function(){ "use strict"; function PrefixedCounter (prefix) { var counter = 0; this.count = function () { return prefix + (++counter); }; } var TestClass = (function(){ var cls, pc = new PrefixedCounter("_TestClass_priv_") , privateField = pc.count() ; cls = function(){ this[privateField] = "hello"; this.nonProtoHello = function(){ console.log(this[privateField]); }; }; cls.prototype.prototypeHello = function(){ console.log(this[privateField]); }; return cls; }()); return TestClass; }()); a = new TestClass(); a.nonProtoHello(); a.prototypeHello(); 

रिंगोज और नोडजे के साथ परीक्षण किया गया। I'm eager to read your opinion.

 var getParams = function(_func) { res = _func.toString().split('function (')[1].split(')')[0].split(',') return res } function TestClass(){ var private = {hidden: 'secret'} //clever magic accessor thing goes here if ( !(this instanceof arguments.callee) ) { for (var key in arguments) { if (typeof arguments[key] == 'function') { var keys = getParams(arguments[key]) var params = [] for (var i = 0; i <= keys.length; i++) { if (private[keys[i]] != undefined) { params.push(private[keys[i]]) } } arguments[key].apply(null,params) } } } } TestClass.prototype.test = function(){ var _hidden; //variable I want to get TestClass(function(hidden) {_hidden = hidden}) //invoke magic to get }; new TestClass().test() 

How's this? Using an private accessor. Only allows you to get the variables though not to set them, depends on the use case.

I have one solution, but I am not sure it is without flaws.

For it to work, you have to use the following structure:

  1. Use 1 private object that contains all private variables.
  2. Use 1 instance function.
  3. Apply a closure to the constructor and all prototype functions.
  4. Any instance created is done outside the closure defined.

यहां कोड है:

 var TestClass = (function () { // difficult to be guessed. var hash = Math.round(Math.random() * Math.pow(10, 13) + + new Date()); var TestClass = function () { var privateFields = { field1: 1, field2: 2 }; this.getPrivateFields = function (hashed) { if(hashed !== hash) { throw "Cannot access private fields outside of object."; // or return null; } return privateFields; }; }; TestClass.prototype.prototypeHello = function () { var privateFields = this.getPrivateFields(hash); privateFields.field1 = Math.round(Math.random() * 100); privateFields.field2 = Math.round(Math.random() * 100); }; TestClass.prototype.logField1 = function () { var privateFields = this.getPrivateFields(hash); console.log(privateFields.field1); }; TestClass.prototype.logField2 = function () { var privateFields = this.getPrivateFields(hash); console.log(privateFields.field2); }; return TestClass; })(); 

How this works is that it provides an instance function "this.getPrivateFields" to access the "privateFields" private variables object, but this function will only return the "privateFields" object inside the main closure defined (also prototype functions using "this.getPrivateFields" need to be defined inside this closure).

A hash produced during runtime and difficult to be guessed is used as parameters to make sure that even if "getPrivateFields" is called outside the scope of closure will not return the "privateFields" object.

The drawback is that we can not extend TestClass with more prototype functions outside the closure.

Here is some test code:

 var t1 = new TestClass(); console.log('Initial t1 field1 is: '); t1.logField1(); console.log('Initial t1 field2 is: '); t1.logField2(); t1.prototypeHello(); console.log('t1 field1 is now: '); t1.logField1(); console.log('t1 field2 is now: '); t1.logField2(); var t2 = new TestClass(); console.log('Initial t2 field1 is: '); t2.logField1(); console.log('Initial t2 field2 is: '); t2.logField2(); t2.prototypeHello(); console.log('t2 field1 is now: '); t2.logField1(); console.log('t2 field2 is now: '); t2.logField2(); console.log('t1 field1 stays: '); t1.logField1(); console.log('t1 field2 stays: '); t1.logField2(); t1.getPrivateFields(11233); 

EDIT: Using this method, it is also possible to "define" private functions.

 TestClass.prototype.privateFunction = function (hashed) { if(hashed !== hash) { throw "Cannot access private function."; } }; TestClass.prototype.prototypeHello = function () { this.privateFunction(hash); }; 

Was playing around with this today and this was the only solution I could find without using Symbols. Best thing about this is it can actually all be completely private.

The solution is based around a homegrown module loader which basically becomes the mediator for a private storage cache (using a weak map).

  const loader = (function() { function ModuleLoader() {} //Static, accessible only if truly needed through obj.constructor.modules //Can also be made completely private by removing the ModuleLoader prefix. ModuleLoader.modulesLoaded = 0; ModuleLoader.modules = {} ModuleLoader.prototype.define = function(moduleName, dModule) { if (moduleName in ModuleLoader.modules) throw new Error('Error, duplicate module'); const module = ModuleLoader.modules[moduleName] = {} module.context = { __moduleName: moduleName, exports: {} } //Weak map with instance as the key, when the created instance is garbage collected or goes out of scope this will be cleaned up. module._private = { private_sections: new WeakMap(), instances: [] }; function private(action, instance) { switch (action) { case "create": if (module._private.private_sections.has(instance)) throw new Error('Cannot create private store twice on the same instance! check calls to create.') module._private.instances.push(instance); module._private.private_sections.set(instance, {}); break; case "delete": const index = module._private.instances.indexOf(instance); if (index == -1) throw new Error('Invalid state'); module._private.instances.slice(index, 1); return module._private.private_sections.delete(instance); break; case "get": return module._private.private_sections.get(instance); break; default: throw new Error('Invalid action'); break; } } dModule.call(module.context, private); ModuleLoader.modulesLoaded++; } ModuleLoader.prototype.remove = function(moduleName) { if (!moduleName in (ModuleLoader.modules)) return; /* Clean up as best we can. */ const module = ModuleLoader.modules[moduleName]; module.context.__moduleName = null; module.context.exports = null; module.cotext = null; module._private.instances.forEach(function(instance) { module._private.private_sections.delete(instance) }); for (let i = 0; i < module._private.instances.length; i++) { module._private.instances[i] = undefined; } module._private.instances = undefined; module._private = null; delete ModuleLoader.modules[moduleName]; ModuleLoader.modulesLoaded -= 1; } ModuleLoader.prototype.require = function(moduleName) { if (!(moduleName in ModuleLoader.modules)) throw new Error('Module does not exist'); return ModuleLoader.modules[moduleName].context.exports; } return new ModuleLoader(); })(); loader.define('MyModule', function(private_store) { function MyClass() { //Creates the private storage facility. Called once in constructor. private_store("create", this); //Retrieve the private storage object from the storage facility. private_store("get", this).no = 1; } MyClass.prototype.incrementPrivateVar = function() { private_store("get", this).no += 1; } MyClass.prototype.getPrivateVar = function() { return private_store("get", this).no; } this.exports = MyClass; }) //Get whatever is exported from MyModule const MyClass = loader.require('MyModule'); //Create a new instance of `MyClass` const myClass = new MyClass(); //Create another instance of `MyClass` const myClass2 = new MyClass(); //print out current private vars console.log('pVar = ' + myClass.getPrivateVar()) console.log('pVar2 = ' + myClass2.getPrivateVar()) //Increment it myClass.incrementPrivateVar() //Print out to see if one affected the other or shared console.log('pVar after increment = ' + myClass.getPrivateVar()) console.log('pVar after increment on other class = ' + myClass2.getPrivateVar()) //Clean up. loader.remove('MyModule') 

I'm just new to javascripting (I need to get acquainted with it) . I stumbled on the same question. For now I would go for a small lightweight wrapper function. This way each new instance will only reimplement the wrapper.

I think it should be something like this:

 // your class function TestClass() { // your field this.privateField = "hello"; // create a local reference to this, // because 'this' in the wrapper function will not be a TestClass var self = this; // implement the wrapper function and pass the 'self' to the static version this.showHello = () => TestClass.showHello(self); } // implement the 'big/complex' functionallity static. The wrapper will pass the instance TestClass.showHello = function(self) { alert(self.privateField); } 

उपयोग:

 var t = new TestClass(); t.showHello(); 

You could even call the static method:

 TestClass.showHello(t); 

Can't you put the variables in a higher scope?

 (function () { var privateVariable = true; var MyClass = function () { if (privateVariable) console.log('readable from private scope!'); }; MyClass.prototype.publicMethod = function () { if (privateVariable) console.log('readable from public scope!'); }; }))(); 

You can also try to add method not directly on prototype, but on constructor function like this:

 var MyArray = function() { var array = []; this.add = MyArray.add.bind(null, array); this.getAll = MyArray.getAll.bind(null, array); } MyArray.add = function(array, item) { array.push(item); } MyArray.getAll = function(array) { return array; } var myArray1 = new MyArray(); myArray1.add("some item 1"); console.log(myArray1.getAll()); // ['some item 1'] var myArray2 = new MyArray(); myArray2.add("some item 2"); console.log(myArray2.getAll()); // ['some item 2'] console.log(myArray1.getAll()); // ['some item 2'] - FINE! 

You can use a prototype assignment within the constructor definition.

The variable will be visible to the prototype added method but all the instances of the functions will access the same SHARED variable.

 function A() { var sharedVar = 0; this.local = ""; A.prototype.increment = function(lval) { if (lval) this.local = lval; alert((++sharedVar) + " while this.p is still " + this.local); } } var a = new A(); var b = new A(); a.increment("I belong to a"); b.increment("I belong to b"); a.increment(); b.increment(); 

I hope this can be usefull.