जॉन रेसिग (jQuery प्रसिद्धि का) Simple JavaScript Inheritance का संक्षिप्त कार्यान्वयन प्रदान करता है। उनके दृष्टिकोण ने चीजों को और भी बेहतर बनाने के अपने प्रयास को प्रेरित किया। मैं Resig के मूल Class.extend
समारोह फिर से लिख दिया निम्न लाभ शामिल करने के लिए:सरल जावास्क्रिप्ट विरासत में सुधार
प्रदर्शन - वर्ग परिभाषा, वस्तु निर्माण के दौरान कम भूमि के ऊपर, और आधार वर्ग प्रणाली को बुलाती है
लचीलापन - के लिए अनुकूलित नए ईसीएमएस्क्रिप्ट 5-संगत ब्राउज़र (जैसे क्रोम), लेकिन पुराने ब्राउज़र (जैसे आईई 6) के लिए समकक्ष "शिम" प्रदान करता है
संगतता - सख्त मोड में मान्य है और बेहतर उपकरण संगतता प्रदान करता है (उदा। VSDoc/JSDoc टिप्पणी, विजुअल स्टूडियो IntelliSense, आदि)
सादगी - आप एक "निंजा" स्रोत कोड को समझने के लिए होने की जरूरत नहीं है (और यह और भी आसान है कि अगर आप ECMAScript 5 सुविधाओं को खो)
सशक्तता - गुजरता है और अधिक "कोने मामले" इकाई परीक्षण (आईई में toString अधिभावी जैसे)
क्योंकि यह लगभग सच होना बहुत अच्छा लगता है, मैं यह सुनिश्चित करने के लिए अपने तर्क नहीं है चाहता हूँ कोई मौलिक खामियां या बी है जीएस, और देखें कि कोई भी सुधार का सुझाव दे सकता है या कोड को खारिज कर सकता है। कि के साथ, मैं classify
समारोह मौजूद:
function classify(base, properties)
{
/// <summary>Creates a type (i.e. class) that supports prototype-chaining (i.e. inheritance).</summary>
/// <param name="base" type="Function" optional="true">The base class to extend.</param>
/// <param name="properties" type="Object" optional="true">The properties of the class, including its constructor and members.</param>
/// <returns type="Function">The class.</returns>
// quick-and-dirty method overloading
properties = (typeof(base) === "object") ? base : properties || {};
base = (typeof(base) === "function") ? base : Object;
var basePrototype = base.prototype;
var derivedPrototype;
if (Object.create)
{
// allow newer browsers to leverage ECMAScript 5 features
var propertyNames = Object.getOwnPropertyNames(properties);
var propertyDescriptors = {};
for (var i = 0, p; p = propertyNames[i]; i++)
propertyDescriptors[p] = Object.getOwnPropertyDescriptor(properties, p);
derivedPrototype = Object.create(basePrototype, propertyDescriptors);
}
else
{
// provide "shim" for older browsers
var baseType = function() {};
baseType.prototype = basePrototype;
derivedPrototype = new baseType;
// add enumerable properties
for (var p in properties)
if (properties.hasOwnProperty(p))
derivedPrototype[p] = properties[p];
// add non-enumerable properties (see https://developer.mozilla.org/en/ECMAScript_DontEnum_attribute)
if (!{ constructor: true }.propertyIsEnumerable("constructor"))
for (var i = 0, a = [ "constructor", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", "toLocaleString", "toString", "valueOf" ], p; p = a[i]; i++)
if (properties.hasOwnProperty(p))
derivedPrototype[p] = properties[p];
}
// build the class
var derived = properties.hasOwnProperty("constructor") ? properties.constructor : function() { base.apply(this, arguments); };
derived.prototype = derivedPrototype;
derived.prototype.constructor = derived;
derived.prototype.base = derived.base = basePrototype;
return derived;
}
और उपयोग Resig के लिए लगभग समान निर्माता का नाम (constructor
बनाम init
) और आधार वर्ग विधि कॉल के लिए वाक्य रचना के अलावा है।
equals(m instanceof Object && m instanceof Minimal && m.constructor === Minimal, true);
equals(c instanceof Object && c instanceof Class && c.constructor === Class, true);
equals(s instanceof Object && s instanceof Class && s instanceof SpanishClass && s.constructor === SpanishClass, true);
equals(p instanceof Object && p instanceof Person && p.constructor === Person, true);
equals(n instanceof Object && n instanceof Person && n instanceof Ninja && n.constructor === Ninja, true);
equals(e instanceof Object && e instanceof Person && e instanceof Ninja && e instanceof ExtremeNinja && e.constructor === ExtremeNinja, true);
equals(c.count(), "John: One. Two. Three.");
equals(s.count(), "Juan: Uno. Dos. Tres.");
equals(p.isQuiet, false);
equals(p.canSing(), true);
equals(p.sing(), "Figaro!");
equals(n.isQuiet, true);
equals(n.skillLevel, 100);
equals(n.canSing(), false);
equals(n.sing(), "Shh!");
equals(n.attack(), "Chop!");
equals(e.isQuiet, true);
equals(e.skillLevel, 200);
equals(e.canSing(), false);
equals(e.sing(), "Shh!");
equals(e.attack(), "Chop! Chop!");
equals(e.backflip(), "Woosh!");
equals(e.skillLevel, 201);
equals(e.canSing(), true);
equals(e.sing(), "Figaro!");
equals(e.toString(), "Hello, World!");
किसी को भी कुछ भी मेरे दृष्टिकोण बनाम जॉन Resig के original approach गलत दिखाई देता है:
/* Example 1: Define a minimal class */
var Minimal = classify();
/* Example 2a: Define a "plain old" class (without using the classify function) */
var Class = function()
{
this.name = "John";
};
Class.prototype.count = function()
{
return this.name + ": One. Two. Three.";
};
/* Example 2b: Define a derived class that extends a "plain old" base class */
var SpanishClass = classify(Class,
{
constructor: function()
{
this.name = "Juan";
},
count: function()
{
return this.name + ": Uno. Dos. Tres.";
}
});
/* Example 3: Define a Person class that extends Object by default */
var Person = classify(
{
constructor: function(name, isQuiet)
{
this.name = name;
this.isQuiet = isQuiet;
},
canSing: function()
{
return !this.isQuiet;
},
sing: function()
{
return this.canSing() ? "Figaro!" : "Shh!";
},
toString: function()
{
return "Hello, " + this.name + "!";
}
});
/* Example 4: Define a Ninja class that extends Person */
var Ninja = classify(Person,
{
constructor: function(name, skillLevel)
{
Ninja.base.constructor.call(this, name, true);
this.skillLevel = skillLevel;
},
canSing: function()
{
return Ninja.base.canSing.call(this) || this.skillLevel > 200;
},
attack: function()
{
return "Chop!";
}
});
/* Example 4: Define an ExtremeNinja class that extends Ninja that extends Person */
var ExtremeNinja = classify(Ninja,
{
attack: function()
{
return "Chop! Chop!";
},
backflip: function()
{
this.skillLevel++;
return "Woosh!";
}
});
var m = new Minimal();
var c = new Class();
var s = new SpanishClass();
var p = new Person("Mary", false);
var n = new Ninja("John", 100);
var e = new ExtremeNinja("World", 200);
और यहाँ मेरी QUnit परीक्षण है जो सभी पास कर रहे हैं? सुझाव और प्रतिक्रिया का स्वागत है!
नोट: उपरोक्त कोड को प्रारंभ में संशोधित किया गया है क्योंकि मैंने शुरुआत में इस प्रश्न को पोस्ट किया था। उपर्युक्त नवीनतम संस्करण का प्रतिनिधित्व करता है। यह देखने के लिए कि यह कैसे विकसित हुआ है, कृपया संशोधन इतिहास देखें।
मैं 'ऑब्जेक्ट.क्रेट' और [traitsjs] (http://traitsjs.org/) की अनुशंसा करता हूं। विरासत जावास्क्रिप्ट में कोई अच्छा नहीं है, ऑब्जेक्ट संरचना – Raynos
का उपयोग करें शायद मैं अभी तक इसका उपयोग नहीं कर रहा हूं, लेकिन लक्षणों का वाक्यविन्यास मेरे सिर को स्पिन बनाता है। मुझे लगता है कि जब तक यह निम्नलिखित प्राप्त नहीं कर लेता है तब तक मैं गुजरता हूं ... – Will