खोज…
वाक्य - विन्यास
- कक्षा फू {}
- कक्षा फू का विस्तार बार {}
- कक्षा फू {कंस्ट्रक्टर () {}}
- कक्षा फू {myMethod () {}}
- कक्षा फू {{myProperty () {}} प्राप्त करें
- कक्षा फू {सेट मायप्रॉपीटी (न्यूवैल्यू) {}}
- कक्षा फू {स्थिर myStaticMethod () {}}
- कक्षा फू {स्थिर हो जाओ myStaticProperty () {}}
- const फू = वर्ग फू {};
- const फू = वर्ग {};
टिप्पणियों
class
समर्थन केवल जावास्क्रिप्ट के लिए 2015 es6 मानक के हिस्से के रूप में जोड़ा गया था।
जावास्क्रिप्ट की पहले से मौजूद प्रोटोटाइप-आधारित विरासत पर जावास्क्रिप्ट कक्षाएं सिंथेटिक चीनी हैं। यह नया वाक्यविन्यास जावास्क्रिप्ट के लिए एक नया ऑब्जेक्ट-ओरिएंटेड इनहेरिटेंस मॉडल पेश नहीं करता है, बस वस्तुओं और विरासत से निपटने का एक सरल तरीका है। एक class
डिक्लेरेशन अनिवार्य रूप से एक कंस्ट्रक्टर function
को मैन्युअल रूप से परिभाषित करने और कंस्ट्रक्टर के प्रोटोटाइप में गुण जोड़ने के लिए एक शॉर्टहैंड है। एक महत्वपूर्ण अंतर यह है कि फ़ंक्शंस को सीधे ( new
कीवर्ड के बिना) कहा जा सकता है, जबकि एक वर्ग जिसे सीधे बुलाया जाता है, अपवाद को फेंक देगा।
class someClass {
constructor () {}
someMethod () {}
}
console.log(typeof someClass);
console.log(someClass);
console.log(someClass === someClass.prototype.constructor);
console.log(someClass.prototype.someMethod);
// Output:
// function
// function someClass() { "use strict"; }
// true
// function () { "use strict"; }
यदि आप जावास्क्रिप्ट के पुराने संस्करण का उपयोग कर रहे हैं, तो आपको कोड को एक संस्करण में संकलित करने के लिए बेबल या गूगल-क्लोजर-कंपाइलर जैसे एक ट्रांसपिलर की आवश्यकता होगी जो लक्ष्य प्लेटफ़ॉर्म को समझने में सक्षम होगा।
कक्षा का निर्माण करनेवाला
अधिकांश वर्गों का मूलभूत हिस्सा इसका निर्माता है, जो प्रत्येक उदाहरण की प्रारंभिक स्थिति सेट करता है और new
कॉल करते समय पारित किए गए किसी भी पैरामीटर को संभालता है।
इसे एक class
ब्लॉक में परिभाषित किया गया है, हालांकि आप constructor
नामक एक विधि को परिभाषित कर रहे हैं, हालांकि इसे वास्तव में एक विशेष मामले के रूप में नियंत्रित किया जाता है।
class MyClass {
constructor(option) {
console.log(`Creating instance using ${option} option.`);
this.option = option;
}
}
उदाहरण उपयोग:
const foo = new MyClass('speedy'); // logs: "Creating instance using speedy option"
एक छोटी सी बात यह है कि एक क्लास कंस्ट्रक्टर को static
कीवर्ड के माध्यम से static
नहीं बनाया जा सकता है, जैसा कि अन्य विधियों के लिए नीचे वर्णित है।
स्थैतिक तरीके
स्थैतिक विधियों और गुणों को वर्ग / कंस्ट्रक्टर पर ही परिभाषित किया जाता है , उदाहरण के लिए वस्तुओं पर नहीं। ये static
कीवर्ड का उपयोग करके एक वर्ग परिभाषा में निर्दिष्ट हैं।
class MyClass {
static myStaticMethod() {
return 'Hello';
}
static get myStaticProperty() {
return 'Goodbye';
}
}
console.log(MyClass.myStaticMethod()); // logs: "Hello"
console.log(MyClass.myStaticProperty); // logs: "Goodbye"
हम देख सकते हैं कि स्थैतिक गुण वस्तु उदाहरणों पर परिभाषित नहीं हैं:
const myClassInstance = new MyClass();
console.log(myClassInstance.myStaticProperty); // logs: undefined
हालांकि, वे उपवर्गों पर परिभाषित हैं :
class MySubClass extends MyClass {};
console.log(MySubClass.myStaticMethod()); // logs: "Hello"
console.log(MySubClass.myStaticProperty); // logs: "Goodbye"
गेटर्स एंड सेटर्स
गेटर्स और सेटर आपको अपनी कक्षा में दी गई संपत्ति को पढ़ने और लिखने के लिए कस्टम व्यवहार को परिभाषित करने की अनुमति देते हैं। उपयोगकर्ता के लिए, वे किसी भी विशिष्ट संपत्ति के समान दिखाई देते हैं। हालाँकि, आंतरिक रूप से आपके द्वारा प्रदान किया जाने वाला एक कस्टम फ़ंक्शन का उपयोग मूल्य को निर्धारित करने के लिए किया जाता है जब संपत्ति (गटर) तक पहुँचा जाता है, और किसी भी आवश्यक परिवर्तन के लिए प्रीफ़ॉर्म किया जाता है जब संपत्ति (सेटर) असाइन की जाती है।
एक में class
परिभाषा, एक गेटर लगाया जाता नो तर्क विधि की तरह लिखा है get
कीवर्ड। एक सेटर समान है, सिवाय इसके कि यह एक तर्क (नया मान दिया जा रहा है) को स्वीकार करता है और इसके बजाय set
कीवर्ड का उपयोग किया जाता है।
यहां एक उदाहरण वर्ग दिया गया है जो अपनी .name
संपत्ति के लिए एक गेट्टर और सेटर प्रदान करता है। जब भी इसे सौंपा जाएगा, हम नए नाम को आंतरिक .names_
array में रिकॉर्ड करेंगे। जितनी बार यह एक्सेस किया जाता है, हम नवीनतम नाम वापस करेंगे।
class MyClass {
constructor() {
this.names_ = [];
}
set name(value) {
this.names_.push(value);
}
get name() {
return this.names_[this.names_.length - 1];
}
}
const myClassInstance = new MyClass();
myClassInstance.name = 'Joe';
myClassInstance.name = 'Bob';
console.log(myClassInstance.name); // logs: "Bob"
console.log(myClassInstance.names_); // logs: ["Joe", "Bob"]
यदि आप केवल एक सेटर को परिभाषित करते हैं, तो संपत्ति तक पहुंचने का प्रयास हमेशा undefined
रहेगा।
const classInstance = new class {
set prop(value) {
console.log('setting', value);
}
};
classInstance.prop = 10; // logs: "setting", 10
console.log(classInstance.prop); // logs: undefined
यदि आप केवल एक गेटर को परिभाषित करते हैं, तो संपत्ति को आवंटित करने के प्रयास का कोई प्रभाव नहीं होगा।
const classInstance = new class {
get prop() {
return 5;
}
};
classInstance.prop = 10;
console.log(classInstance.prop); // logs: 5
कक्षा में प्रवेश
वंशानुक्रम उसी तरह काम करता है जैसे वह अन्य वस्तु-उन्मुख भाषाओं में करता है: सुपरक्लास पर परिभाषित विधियाँ उप-उपवर्ग में सुलभ हैं।
यदि उपवर्ग अपना खुद का कंस्ट्रक्टर घोषित करता है, तो उसे this
तक पहुंचने से पहले super()
माध्यम से माता-पिता के कंस्ट्रक्टर को आमंत्रित करना होगा।
class SuperClass {
constructor() {
this.logger = console.log;
}
log() {
this.logger(`Hello ${this.name}`);
}
}
class SubClass extends SuperClass {
constructor() {
super();
this.name = 'subclass';
}
}
const subClass = new SubClass();
subClass.log(); // logs: "Hello subclass"
निजी सदस्य
भाषा की विशेषता के रूप में जावास्क्रिप्ट निजी सदस्यों का तकनीकी रूप से समर्थन नहीं करता है। डगलस क्रॉकफोर्ड द्वारा वर्णित गोपनीयता - को क्लोजर (संरक्षित फंक्शन स्कोप) के माध्यम से इसके बजाय उत्सर्जित किया जाता है जो कि एक कंस्ट्रक्टर फ़ंक्शन के प्रत्येक इंस्टेंटेशन कॉल के साथ उत्पन्न होगा।
Queue
उदाहरण यह दर्शाता है कि, कंस्ट्रक्टर कार्यों के साथ, स्थानीय राज्य को संरक्षित किया जा सकता है और विशेषाधिकार प्राप्त तरीकों के माध्यम से भी सुलभ बनाया जा सकता है।
class Queue {
constructor () { // - does generate a closure with each instantiation.
const list = []; // - local state ("private member").
this.enqueue = function (type) { // - privileged public method
// accessing the local state
list.push(type); // "writing" alike.
return type;
};
this.dequeue = function () { // - privileged public method
// accessing the local state
return list.shift(); // "reading / writing" alike.
};
}
}
var q = new Queue; //
//
q.enqueue(9); // ... first in ...
q.enqueue(8); //
q.enqueue(7); //
//
console.log(q.dequeue()); // 9 ... first out.
console.log(q.dequeue()); // 8
console.log(q.dequeue()); // 7
console.log(q); // {}
console.log(Object.keys(q)); // ["enqueue","dequeue"]
एक Queue
प्रकार के हर पल के साथ निर्माण एक बंद उत्पन्न करता है।
इस प्रकार एक के दोनों Queue
प्रकार के अपने तरीकों enqueue
और dequeue
(देखें Object.keys(q)
) अभी भी करने के लिए उपयोग की क्या ज़रूरत list
है कि इसका आवरण दायरे में रहने के लिए है कि, निर्माण समय में, संरक्षित किया गया है जारी है।
इस पद्धति का इस्तेमाल कर रही - विशेषाधिकार प्राप्त सार्वजनिक विधियों के माध्यम से निजी सदस्यों की नकल - एक है कि, हर मामले के साथ, अतिरिक्त मेमोरी हर अपनी संपत्ति विधि के लिए भस्म हो जाएगा ध्यान में रखना चाहिए (यह कोड है कि साझा नहीं किया जा सकता / पुन: उपयोग किया है के लिए)। राज्य की राशि / आकार के लिए भी यही सच है जो इस तरह के बंद होने के भीतर संग्रहीत होने जा रहा है।
गतिशील विधि नाम
जब आप किसी वस्तु के गुणों को []
साथ कैसे एक्सेस कर सकते हैं, इसी तरह के तरीकों का नामकरण करते समय अभिव्यक्तियों का मूल्यांकन करने की क्षमता भी होती है। यह गतिशील संपत्ति के नाम रखने के लिए उपयोगी हो सकता है, हालांकि अक्सर प्रतीकों के साथ संयोजन में उपयोग किया जाता है।
let METADATA = Symbol('metadata');
class Car {
constructor(make, model) {
this.make = make;
this.model = model;
}
// example using symbols
[METADATA]() {
return {
make: this.make,
model: this.model
};
}
// you can also use any javascript expression
// this one is just a string, and could also be defined with simply add()
["add"](a, b) {
return a + b;
}
// this one is dynamically evaluated
[1 + 2]() {
return "three";
}
}
let MazdaMPV = new Car("Mazda", "MPV");
MazdaMPV.add(4, 5); // 9
MazdaMPV[3](); // "three"
MazdaMPV[METADATA](); // { make: "Mazda", model: "MPV" }
तरीके
किसी कार्य को करने के लिए विधियों को कक्षाओं में परिभाषित किया जा सकता है और वैकल्पिक रूप से एक परिणाम लौटाया जा सकता है।
वे कॉल करने वाले से तर्क प्राप्त कर सकते हैं।
class Something {
constructor(data) {
this.data = data
}
doSomething(text) {
return {
data: this.data,
text
}
}
}
var s = new Something({})
s.doSomething("hi") // returns: { data: {}, text: "hi" }
कक्षाओं के साथ निजी डेटा का प्रबंधन
कक्षाओं का उपयोग करने वाली सबसे आम बाधाओं में से एक निजी राज्यों को संभालने के लिए उचित दृष्टिकोण है। निजी राज्यों को संभालने के लिए 4 सामान्य उपाय हैं:
प्रतीकों का उपयोग करना
MDN पर परिभाषित के रूप में प्रतीक ES2015 में पेश किए गए नए आदिम प्रकार हैं
एक प्रतीक एक अद्वितीय और अपरिवर्तनीय डेटा प्रकार है जिसका उपयोग ऑब्जेक्ट गुणों के लिए एक पहचानकर्ता के रूप में किया जा सकता है।
एक संपत्ति कुंजी के रूप में प्रतीक का उपयोग करते समय, यह गणना करने योग्य नहीं है।
जैसे, वे for var in
or Object.keys
का उपयोग करके प्रकट नहीं होंगे।
इस प्रकार हम निजी डेटा को संग्रहीत करने के लिए प्रतीकों का उपयोग कर सकते हैं।
const topSecret = Symbol('topSecret'); // our private key; will only be accessible on the scope of the module file
export class SecretAgent{
constructor(secret){
this[topSecret] = secret; // we have access to the symbol key (closure)
this.coverStory = 'just a simple gardner';
this.doMission = () => {
figureWhatToDo(topSecret[topSecret]); // we have access to topSecret
};
}
}
क्योंकि symbols
अद्वितीय हैं, हमारे पास निजी संपत्ति तक पहुंचने के लिए मूल प्रतीक का संदर्भ होना चाहिए।
import {SecretAgent} from 'SecretAgent.js'
const agent = new SecretAgent('steal all the ice cream');
// ok lets try to get the secret out of him!
Object.keys(agent); // ['coverStory'] only cover story is public, our secret is kept.
agent[Symbol('topSecret')]; // undefined, as we said, symbols are always unique, so only the original symbol will help us to get the data.
लेकिन यह 100% निजी नहीं है; चलो उस एजेंट को तोड़ दो! हम ऑब्जेक्ट प्रतीकों को प्राप्त करने के लिए Object.getOwnPropertySymbols
विधि का उपयोग कर सकते हैं।
const secretKeys = Object.getOwnPropertySymbols(agent);
agent[secretKeys[0]] // 'steal all the ice cream' , we got the secret.
WeakMaps का उपयोग करना
WeakMap
एक नई प्रकार की वस्तु है जिसे es6 के लिए जोड़ा गया है।
जैसा कि एमडीएन पर परिभाषित है
WeakMap वस्तु कुंजी / मूल्य जोड़े का एक संग्रह है जिसमें कुंजियों को कमजोर रूप से संदर्भित किया जाता है। कुंजियाँ ऑब्जेक्ट होनी चाहिए और मान मनमाने मूल्य हो सकते हैं।
WeakMap
की एक और महत्वपूर्ण विशेषता है, जैसा कि MDN पर परिभाषित किया गया है।
कमजोर मानचित्र में कुंजी को कमजोर तरीके से रखा जाता है। इसका मतलब यह है कि, यदि कुंजी का कोई अन्य मजबूत संदर्भ नहीं है, तो पूरी प्रविष्टि को कचरे के संग्रहकर्ता द्वारा WeakMap से हटा दिया जाएगा।
यह विचार है कि वीकपाइप का उपयोग पूरी कक्षा के लिए एक स्थिर नक्शे के रूप में, प्रत्येक उदाहरण को कुंजी के रूप में रखने के लिए और उस उदाहरण कुंजी के लिए निजी डेटा को एक मूल्य के रूप में रखने के लिए।
इस प्रकार केवल कक्षा के अंदर ही हमारे पास WeakMap
संग्रह तक पहुँच होगी।
आइए हमारे एजेंट को एक कोशिश दें, WeakMap
साथ:
const topSecret = new WeakMap(); // will hold all private data of all instances.
export class SecretAgent{
constructor(secret){
topSecret.set(this,secret); // we use this, as the key, to set it on our instance private data
this.coverStory = 'just a simple gardner';
this.doMission = () => {
figureWhatToDo(topSecret.get(this)); // we have access to topSecret
};
}
}
क्योंकि कॉन्स्ट topSecret
को हमारे मॉड्यूल क्लोजर के अंदर परिभाषित किया गया है, और चूंकि हमने इसे अपने इंस्टेंस प्रॉपर्टीज से नहीं topSecret
, इसलिए यह दृष्टिकोण पूरी तरह से निजी है, और हम एजेंट topSecret
तक नहीं पहुंच सकते हैं।
कंस्ट्रक्टर के अंदर सभी तरीकों को परिभाषित करें
यहां विचार बस हमारे सभी तरीकों और सदस्यों को कंस्ट्रक्टर के अंदर परिभाषित करने और निजी सदस्यों को this
तक पहुंचने के बिना बंद करने का उपयोग करने के लिए है।
export class SecretAgent{
constructor(secret){
const topSecret = secret;
this.coverStory = 'just a simple gardner';
this.doMission = () => {
figureWhatToDo(topSecret); // we have access to topSecret
};
}
}
इस उदाहरण में भी डेटा 100% निजी है और इसे कक्षा से बाहर नहीं पहुँचा जा सकता है, इसलिए हमारा एजेंट सुरक्षित है।
नामकरण सम्मेलनों का उपयोग करना
हम तय करेंगे कि कोई भी संपत्ति जो निजी है, _
साथ उपसर्ग किया जाएगा।
ध्यान दें कि इस दृष्टिकोण के लिए डेटा वास्तव में निजी नहीं है।
export class SecretAgent{
constructor(secret){
this._topSecret = secret; // it private by convention
this.coverStory = 'just a simple gardner';
this.doMission = () => {
figureWhatToDo(this_topSecret);
};
}
}
वर्ग नाम बंधन
ClassDeclaration का नाम अलग-अलग तरीकों से अलग-अलग तरीकों से बंधा हुआ है -
- वर्ग को जिस दायरे में परिभाषित किया गया है - बाध्यकारी
let
- वर्ग का दायरा -
{
}
भीतर औरclass {}
-const
बाइंडिंग में है
class Foo {
// Foo inside this block is a const binding
}
// Foo here is a let binding
उदाहरण के लिए,
class A {
foo() {
A = null; // will throw at runtime as A inside the class is a `const` binding
}
}
A = null; // will NOT throw as A here is a `let` binding
यह एक फंक्शन के लिए समान नहीं है -
function A() {
A = null; // works
}
A.prototype.foo = function foo() {
A = null; // works
}
A = null; // works