2012-08-02 15 views
9

यह जावास्क्रिप्ट के गुरु के लिए एक प्रश्न है। मैं जावास्क्रिप्ट प्रोटोटाइप मॉडल के साथ और अधिक सुरुचिपूर्ण काम करने की कोशिश कर रहा हूँ। यहाँ मेरी उपयोगिता कोड है (यह प्रोटोटाइप का असली श्रृंखला और instanceof ऑपरेटर के साथ सही काम प्रदान करता है): वहाँ है:मैं जावास्क्रिप्ट प्रोटोटाइप विरासत (प्रोटोटाइप की श्रृंखला) कैसे कर सकता हूं

var Class_1 = new Class({ 
    init: function (msg) { // constructor 
    this.msg = msg; 
    }, 

    method_1: function() { 
    alert(this.msg + ' in Class_1::method_1'); 
    }, 

    method_2: function() { 
    alert(this.msg + ' in Class_1::method_2'); 
    } 
}); 

var Class_2 = new Class({ 
    parent: Class_1, 

    init: function (msg) { // constructor 
    this.msg = msg; 
    }, 

    // method_1 will be taken from Class_1 

    method_2: function() { // this method will overwrite the original one 
    alert(this.msg + ' in Class_2::method_2'); 
    }, 

    method_3: function() { // just new method 
    alert(this.msg + ' in Class_2::method_3'); 
    } 
}); 

var c1 = new Class_1('msg'); 
c1.method_1(); // msg in Class_1::method_1 
c1.method_2(); // msg in Class_1::method_2 

var c2 = new Class_2('msg'); 
c2.method_1(); // msg in Class_1::method_1 
c2.method_2(); // msg in Class_2::method_2 
c2.method_3(); // msg in Class_2::method_3 

alert('c1 < Class_1 - ' + (c1 instanceof Class_1 ? 'true' : 'false')); // true 
alert('c1 < Class_2 - ' + (c1 instanceof Class_2 ? 'true' : 'false')); // false 

alert('c2 < Class_1 - ' + (c2 instanceof Class_1 ? 'true' : 'false')); // true 
alert('c2 < Class_2 - ' + (c2 instanceof Class_2 ? 'true' : 'false')); // true 

मेरा प्रश्न है:

function Class(conf) { 
    var init = conf.init || function() {}; 
    delete conf.init; 

    var parent = conf.parent || function() {}; 
    delete conf.parent; 

    var F = function() {}; 
    F.prototype = parent.prototype; 
    var f = new F(); 
    for (var fn in conf) f[fn] = conf[fn]; 
    init.prototype = f; 

    return init; 
}; 

यह मुझे इस तरह के thigns करने की अनुमति देता ऐसा करने के लिए और अधिक आसान तरीका है?

+0

http://codereview.stackexchange.com/ –

+1

[जॉन रेसिग] (http://ejohn.org/blog/simple-javascript-inheritance/) द्वारा कक्षा विरासत का एक बहुत अच्छा उदाहरण है। यह सुपर और अन्य उपहार प्रदान करता है। – elclanrs

+0

यह रुचि का हो सकता है: http://ejohn.org/apps/learn/ –

उत्तर

0

कुछ शोध मैंने निष्कर्ष निकाला गया है वहाँ यह करने के लिए कोई और अधिक आसान तरीका है के बाद।

0

हां, ऐसा करने का एक बेहतर तरीका है।

var call = Function.prototype.call; 

var classes = createStorage(), 
    namespaces = createStorage(), 
    instances = createStorage(createStorage); 


function createStorage(creator){ 
    var storage = new WeakMap; 
    creator = typeof creator === 'function' ? creator : Object.create.bind(null, null, {}); 
    return function store(o, v){ 
    if (v) { 
     storage.set(o, v); 
    } else { 
     v = storage.get(o); 
     if (!v) { 
     storage.set(o, v = creator(o)); 
     } 
    } 
    return v; 
    }; 
} 

function Type(){ 
    var self = function(){} 
    self.__proto__ = Type.prototype; 
    return self; 
} 

Type.prototype = Object.create(Function, { 
    constructor: { value: Type, 
       writable: true, 
       configurable: true }, 
    subclass: { value: function subclass(scope){ return new Class(this, scope) }, 
       configurable: true, 
       writable: true } 
}); 

function Class(Super, scope){ 
    if (!scope) { 
    scope = Super; 
    Super = new Type; 
    } 

    if (typeof Super !== 'function') { 
    throw new TypeError('Superconstructor must be a function'); 
    } else if (typeof scope !== 'function') { 
    throw new TypeError('A scope function was not provided'); 
    } 

    this.super = Super; 
    this.scope = scope; 

    return this.instantiate(); 
} 

Class.unwrap = function unwrap(Ctor){ 
    return classes(Ctor); 
}; 

Class.prototype.instantiate = function instantiate(){ 
    function super_(){ 
    var name = super_.caller === Ctor ? 'constructor' : super_.caller.name; 
    var method = Super.prototype[name]; 

    if (typeof method !== 'function') { 
     throw new Error('Attempted to call non-existent supermethod'); 
    } 

    return call.apply(method, arguments); 
    } 

    var Super = this.super, 
     namespace = namespaces(Super), 
     private = instances(namespace) 

    var Ctor = this.scope.call(namespace, private, super_); 
    Ctor.__proto__ = Super; 
    Ctor.prototype.__proto__ = Super.prototype; 
    namespaces(Ctor, namespace); 
    classes(Ctor, this); 
    return Ctor; 
} 

उदाहरण उपयोग:

var Primary = new Class(function(_, super_){ 
    var namespace = this; 
    namespace.instances = 0; 

    function Primary(name, secret){ 
    this.name = name; 
    _(this).secret = secret; 
    namespace.instances++; 
    } 

    Primary.prototype.logSecret = function logSecret(label){ 
    label = label || 'secret'; 
    console.log(label + ': ' + _(this).secret); 
    } 

    return Primary; 
}); 


var Derived = Primary.subclass(function(_, super_){ 

    function Derived(name, secret, size){ 
    super_(this, name, secret); 
    this.size = size; 
    } 

    Derived.prototype.logSecret = function logSecret(){ 
    super_(this, 'derived secret'); 
    } 

    Derived.prototype.exposeSecret = function exposeSecret(){ 
    return _(this).secret; 
    } 

    return Derived; 
}); 

var Bob = new Derived('Bob', 'is dumb', 20); 
Bob.logSecret(); 
console.log(Bob); 
console.log(Bob.exposeSecret()); 
+0

काम कर रहे सुपर और निजी गुण –

संबंधित मुद्दे