是否可以在javascript中为现有对象分配原型?

时间:2011-08-28 18:52:32

标签: javascript inheritance

如果我有:

function Base (){
    this.sayHi = function(){
        alert('hi');
    }
}

function Thing (val){
    this.value = val;
}

var bob = new Thing("bob");

有没有什么方法我现在可以说bob继承自Base,以便我可以调用:

bob.sayHi();

基本上可以在该实例上使用Base类的所有方法和属性吗?

基于CMS帖子的解决方案的更相关示例:

此处项目可以表示服务器返回的数据..

var Items = [
    { sku: 123, type:'buggy', title:'This is a title', description: 'this is a description' },
    { sku: 234, type: 'baby-monitor', title: 'This is a title 2', description: 'this is a description 2' }
]

function ItemMethods() {
    this.BannerHTML = function () {
        return '<div class="banner _item_' + this.type + '_' + this.sku + '"><h2>' +
            this.title + '</h2><p>' +
            this.description + '</p></div>';
    };
}

Items.GetBySKU = function (code) {
    for (var i = 0; i < Items.length; i++) {
        if (Items[i].sku == code) {
            return Items[i];
        }
    }
};

$.each(Items, function (i, item) {
    ItemMethods.apply(item);
});

alert(Items.GetBySKU(234).BannerHTML());

任何进一步的评论或解决方案都很乐意接受..总是对问题的潜在解决方案感兴趣; - )

4 个答案:

答案 0 :(得分:6)

否。至少根据规范,无法为现有对象分配不同的 [[prototype]] [[prototype]] 是在新对象创建时构造函数prototype property 的评估(也称为“包含在”)中产生的对象以后不能重新分配。 (我希望它可以正式更改,但是它是一个不受支持的操作,并且通常可以通过不同的方法进行模拟。)

某些浏览器/环境可能会选择使用非标准方法公开创建后的 [[prototype]] 。可以修改 [[prototype]]对象(例如添加到String.prototype),或者可以将单例函数添加到目标对象(请参阅CMS的答案),或者现有对象可以是包装(基本上是一个动态的“子类”) - 取决于要求和限制。

此外,Javascript中没有“类”:虽然“经典的单继承对象定向类”可以在Javascript中实现,但我发现限制自己限制模型或使用这样的术语。语言希望成为现实。

快乐的编码。

答案 1 :(得分:2)

在javascript中,您可以通过将子类'prototype设置为基类的实例来创建另一个的子类:

function BaseClass() {
    this.baseFunction = function() {
    };
};

function SubClass() {
};
SubClass.prototype = new BaseClass;
SubClass.prototype.someFunction = function() {
};

// create an instance of SubClass
var obj = new SubClass;

// SubClass truly extends BaseClass
obj instanceof BaseClass // true
obj instanceof SubClass // true

// the instance has both methods of BaseClass and SubClass
typeof obj.someFunction // Function
typeof obj.baseFunction // Function

这相当于java中的class SubClass extends BaseClass


如果你之后也修改了原型。

如果将函数和属性添加到对象构造函数的原型中,则函数和属性将在所有实例上可用。

以下是一个例子:

function Thing (val){
    this.value = val;
}

var bob = new Thing("bob");

console.log(bob.foo); // undefined

Thing.prototype.foo = function() {
    console.log('foo!');
};

console.log(bob.foo); // function()
bob.foo(); // foo!

现在,如果你想用Base扩展所有Thing实例,你可以这样做:

var base = new Base;
for (var k in base) {
    Thing.prototype[k] = base[k];
}

或者如果你想让Thing实例扩展Base :(即不要覆盖已经存在的东西的方法)

var base = new Base;
for (var k in base) {
    if (Thing.prototype[k]) continue;
    Thing.prototype[k] = base[k];
}

如果您只想扩展一个唯一的对象实例,只需指定它:

var bob = new Thing("bob");
var base = new Base();

bob.sayHi = base.sayHi;

bob.sayHi();

您也可以在对象的上下文中调用函数,甚至不将函数赋值给对象:

var base = new Base();
base.sayHi.call(bob);

答案 2 :(得分:1)

请注意,您在构造函数中创建的属性与构造函数的prototype无关,它们是您使用new Base();创建的对象的自己的属性,他们不是遗传的。但是,我认为您要在Base新创建的对象上应用 {/ 1}}构造函数来执行此操作:

Thing

请注意,function Base (){ this.sayHi = function(){ alert('hi'); } } function Thing (val){ Base.apply(this, arguments); this.value = val; } var bob = new Thing("bob"); bob.sayHi(); 不会从bob继承(它无法访问添加到Base的属性)

Base.prototype

答案 3 :(得分:1)

是。

1)您可以将Base的构造函数定义直接添加到bob实例

Base.call(bob);
bob.sayHi(); //hi

2)或者你可以使用Base的构造函数定义来扩充Thing.prototype。 bob实例可以访问其原型的新属性,即使它是在添加它们之前创建的

var bob = new Thing("bob");
Base.call(Thing.prototype);
bob.sayHi(); //hi