在Javascript中使用寄生继承,是否可以实现内省实例方法

Using parasitic inheritance in Javascript, is it possible to implement introspective instance methods?

本文关键字:是否 实现 实例方法 内省 继承 Javascript 寄生      更新时间:2023-09-26

我正在尝试为以Crockford为模型的Javascript类开发一个简单的寄生接口,我想实现一些基本的内省方法。给定下面的类,如何编写正确标识对象类的class_nameis_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/

原型继承是高性能的,关于内存的经济性,相对简单,并且对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;

以上十行将通过第一个示例的所有测试。