ES2015 (ES6) `वर्ग` सिंटैक्स क्या लाभ प्रदान करता है?


87

ईएस 6 कक्षाओं के बारे में मेरे कई सवाल हैं।

classवाक्य रचना का उपयोग करने का क्या लाभ है ? मैंने पढ़ा कि सार्वजनिक / निजी / स्थैतिक ES7 का हिस्सा होगा, क्या यह एक कारण है?

इसके अलावा, classओओपी का एक अलग प्रकार है या यह अभी भी जावास्क्रिप्ट की प्रोटोटाइप विरासत है? क्या मैं इसका उपयोग करके संशोधित कर सकता हूं .prototype? या यह सिर्फ एक ही वस्तु है लेकिन इसे घोषित करने के दो अलग-अलग तरीके हैं।

गति लाभ हैं? हो सकता है कि अगर आपके पास बड़े एप्लिकेशन जैसे बड़े एप्लिकेशन हैं, तो इसे बनाए रखना / समझना आसान है?


बस मेरी अपनी राय: नए वाक्यविन्यास को समझना बहुत आसान है और इसके लिए बहुत पहले के अनुभव की आवश्यकता नहीं होगी (विशेषकर चूंकि अधिकांश लोग ओओपी भाषा से आए होंगे)। लेकिन प्रोटोटाइप ऑब्जेक्ट मॉडल जानने लायक है और आप कभी भी यह नहीं जान पाएंगे कि नए सिंटैक्स का उपयोग करना, इसके अलावा, प्रोटोटाइप कोड पर काम करना अधिक चुनौतीपूर्ण होगा जब तक कि आप पहले से ही इसे नहीं जानते। इसलिए मेरे पास पुराने सिंटेक्स के साथ अपना खुद का कोड लिखने का विकल्प होगा, जब मेरे पास वह विकल्प होगा
Zach Smith

जवाबों:


120

नया classसिंटैक्स अभी के लिए , ज्यादातर सिंटैक्टिक शुगर है। (लेकिन, आप जानते हैं, चीनी की अच्छी किस्म।) ES2015-ES2020 में ऐसा कुछ भी नहीं classहै जो आप कर सकते हैं कि आप निर्माण कार्यों और Reflect.construct(उपवर्ग Errorऔर including सहित Array) के साथ नहीं कर सकते । (यह है की संभावना देखते ES2021 में कुछ चीजें है कि आप के साथ कर सकते हो जाएगा classकि आप अन्यथा नहीं कर सकते: निजी क्षेत्रों , निजी तरीकों , और स्थिर क्षेत्रों / निजी स्थिर तरीकों ।)

इसके अलावा, classओओपी का एक अलग प्रकार है या यह अभी भी जावास्क्रिप्ट की प्रोटोटाइप विरासत है?

यदि आप कंस्ट्रक्टर फ़ंक्शंस ( new Fooआदि) का उपयोग करना पसंद करते हैं, तो यह वही प्रोटोटाइपिक विरासत है जो हमारे पास हमेशा होती है, बस क्लीनर और अधिक सुविधाजनक सिंटैक्स के साथ । (विशेष रूप से Arrayया Errorजिसे आप ES5 और पहले नहीं कर सकते थे, से प्राप्त करने के मामले में । अब आप Reflect.construct[ युक्ति , MDN ] के साथ कर सकते हैं , लेकिन पुराने ES5- शैली के साथ नहीं।)

क्या मैं इसका उपयोग करके संशोधित कर सकता हूं .prototype?

हाँ, आप prototypeक्लास बनाने के बाद भी क्लास के कंस्ट्रक्टर पर ऑब्जेक्ट को संशोधित कर सकते हैं । जैसे, यह पूरी तरह से कानूनी है:

class Foo {
    constructor(name) {
        this.name = name;
    }
    
    test1() {
        console.log("test1: name = " + this.name);
    }
}
Foo.prototype.test2 = function() {
    console.log("test2: name = " + this.name);
};

गति लाभ हैं?

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

ES2015 (ES6) classसिंटैक्स क्या लाभ प्रदान करता है?

संक्षेप में: आप पहली जगह में निर्माता कार्यों का उपयोग नहीं करते हैं, पसंद करते हैं Object.createया इसी तरह, classआप के लिए उपयोगी नहीं है।

यदि आप निर्माण कार्यों का उपयोग करते हैं, तो इसके कुछ लाभ हैं class:

  • वाक्यविन्यास सरल और कम त्रुटि-प्रवण है।

  • यह बहुत आसान (और फिर, त्रुटि-रहित होता) वर्ष के साथ की तुलना में नए सिंटैक्स का उपयोग विरासत पदानुक्रम स्थापित करने के लिए।

  • classआपको newकंस्ट्रक्टर फ़ंक्शन के साथ उपयोग करने में विफल होने की सामान्य त्रुटि से बचाव करता है (यदि कंस्ट्रक्टर thisएक वैध ऑब्जेक्ट नहीं है, तो कंस्ट्रक्टर ने एक अपवाद फेंक दिया है)।

  • किसी विधि के मूल प्रोटोटाइप के संस्करण को कॉल करना पुराने ( या के super.method()बजाय ) की तुलना में नए सिंटैक्स के साथ बहुत सरल है ।ParentConstructor.prototype.method.call(this)Object.getPrototypeOf(Object.getPrototypeOf(this)).method.call(this)

यहाँ एक पदानुक्रम के लिए एक वाक्यविन्यास तुलना है:

// ***ES2015+**
class Person {
    constructor(first, last) {
        this.first = first;
        this.last = last;
    }

    personMethod() {
        // ...
    }
}

class Employee extends Person {
    constructor(first, last, position) {
        super(first, last);
        this.position = position;
    }

    employeeMethod() {
        // ...
    }
}

class Manager extends Employee {
    constructor(first, last, position, department) {
        super(first, last, position);
        this.department = department;
    }

    personMethod() {
        const result = super.personMethod();
        // ...use `result` for something...
        return result;
    }

    managerMethod() {
        // ...
    }
}

उदाहरण:

बनाम

// **ES5**
var Person = function(first, last) {
    if (!(this instanceof Person)) {
        throw new Error("Person is a constructor function, use new with it");
    }
    this.first = first;
    this.last = last;
};

Person.prototype.personMethod = function() {
    // ...
};

var Employee = function(first, last, position) {
    if (!(this instanceof Employee)) {
        throw new Error("Employee is a constructor function, use new with it");
    }
    Person.call(this, first, last);
    this.position = position;
};
Employee.prototype = Object.create(Person.prototype);
Employee.prototype.constructor = Employee;
Employee.prototype.employeeMethod = function() {
    // ...
};

var Manager = function(first, last, position, department) {
    if (!(this instanceof Manager)) {
        throw new Error("Manager is a constructor function, use new with it");
    }
    Employee.call(this, first, last, position);
    this.department = department;
};
Manager.prototype = Object.create(Employee.prototype);
Manager.prototype.constructor = Manager;
Manager.prototype.personMethod = function() {
    var result = Employee.prototype.personMethod.call(this);
    // ...use `result` for something...
    return result;
};
Manager.prototype.managerMethod = function() {
    // ...
};

लाइव उदाहरण:

जैसा कि आप देख सकते हैं, बहुत सारे दोहराए गए और क्रियाओं के सामान जो कि गलत होना आसान है और फिर से लिखना उबाऊ है (यही कारण है कि मैंने इसे करने के लिए एक स्क्रिप्ट लिखी थी, दिन में वापस)।


¹ "ES2015-ES2018 में कुछ भी नहीं है कि नहीं है classकि आप निर्माता कार्यों के साथ ऐसा नहीं कर सकते कर सकते हैं और कर सकते हैं Reflect.construct(सहित उपवर्गीकरण Errorऔर Array)"

उदाहरण:


9
मुझे नहीं पता कि यह उचित तुलना है। आप सभी cruft के बिना एक समान वस्तु प्राप्त कर सकते हैं। यह क्लासिकल इनहेरिटेंस को अनुमानित करने के बजाय प्रोटोटाइप चेन के माध्यम से ऑब्जेक्ट के JS तरीके का उपयोग करता है। मैंने ऐसा करने के लिए आपको दिखाने के लिए एक सरल उदाहरण दिखाते हुए एक जिस्ट बनाया ।
जेसन कस्ट

8
@JasonCust: हाँ, यह एक उचित तुलना है, क्योंकि मैं ES5 रास्ता दिखा रहा हूँ कि ES6 क्या करता है class। जावास्क्रिप्ट पर्याप्त लचीला है कि आपको निर्माण कार्यों का उपयोग नहीं करना है यदि आप नहीं करना चाहते हैं, जो आप कर रहे हैं, लेकिन यह अलग है class- पूरे बिंदु classजावास्क्रिप्ट में छद्म-शास्त्रीय विरासत को सरल बनाते हैं।
टीजे क्राउडर

3
@JasonCust: हां, यह एक अलग तरीका है। मैं इसे "अधिक देशी" नहीं कहूंगा (मुझे पता है कि काइल करता है, लेकिन यह काइल है)। कंस्ट्रक्टर फ़ंक्शंस जावास्क्रिप्ट के लिए मौलिक हैं, सभी अंतर्निहित प्रकारों को देखें (सिवाय इसके कि विरोधी कंस्ट्रक्टर गुट किसी तरह Symbolगड़बड़ करने में कामयाब रहे )। लेकिन बड़ी बात यह है कि यदि आप उनका उपयोग नहीं करना चाहते हैं, तो आपको नहीं करना है। मैं अपने काम में पाता हूं कि कई जगहों पर निर्माण कार्य newस्पष्ट होते हैं और स्पष्टता में सुधार के शब्दार्थ ; और Object.createकई अन्य स्थानों पर जासूसी करता है। चेहरे की स्थिति। वे पूरक हैं। :-)
टीजे क्राउडर

4
हुंह। मैं इसके लिए जरूरत नहीं खरीदता। मैं o से दूर होने के लिए c # से दूर चला गया और अब oop जावास्क्रिप्ट पर रेंग रहा है। मुझे प्रकार पसंद नहीं है। सब कुछ एक var / object / function होना चाहिए। बस। कोई और अधिक बाहरी कीवर्ड नहीं है। और विरासत एक घोटाला है। यदि आप प्रकार और nontypes के बीच एक अच्छी लड़ाई देखना चाहते हैं। साबुन बनाम आराम पर एक नज़र डालें। और हम सभी जानते हैं कि कौन जीता।
foreyez

3
@foreyez: classसिंटैक्स जावास्क्रिप्ट को पहले की तुलना में अधिक टाइप नहीं करता है। जैसा कि मैंने उत्तर में कहा है, यह ज्यादातर (बहुत) सरल सिंटैक्स है जो पहले से ही था। इसके लिए पूरी तरह से आवश्यकता थी, लोग लगातार पुराने वाक्यविन्यास को गलत कर रहे थे। इसका मतलब यह भी नहीं है कि आपको पहले की तुलना में अब विरासत का उपयोग करना होगा। (और निश्चित रूप से, यदि आप पुराने वाक्य रचना के साथ "कक्षाएं" कभी सेट नहीं करते हैं, तो नएax के साथ ऐसा करने की कोई आवश्यकता नहीं है, या तो।)
TJ Crowder

22

ईएस 6 कक्षाएं आज हम जिस प्रोटोटाइप क्लास प्रणाली का उपयोग करते हैं, उसके लिए सिंटैक्टिक शुगर है। वे आपके कोड को अधिक संक्षिप्त और स्व-दस्तावेजीकरण बनाते हैं, जो उन्हें (मेरी राय में) उपयोग करने के लिए पर्याप्त है।

इस ES6 वर्ग को बदलने के लिए बैबल का उपयोग करना:

class Foo {
  constructor(bar) {
    this._bar = bar;
  }

  getBar() {
    return this._bar;
  }
}

आपको कुछ इस तरह देगा:

var Foo = (function () {
  function Foo(bar) {    
    this._bar = bar;
  }

  Foo.prototype.getBar = function () {
    return this._bar;
  }

  return Foo;
})();

दूसरा संस्करण बहुत अधिक जटिल नहीं है, इसे बनाए रखने के लिए अधिक कोड है। जब आप विरासत में शामिल होते हैं, तो वे पैटर्न और भी जटिल हो जाते हैं।

क्योंकि कक्षाएं हमारे द्वारा उपयोग किए जा रहे समान प्रोटोटाइप पैटर्न का संकलन करती हैं, आप उन पर एक ही प्रोटोटाइप हेरफेर कर सकते हैं। जिसमें विधियाँ जोड़ना और रनटाइम पर लाइक, एक्सेस करने के तरीके Foo.prototype.getBarआदि शामिल हैं।

आज ES6 में गोपनीयता के लिए कुछ बुनियादी समर्थन है, हालांकि यह उन वस्तुओं को निर्यात नहीं करने पर आधारित है जिन्हें आप सुलभ नहीं चाहते हैं। उदाहरण के लिए, आप कर सकते हैं:

const BAR_NAME = 'bar';

export default class Foo {
  static get name() {
    return BAR_NAME;
  }
}

और BAR_NAMEसीधे संदर्भ के लिए अन्य मॉड्यूल के लिए उपलब्ध नहीं होगा।

बहुत सारे पुस्तकालयों ने इस तरह का समर्थन करने या हल करने की कोशिश की है, जैसे बैकबोन अपने extendsसहायक के साथ जो विधि-जैसे कार्यों और गुणों का एक असमान हैश लेता है, लेकिन प्रोटोटाइप के साथ घूमने में शामिल नहीं होने वाली प्रोटोटाइप विरासत को उजागर करने के लिए कोई व्यवस्था नहीं है।

जेएस कोड अधिक जटिल हो गया है और कोडबेस बड़ा हो गया है, हमने विरासत और मॉड्यूल जैसी चीजों को संभालने के लिए बहुत सारे पैटर्न विकसित करना शुरू कर दिया है। मॉड्यूल के लिए एक निजी गुंजाइश बनाने के लिए उपयोग किए जाने वाले IIFE में बहुत सारे ब्रेसिज़ और परेंस होते हैं; उन में से एक को गायब करने के परिणामस्वरूप एक वैध स्क्रिप्ट हो सकती है जो पूरी तरह से अलग करती है (एक मॉड्यूल के बाद अर्धविराम को छोड़ना अगले मॉड्यूल को एक पैरामीटर के रूप में पारित कर सकता है, जो शायद ही कभी अच्छा होता है)।

tl; dr: यह चीनी है जो हम पहले से ही करते हैं और कोड में अपना इरादा स्पष्ट करते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.