ECMAScript పరివర్తన పద్ధతి అమలు

పరిపాలన వ్యవస్థ అమలు

ఇక్మాస్క్రిప్ట్ లో పరిపాలన వ్యవస్థను అమలు చేయడానికి, పరిపాలన వ్యవస్థను అనుసరించాల్సిన బేస్ వర్గాన్ని చూడండి. అన్ని డెవలపర్స్ నిర్వచించిన వర్గాలు బేస్ వర్గాలుగా ఉంటాయి. భద్రత కారణంగా, స్థానిక వర్గాలు మరియు హోస్ట్ వర్గాలను బేస్ వర్గాలుగా చేయకూడదు, ఇది పబ్లిషింగ్ బ్రౌజర్ స్టేజ్ కోడ్ను సాధారణ ప్రాప్తికి అవకాశం ఇస్తుంది, ఇది క్రూర్ ఆక్రమణకు ఉపయోగించబడవచ్చు.

బేస్ వర్గాన్ని ఎంచుకున్న తరువాత, దాని ఉపవర్గాన్ని సృష్టించవచ్చు. బేస్ వర్గాన్ని ఉపయోగించాలా లేదా లేదా ఉపయోగించకుండా ఉండాలా మీ నిర్ణయం. కొన్నిసార్లు మీరు నేరుగా ఉపయోగించలేని బేస్ వర్గాన్ని సృష్టించాలని కోరుకునే సందర్భాలు ఉంటాయి, ఇది ఉపవర్గాలకు సాధారణ ఫంక్షన్స్ అందించడానికి ఉపయోగించబడుతుంది. ఈ సందర్భంలో, బేస్ వర్గం అబ్స్ట్రాక్ట్ వర్గంగా పరిగణించబడుతుంది.

ఇతర భాషలకంటే ఎక్మాస్క్రిప్ట్ సాధారణంగా అబ్స్ట్రాక్ట్ వర్గాలను కనీసం నిర్వచించలేదు, కానీ కొన్నిసార్లు అది ఉపయోగించకుండా ఉండే కొన్ని వర్గాలను సృష్టిస్తుంది. అటువంటి వర్గాలను సాధారణంగా అబ్స్ట్రాక్ట్ వర్గాలు అని పిలుస్తారు.

సృష్టిచేయబడిన ఉపవర్గం పెరిగిన వర్గం అన్ని లక్షణాలు మరియు పద్ధతులను అనుసరిస్తుంది, ఇంకా నిర్మాణ పద్ధతిని మరియు పద్ధతుల అమలును. గమనించండి, అన్ని లక్షణాలు మరియు పద్ధతులు సార్వజనీనంగా ఉన్నాయి, కాబట్టి ఉపవర్గం ఈ పద్ధతులను నేరుగా ప్రాప్తించవచ్చు. ఉపవర్గం పెరిగిన వర్గంలో ఉన్న కొత్త లక్షణాలు మరియు పద్ధతులను చేర్చవచ్చు, కాబట్టి అనుసరించబడే వర్గం లక్షణాలను మరియు పద్ధతులను పరిచయం చేయవచ్చు.

继承的方式

和其他功能一样,ECMAScript 实现继承的方式不止一种。这是因为 JavaScript 中的继承机制并不是明确规定的,而是通过模仿实现的。这意味着所有的继承细节并非完全由解释程序处理。作为开发者,你有权决定最适用的继承方式。

下面为您介绍几种具体的继承方式。

对象冒充

构想原始的 ECMAScript 时,根本没打算设计对象冒充(object masquerading)。它是在开发者开始理解函数的工作方式,尤其是如何在函数环境中使用 this 关键字后才发展出来。

其原理如下:构造函数使用 this 关键字给所有属性和方法赋值(即采用类声明的构造函数方式)。因为构造函数只是一个函数,所以可使 ClassA 构造函数成为 ClassB 的方法,然后调用它。ClassB 就会收到 ClassA 的构造函数中定义的属性和方法。例如,用下面的方式定义 ClassA 和 ClassB:

function ClassA(sColor) {
    this.color = sColor;
    this.sayColor = function () {
        alert(this.color);
    };
}
function ClassB(sColor) {
}

还记得吗?关键字 this 引用的是构造函数当前创建的对象。不过在这个方法中,this 指向的所属的对象。这个原理是把 ClassA 作为常规函数来建立继承机制,而不是作为构造函数。如下使用构造函数 ClassB 可以实现继承机制:

function ClassB(sColor) {
    this.newMethod = ClassA;
    this.newMethod(sColor);
    delete this.newMethod;
}

在这段代码中,为 ClassA 赋予了方法 newMethod(请记住,函数名只是指向它的指针)。然后调用该方法,传递给它的是 ClassB 构造函数的参数 sColor。最后一行代码删除了对 ClassA 的引用,这样以后就不能再调用它。

所有新属性和新方法都必须在删除了新方法的代码行后定义。否则,可能会覆盖超类的相关属性和方法:

function ClassB(sColor, sName) {
    this.newMethod = ClassA;
    this.newMethod(sColor);
    delete this.newMethod;
    this.name = sName;
    this.sayName = function () {
        alert(this.name);
    };
}

为证明前面的代码有效,可以运行下面的例子:

var objA = new ClassA("blue");
var objB = new ClassB("red", "John");
objA.sayColor();	//అవుట్పుట్ "blue"
objB.sayColor();	//అవుట్పుట్ "red"
objB.sayName();		//输出 "John"

对象冒充可以实现多重继承

有趣的是,对象冒充可以支持多重继承。也就是说,一个类可以继承多个超类。用 UML 表示的多重继承机制如下图所示:

UML పరివర్తన దృశ్యం ఉత్తరం

例如,如果存在两个类 ClassX 和 ClassY,ClassZ 想继承这两个类,可以使用下面的代码:

function ClassZ() {
    this.newMethod = ClassX;
    this.newMethod();
    delete this.newMethod;
    this.newMethod = ClassY;
    this.newMethod();
    delete this.newMethod;
}

TIY

ఈ విధమైన పరిపాలన మెకానిజమ్ ప్రాచుర్యం కారణంగా, ECMAScript మూడవ ఎడిషన్లో Function ఆబ్జెక్ట్కు రెండు నెవి మెథడ్స్ జోడించబడ్డాయి, అవి call() మరియు apply().

ఈ విధమైన పరిపాలన మెకానిజమ్ ప్రాచుర్యం కారణంగా, ECMAScript మూడవ ఎడిషన్లో Function ఆబ్జెక్ట్కు రెండు నెవి మెథడ్స్ జోడించబడ్డాయి, అవి call() మరియు apply().

call() మాధ్యమం

call() మాధ్యమం క్లాసికల్ ఆబ్జెక్ట్ స్ప్రాంగింగ్ మాధ్యమాలతో అత్యంత సమానం. దాని మొదటి పరామితి this కొన్నికి వస్తుంది. ఇతర పరామితులు ఫంక్షన్కు నేరుగా పరామితులుగా పంపబడతాయి. ఉదాహరణకు:

function sayColor(sPrefix,sSuffix) {
    alert(sPrefix + this.color + sSuffix);
};
var obj = new Object();
obj.color = "blue";
sayColor.call(obj, "The color is ", "a very nice color indeed.");

ఈ ఉదాహరణలో, ఫంక్షన్ sayColor() ఆబ్జెక్ట్ వెలుపల నిర్వహించబడింది, దీని ఎటువంటి ఆబ్జెక్ట్కు చెందని కూడా ప్రత్యేక పదం this ను ఉపయోగించవచ్చు. ఆబ్జెక్ట్ obj యొక్క color అంశం blue కన్నా సమానం. call() మాధ్యమాన్ని కాల్ చేయడంలో, మొదటి పరామితి obj అని అర్థం చేస్తుంది మరియు sayColor() ఫంక్షన్కు లోపల ప్రత్యేక పదం this కు విలువ ఇవ్వాలి. రెండవ మరియు మూడవ పరామితులు పదాలు. వాటిని sayColor() ఫంక్షన్కు పరామితులుగా ఉపయోగించాలి, ఫలితంగా సృష్టించబడిన సందేశం "The color is blue, a very nice color indeed." ప్రదర్శించబడుతుంది.

ఈ విధమైన పరిపాలన మెకానిజమ్ తో కలిపి ఉపయోగించడానికి ఈ మాధ్యమాన్ని ఉపయోగించడానికి, మొదటి మూడు వరుసలలో విలువలను అప్పగించడం, కాల్ చేయడం మరియు తొలగించడం కోడ్లను మార్చాలి:

function ClassB(sColor, sName) {
    //this.newMethod = ClassA;
    //this.newMethod(color);
    //delete this.newMethod;
    ClassA.call(this, sColor);
    this.name = sName;
    this.sayName = function () {
        alert(this.name);
    };
}

TIY

ఇక్కడ, మేము ClassA లోని ప్రత్యేక పదం this ను కొత్తగా సృష్టించిన ClassB ఆబ్జెక్ట్ కు సమానం చేయాలని చూస్తున్నాము, కాబట్టి this మొదటి పరామితి. రెండవ పరామితి sColor రెండు క్లాసులకు కూడా ప్రత్యేకం.

apply() మాధ్యమం

apply() మాధ్యమం రెండు పరామితులు కలిగి ఉంటుంది, వాటిలో ఒకటి this కొన్నికి వస్తుంది మరియు మరొకటి ఫంక్షన్కు పరామితుల క్రమశిక్షణ ఉంటుంది. ఉదాహరణకు:

function sayColor(sPrefix,sSuffix) {
    alert(sPrefix + this.color + sSuffix);
};
var obj = new Object();
obj.color = "blue";
sayColor.apply(obj, new Array("The color is ", "a very nice color indeed."));

ఈ ఉదాహరణ ముంది ఉదాహరణలతో అనుకూలంగా ఉంది, కానీ ఇప్పుడు అనుసరించబడుతున్నది apply() పద్ధతి. apply() పద్ధతిని అనుసరించినప్పుడు, మొదటి పరిమాణం కూడా obj ఉంటుంది. రెండవ పరిమాణం రెండు స్ట్రింగుల కలిగిన ప్రాణికి ప్రతిమానికి, sayColor() పద్ధతిలో పరిమాణాలు sPrefix మరియు sSuffixలతో సరిపోతాయి. అంతేకాకుండా, అందించబడిన సందేశం "The color is blue, a very nice color indeed." కూడా ప్రదర్శించబడుతుంది.

ఈ పద్ధతి కూడా మొదటి మూడు పద్ధతులను రద్దు చేయడం, కాల్లు చేయడం మరియు కొత్త పద్ధతిని రద్దు చేయడం స్థానం లో ఉపయోగించబడుతుంది:

function ClassB(sColor, sName) {
    //this.newMethod = ClassA;
    //this.newMethod(color);
    //delete this.newMethod;
    ClassA.apply(this, new Array(sColor));
    this.name = sName;
    this.sayName = function () {
        alert(this.name);
    };
}

అలాగే, మొదటి పరిమాణం కూడా this ఉంటుంది. రెండవ పరిమాణం ఒక మాత్రమే విలువ కలిగిన ప్రాణికి ప్రతిమానికి ఉంటుంది. కాబట్టి, ClassB యొక్క మొత్తం arguments ఆబ్జెక్ట్ను apply() పద్ధతికి రెండవ పరిమాణంగా పంపిణీ చేయవచ్చు:

function ClassB(sColor, sName) {
    //this.newMethod = ClassA;
    //this.newMethod(color);
    //delete this.newMethod;
    ClassA.apply(this, arguments);
    this.name = sName;
    this.sayName = function () {
        alert(this.name);
    };
}

TIY

సరిగ్గా, మాత్రమే సుపర్ క్లాస్ లో మరియు కుమార క్లాస్ లో పరిమాణాల క్రమం పూర్తిగా అనుకూలంగా ఉండితే పరిమాణాల ఆబ్జెక్ట్ను పంపిణీ చేయవచ్చు. అలా కాకపోయితే, ప్రత్యేకంగా ఒక ప్రాణికి ప్రతిమానికి క్రమబద్ధంగా నింపబడిన ఒక ప్రాణికి ప్రతిమానికి సృష్టించవలసివుంటుంది. ఇంకా call() పద్ధతిని ఉపయోగించవచ్చు.

ప్రాటోటైప్ చేయడం (prototype chaining)

ఈ రీతి యొక్క వారసత్వం ECMAScriptలో ప్రాటోటైప్ చేయడానికి ఉపయోగపడుతుంది. పూర్వ చాపలో క్లాస్ యొక్క ప్రాటోటైప్ పద్ధతిని పరిచయం చేయబడింది. ప్రాటోటైప్ చేయడం ఈ పద్ధతిని విస్తరించి, వారసత్వ వ్యవస్థను ఒక ఆసక్తికరమైన రీతిలో అమలు చేస్తుంది.

పూర్వ చాపలో నేర్చుకున్నట్లు ఉంది, prototype ఆబ్జెక్ట్ ఒక మాదిరి ప్రతిరూపం కాగా, సంకల్పించబడే అన్ని ఆబ్జెక్ట్లు ఈ మాదిరి ప్రతిరూపం మీద ఆధారపడతాయి. మొత్తంగా, prototype ఆబ్జెక్ట్ యొక్క ఏ అంశం లేదా పద్ధతి అన్ని క్లాస్ యొక్క అన్ని ఇన్స్టాన్స్లకు పాఠ్యపద్ధతిగా అందిస్తాయి. ప్రాటోటైప్ చేయడం ఈ ఫంక్షన్లు ఉపయోగించి పరివర్తన వ్యవస్థను అమలు చేస్తుంది.

ఈ ఉదాహరణలో ప్రాటోటైప్ పద్ధతితో పునర్వ్యాఖ్యానించిన విధంగా వాటిని కనిపించేలా మారుతాయి:

function ClassA() {
}
ClassA.prototype.color = "blue";
ClassA.prototype.sayColor = function () {
    alert(this.color);
};
function ClassB() {
}
ClassB.prototype = new ClassA();

原型方式的神奇之处在于突出显示的蓝色代码行。这里,把 ClassB 的 prototype 属性设置成 ClassA 的实例。这很有意思,因为想要 ClassA 的所有属性和方法,但又不想逐个将它们 ClassB 的 prototype 属性。还有比把 ClassA 的实例赋予 prototype 属性更好的方法吗?

గమనిక:క్లాస్ ఎ యొక్క కన్స్ట్రక్టర్ ఫంక్షన్ కి కోసం కోసం పారామీతాలను పంపకుండా కాల్ చేయడం ఇక్కడ ప్రాటోటైప్ లైన్ లో సాధారణ పద్ధతి. ప్రత్యామ్నాయంగా కోసం కోసం కోసం పారామీతాలను పంపకుండా కాల్ చేయడం చేయాలి.

ఆప్లికేషన్ కోసం ఉపయోగించడానికి, క్లాస్ బి యొక్క అన్ని లక్షణాలు మరియు మార్గాలు ప్రాటోటైప్ అంశంపై అంకితం అయ్యే తర్వాత ఉండాలి, ఎందుకంటే ప్రాటోటైప్ అంశం ప్రత్యామ్నాయ వస్తుంది అందుకు మొదటి మార్గాలు తొలగిస్తాయి. ఎందుకు? ప్రాటోటైప్ అంశం ప్రత్యామ్నాయ వస్తుంది ఎందుకంటే మొదటి వస్తువు తొలగించబడుతుంది. క్లాస్ బి కు పేరు అంశం మరియు sayName() మార్గాన్ని జోడించడానికి కోడ్ కావాలి:

function ClassB() {
}
ClassB.prototype = new ClassA();
ClassB.prototype.name = "";
ClassB.prototype.sayName = function () {
    alert(this.name);
};

ఈ కోడ్ ని పరీక్షించడానికి క్రింది ఉదాహరణను ఉపయోగించండి:

var objA = new ClassA();
var objB = new ClassB();
objA.color = "blue";
objB.color = "red";
objB.name = "John";
objA.sayColor();
objB.sayColor();
objB.sayName();

TIY

ప్రాటోటైప్ లైన్ లో, instanceof ఆపరేటర్ పనిపద్ధతి కూడా విశేషం. క్లాస్ బి యొక్క అన్ని ఇన్స్టాన్స్ కు, instanceof ఆపరేటర్ క్లాస్ ఎ మరియు క్లాస్ బి ని కూడా true అవుతుంది. ఉదాహరణకు:

var objB = new ClassB();
alert(objB instanceof ClassA);	//అవుట్పుట్ "true"
alert(objB instanceof ClassB);	//అవుట్పుట్ "true"

ఇక్కడ ఇస్క్రిప్ట్ యొక్క పరిమిత రకంలో, ఇది చాలా ఉపయోగపడుతుంది, కానీ ఆప్లికేషన్ కోసం ఉపయోగించడానికి అది లేదు.

ప్రాటోటైప్ లైన్ పరామితి బహుళ ఉత్తరాధికారం నిర్బంధించడం లేదు. గమనించండి, ప్రాటోటైప్ లైన్ ఒక ప్రకారం యొక్క ప్రాటోటైప్ అంశాన్ని క్లాస్ నిర్వచించడానికి ఉపయోగిస్తుంది.

మిశ్రమ పద్ధతి

ఈ పద్ధతిలో క్లాస్ నిర్వచించడానికి కన్స్ట్రక్టర్ ఫంక్షన్ ఉపయోగిస్తారు, ఏ ప్రాటోటైప్ కాదు. ఆప్లికేషన్ కోసం ముఖ్యమైన సమస్య కన్స్ట్రక్టర్ ఫంక్షన్ ఉపయోగించడం అవసరం, ఇది ఉత్తమ ఎంపిక కాదు. కానీ ప్రాటోటైప్ లైన్ ఉపయోగించినప్పుడు, పరామీతంగా కన్స్ట్రక్టర్ ఫంక్షన్ ఉపయోగించలేము. డెవలపర్లు ఎలా ఎంచుకోవాలి? సరళమైన పరిష్కారం ఉంది, రెండింటినీ ఉపయోగించండి.

在前一章,我们曾经讲解过创建类的最好方式是用构造函数定义属性,用原型定义方法。这种方式同样适用于继承机制,用对象冒充继承构造函数的属性,用原型链继承 prototype 对象的方法。用这两种方式重写前面的例子,代码如下:

function ClassA(sColor) {
    this.color = sColor;
}
ClassA.prototype.sayColor = function () {
    alert(this.color);
};
function ClassB(sColor, sName) {
    ClassA.call(this, sColor);
    this.name = sName;
}
ClassB.prototype = new ClassA();
ClassB.prototype.sayName = function () {
    alert(this.name);
};

ఈ ఉదాహరణలో, పరిపాలన విధానం రెండు మురికైన నీలం కోడ్ ద్వారా అమలు అవుతుంది. మొదటి మురికైన కోడ్ లో, ClassB నిర్మాణ కాల్పనలో, ClassA క్లాస్ యొక్క sColor లఘువును పరిపాలన విధానం ద్వారా అనుసరించబడుతుంది. రెండవ మురికైన కోడ్ లో, ClassA క్లాస్ యొక్క ప్రాతిపదికన పరిపాలన విధానం ద్వారా మెథడ్స్ అనుసరించబడుతుంది. ఈ మిశ్రమ పద్ధతిలో ప్రాతిపదికన పరిపాలన విధానం ఉపయోగించబడినందున, instanceof ఆపరేటర్ సరిగ్గా పని చేస్తుంది.

ఈ ఉదాహరణలో కోడ్ ఈ ఉదాహరణను పరీక్షించబడింది:

var objA = new ClassA("blue");
var objB = new ClassB("red", "John");
objA.sayColor();	//అవుట్పుట్ "blue"
objB.sayColor();	//అవుట్పుట్ "red"
objB.sayName();	//అవుట్పుట్ "John"

TIY