2

Crockfordをモデルにした Javascript クラス用の単純な寄生インターフェイスを開発しようとしており、いくつかの基本的な内省的メソッドを実装したいと考えています。以下のクラスが与えられた場合、オブジェクト クラスを正しく識別するメソッドを作成するclass_nameにはどうすればよいでしょうか?is_a

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

    self.init = function() {
        console.debug('init', self);
        return self;
    };

    self.ama = function() {
        return "AMA Parent named " + self.name;
    };

    // Introspective methods
    self.class_name = function() {
        // returns class name as a string
    };

    self.is_a = function(obj_class) {
        // returns boolean indicating whether object is instance of obj_class
    };

    self = self.init();
    return self;
}

function Child(name) {  
    var self = new Parent(name);

    var base_ama = self.ama;
    self.ama = function() {
        var ama = base_ama();
        return ama + ". NOT!";
    };

    self.init();
    return self;
}

合格することが期待されるテストは次のとおりです。

var alice = new Parent('Alice');
assert_equal(alice.name, 'Alice');
assert_equal(alice.class_name(), 'Parent');
assert(alice.is_a(Parent));
assert_not(alice.is_a(Child));
assert_equal(alice.ama(), 'AMA Parent named Alice');

var bob = new Child('Bob');
assert_equal(bob.class_name(), 'Child');
assert_not(bob.is_a(Parent));
assert(bob.is_a(Child));
assert_equal(bob.ama(), 'AMA Parent named Bob. NOT!');

テストがセットアップされたフィドルをここで見つけることができます:

http://jsfiddle.net/LTfVa/3/

4

1 に答える 1

2

プロトタイプの継承は、パフォーマンスが高く、メモリを節約し、比較的単純で、Javascript の機能に慣用的です。私の意見では、寄生遺伝はそれらのどれでもありません。

// extend:
// receiverCtor - A constructor function that we want to extend with another constructor's behavior
// supplierCtor - The supplier of the other constructor's behavior
// receiverProperties - Any instance methods/properties you want to push onto the receiver's prototype
// receiverStatics - Any methods/properties you want to attach to the constructor function itself
//
function extend(receiverCtor, supplierCtor, receiverProperties, receiverStatics) {
    receiverProperties = receiverProperties || {};
    receiverStatics = receiverStatics || {};

    var supplierProto = supplierCtor.prototype,
        receiverProto = Object.create(supplierProto),
        prop;

    receiverCtor.prototype = receiverProto;
    receiverProto.constructor = receiverCtor;
    receiverCtor.parent = supplierProto;

    if(supplierCtor !== Object && supplierProto.constructo === Object.prototype.constructor) {
        supplierProto.constructor = supplierCtor;
    }

    for(prop in receiverProperties) {
        if(receiverProperties.hasOwnProperty(prop)) {
            receiverProto[prop] = receiverProperties[prop];
        }
    }

    for(prop in receiverStatics) {
        if(receiverStatics.hasOwnProperty(prop)) {
            receiverCtor[prop] = receiverStatics[prop];
        }
    }
}

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

function Child(name) {
    Child.parent.constructor.apply(this, arguments);
}

extend(Child, Parent);

var alice = new Parent('alice');
var bob = new Child('bob');

console.log(alice instanceof Parent);
console.log(!(alice instanceof Child));
console.log(alice.name == 'alice');

console.log(bob instanceof Parent); // inherits from parent
console.log(bob.constructor !== Parent); // but it isn't a parent
console.log(bob instanceof Child);
console.log(bob.constructor === Child);
console.log(bob.name === 'bob');

確認する jsbin は次のとおりです。

編集:extend関数は、次の非常に単純な関係の上にある構文シュガーのコレクションです。

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

function Child(name) {
    Parent.apply(this, arguments);
}

Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;

上記の 10 行は、最初の例のすべてのテストに合格します。

于 2013-09-20T18:35:41.507 に答える