【问题标题】:How can I attach prototype to Object Literals in JS如何在 JS 中将原型附加到对象文字
【发布时间】:2012-07-08 10:42:11
【问题描述】:

我正在尝试了解 JavaScript 的原型性质,并且我正在尝试在不使用类之类的构造函数的情况下创建对象继承。

如果它们都是三个对象文字,我如何将原型链从 Animals 附加到 Cat 和 Dog?

另外,有没有办法执行 Object.create 并以文字形式添加更多属性(如 myCat)。

我已经添加了下面的代码 & 来粘贴 bin http://jsbin.com/eqigox/edit#javascript

var Animal = {
    name        : null,
    hairColor   : null,
    legs        : 4,

    getName : function() {
        return this.name;
    },
    getColor : function() {
        console.log("The hair color is " + this.hairColor);
    }
};

/* Somehow Dog extends Animal */

var Dog = {
    bark : function() {
        console.log("Woof! My name is ");
    }
};

/* Somehow Cat Extends Animal */

var Cat = {
    getName : function() {
        return this.name;
    },

    meow : function() {
        console.log("Meow! My name is " + this.name);
    }
};


/* myDog extends Dog */

var myDog = Object.create(Dog);

/* Adding in with dot notation */
myDog.name = "Remi";
myDog.hairColor = "Brown";
myDog.fetch = function() {
    console.log("He runs and brings back it back");
};


/* This would be nice to add properties in litteral form */
var myCat = Object.create(Cat, {
    name        : "Fluffy",
    hairColor   : "white",
    legs : 3, //bad accident!
    chaseBall : function(){
        console.log("It chases a ball");
    }

});

myDog.getColor();

【问题讨论】:

  • 您无法更改现有对象的原型,除非通过非标准的__proto__ 属性。

标签: javascript prototype


【解决方案1】:

您可以使用Object.create 将您定义的对象用作原型。例如:

var Dog = Object.create(Animal, {
    bark : {
        value: function() {
            console.log("Woof! My name is " + this.name);
        }
    }
});

现在您可以创建一个新的 Dog 对象:

var myDog = Object.create(Dog);
myDog.bark();  // 'Woof! My name is null'
myDog.getColor();  // 'The hair color is null'

示例:http://jsfiddle.net/5Q3W7/1/

或者,如果您在没有Object.create 的情况下工作,您可以使用构造函数:

function Animal() {
    this.name = null;
    this.hairColor = null;
    this.legs = 4;
};

Animal.prototype = {
    getName : function() {
        return this.name;
    },
    getColor : function() {
        console.log("The hair color is " + this.hairColor);
    }
}

function Dog() {
}

Dog.prototype = new Animal;
Dog.prototype.bark = function() {
    console.log("Woof! My name is " + this.name);
};

示例:http://jsfiddle.net/5Q3W7/2/

有关 Object.create 的更多信息:https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/create/

有关构造函数和原型链的更多信息: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/constructor

https://developer.mozilla.org/en/JavaScript/Guide/Inheritance_and_the_prototype_chain

【讨论】:

  • 哇,谢谢!这正是我一直在寻找的 :) 我没有意识到这是 ES5 内置的......非常酷!
【解决方案2】:

编辑:完全忽略了Object.create。 @jMerliN 的回答更合适,除非您需要更广泛的向后兼容性。


AnimalCatDog 共享 Object.prototype,因为它们是 Object 的实例,但这不是您想要放置方法的地方。

您可以使用extend 函数来模仿继承:

var Dog = {
    bark : function() {
        console.log("Woof! My name is ")
    }
}

jQuery.extend(Dog, Animal)

这可能是下划线的_.extend 或您自己的扩展函数,它只是简单地复制它的属性:

function extend(obj, source){
    for (var prop in source) {
        obj[prop] = source[prop]
    }
} 

但要小心引用:字符串、数字、布尔值等“原始”值将被复制,而对象、函数和数组将被引用

var Animal = {
    tags: [1,2,3]
}

var Dog = {
    //...
}

_.extend(Dog, Animal)

Dog.tags.push(4)

Dog.tags // [1,2,3,4]
Animal.tags // [1,2,3,4] oh no!

没有理由这样做,它容易出错并且内存效率较低;只需使用构造函数:)

【讨论】:

  • 我在 OP 上没有看到 jQuery 标签,为此使用这么大的库似乎也不合适,特别是当 OP 试图理解 javascript(即 ECMAScript)时。此外,extend 函数检查自己的属性。
  • Object.create 也设置了 [[Prototype]]:不仅仅是构造函数这样做。
  • @RobG 来吧,我说的是一个扩展函数,提到了下划线并给出了实现代码(下划线的,不做自己的检查)。不需要讨厌 jQuery。
  • @RicardoTomasi — 将对象属性从一个对象复制到另一个对象不是继承,并且期望 OP 遵循 jQuery 扩展代码要求太多(特别是当它包含像 isPlainObject 这样的方法时) )。
  • 这很有趣……只是出于好奇,coffeescript 在这里做什么:coffeescript.org/…
猜你喜欢
  • 1970-01-01
  • 2011-06-24
  • 1970-01-01
  • 2013-12-02
  • 1970-01-01
  • 2022-01-22
  • 2015-08-30
  • 2018-09-24
  • 2014-09-16
相关资源
最近更新 更多