良好的伪古典JavaScript继承模式?

时间:2011-11-18 19:48:28

标签: javascript inheritance prototypal-inheritance

阅读来自Crocksford的'Javascript好部分',我一直在寻求编写一些高效,可读和可重用的 JavaScript代码。 这就是我的目标,特别是对象的属性是公开的。

话虽如此,代码是否有任何特定的问题或改进点?

( function(){

    window.App = {}

    // define uma pessoa normal
    App.Person = function(name){
        this.name = name || "anon"
        this.iq = 100
        this.fortune_number = Math.floor(Math.random()*100)
    }

    App.Person.prototype.sayName = function() {
        return (this.name+"!")
    }

    App.Person.prototype.sayIQ = function() {
        return (this.iq)
    }



    // define um genio da humanidade
    App.Genius = function(name) {
        App.Person.call( this, name )
        this.iq = 9000
    };
    // inherits All methods from Pessoa
    App.Genius.prototype = App.Person.prototype

    App.Genius.prototype.solveNP = function() {
        return "eureka!"
    };

})()


var p = new App.Person('Jon')
console.log( "A Person:", p.sayName(), p.fortune_number, p.sayIQ() )
//-> A Person: Jon! 10 100

var g = new App.Genius( 'Eugenios' )
console.log( "A Genious:", g.sayName(), g.fortune_number, g.sayIQ(), g.solveNP() )
//-> A Genious: Eugenios! 7 9000 eureka!

我特别不确定此行App.Genius.prototype = App.Person.prototype是否合适,因为我通常会在某些新实例之后看到原型,例如Mozilla Guide

4 个答案:

答案 0 :(得分:2)

您的代码中没有真正的继承。你必须扩展原型链才能拥有真正的(原型)继承。

// This is how it's done in JS
Child.prototype = new Parent();
Child.prototype.constructor = Child;

这有执行Parent构造函数的副作用,在某些情况下这可能是坏的(例如,如果构造函数需要任何参数)。您应该使用以下位来进行继承。

var Fn = function () {}; // empty constructor, no side-effects
Fn.prototype = Parent.prototype;

Child.prototype = new Fn();
Child.prototype.constructor = Child;

答案 1 :(得分:1)

否则

App.Genius.prototype = App.Person.prototype

不是一个好主意:

var Parent = function (name) {
    this.name = name;
}

Parent.prototype.greet = function (who) {
    alert(name + ' say hi to ' + who);
}

var Child = function () {
}

Child.prototype = Parent.prototype;

Child.prototype.shout = function (you) {
    alert('HEEEEY '+ you);
}

var c = new Child();
c.shout('Joe');

var p = new Parent('Joe');
p.shout('Jimmy');

请参阅此in action

此提醒HEEEEY JoeHEEEY Jimmy

父母和孩子都会获得相同的prototype对象。实际上,您可以覆盖父级的prototype

通常最好为childs原型添加一个实例:

Child.prototype = new Parent();

但是,这会导致Parent的{​​{1}}参数丢失,更重要的是执行构造函数。通常所做的是在中间放置一个空函数。将它包装在实用程序中是个好主意。

name

用法:

var hasProp = Object.prototype.hasOwnProperty, 
    extend = function(child, parent) { 
    # Copy the class-level attributes (static in Java)
    for (var key in parent) { 
        if (hasProp.call(parent, key)) child[key] = parent[key]; 
    }
    # Create the middle man
    function ctor() { 
        this.constructor = child; 
    }
    # Use parent's prototype and DON'T modify it
    ctor.prototype = parent.prototype;
    # Assign an instance to child's prototype, so modifications
    # to it are not reflected up the inheritance chain
    child.prototype = new ctor;
    # Simple convenience attribute to know your super class
    child.__super__ = parent.prototype;
    return child;
};

或者只使用CoffeeScript做正确的事™。

答案 2 :(得分:0)

以下是我使用自制继承库创建伪类的方法:

      //Namespace, ie global. could be "MyNamespace.MyClass"...
Class( "MyClass", HisClass, /* List of classes to inherit from/interfaces to implement */, {

    MyClass: function( name ) { //Constructor
    this.name = name;
    }

    "final override sayHello": function(){ //there is no implicit overriding
    alert( "hello from " + this.name );
    },

    "static create": function( name ) {
    return new this( name ); //this refers to constructor in static method
    }
});

然后您将实例化该类:

var a = new MyClass( "john" );

var a = MyClass.create( "john" );

我只实现了伪语“final”,“static”和“override”。我不知道它是否好,但它对我有用。但正如你所看到的,我并不担心那里的原型,所以如果你想创建一个伪古典库但是在你上课时必须使用原型,那么在我看来它不是那种伪古典。

答案 3 :(得分:-1)

我只想添加一个私有字段:

var that = this;

在您的所有方法中,使用that代替this