开发者

is it possible to assign a prototype on an existing object in javascript?

开发者 https://www.devze.com 2023-03-31 03:08 出处:网络
if i have: function Base (){ th开发者_运维问答is.sayHi = function(){ alert(\'hi\'); } } function Thing (val){

if i have:

function Base (){
    th开发者_运维问答is.sayHi = function(){
        alert('hi');
    }
}

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

var bob = new Thing("bob");

Is there some way I can now say that bob inherits from Base so that I could call:

bob.sayHi();

Basically have all the methods and properties of the Base class available on that instance?

A more relevant example with solution based on CMS's post:

Here Items could represent data returned by the server..

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());

Any further comments or solutions gladly accepted.. always interested in potential solutions to a problem ;-)


No. There is no way to assign a different [[prototype]] of an existing object, at least according the the specification. The [[prototype]] is the object resulting from the evaluation (aka "contained in") of the constructors prototype property at time of new object creation and cannot be reassigned later. (I wish it could be officially changed, but alas it is an unsupported operation and can generally be emulated via different methods.)

Some browsers/environments may choose to expose post-creation [[prototype]] assignment with non-standard approaches. The [[prototype]] object(s) can be modified (e.g. adding to String.prototype), or singleton functions can be added to the target object (see CMS's answer), or existing objects can be wrapped (essentially a dynamic "subclass") -- depending upon requirements and restrictions.

Also, there are no "classes" in Javascript: while "classical single-inheritance objected oriented classes" can be implemented in Javascript, I find it limiting to restrict oneself to the model or use such terminology in general. A language wants to be what it is.

Happy coding.


In javascript you can create a subclass of an other by setting the subclass' prototype to an instance of the base class:

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

This is the equivalent of class SubClass extends BaseClass in java.


If you also modify the prototypes after that.

If you add functions and properties to the prototype of the object's constructor, the functions and properties will be available on all the instances.

Here is an example:

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!

Now if you want to extend all Thing instances with Base, you can do it like this:

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

Or if you want to make Thing instances extend Base: (i.e. don't override methods that are already in Thing)

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

If you only want to extend a unique object instance, just assign to it:

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

bob.sayHi = base.sayHi;

bob.sayHi();

You can also call a function in the context of an object, without even assign the function to the object:

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


Note that the properties that you create within the constructor, have nothing to do with the constructor's prototype, they are own properties of the object you create using new Base();, they are not inherited. However, I think what you want to do it to apply the Base constructor function on the newly created object of 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();

Note that bob will not inherit from Base (it won't have access to properties added to Base.prototype)

bob instanceof Base;  // false
bob instanceof Thing; // true


Yes.

1) You can add Base's constructor definition directly to the bob instance

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

2) Or you can augment Thing.prototype with Base's constructor definition. The bob instance can access its prototype's new properties even if it was created before they were added

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

精彩评论

暂无评论...
验证码 换一张
取 消