Javascript:原型继承和原型属性

Jan*_*anD 4 javascript inheritance

我在JS中有一个简单的代码片段,它使用原型继承.

function object(o) {
    function F() {}
    F.prototype = o;
    return new F();
}

//the following code block has a alternate version
var mammal = {
    color: "brown",
    getColor: function() {
        return this.color;
    }
}

var myCat = object(mammal);
myCat.meow = function(){return "meow";}
Run Code Online (Sandbox Code Playgroud)

工作正常,但添加这个:

mammal.prototype.kindOf = "predator";
Run Code Online (Sandbox Code Playgroud)

才不是.("哺乳动物.原型未定义")

因为我猜对象可能没有原型我重写了它,用以下代码替换了var mammal = {... block:

function mammal() {
    this.color = "brown";
    this.getColor = function() { return this.color; }
}
Run Code Online (Sandbox Code Playgroud)

这给了我一堆其他错误:

"函数
.prototype.toString调用不兼容的对象",如果我尝试调用_myCat.getColor()
"myCat.getColor不是函数"


现在我完全糊涂了.在阅读了Crockford和Flanagan后,我没有得到错误的解决方案.如果有人知道的话会很棒

- 为什么原型未在第一个例子中定义(这是最重要的问题;我认为在object()函数中显式设置的原型)

- 为什么我试图在object()函数中使用哺乳动物函数作为原型对象时遇到这些奇怪的错误?

由问题的创建者编辑: 这两个链接也有很多帮助:

Prototypes_in_JavaScript在spheredev维基解释原型属性工程relativily简单的方式.它缺少的是一些试用代码示例.莫里斯约翰的文章提供了一些很好的例子.我个人觉得解释并不像第一个链接那么简单,但仍然非常好.即使在我真正得到它之后,最困难的部分实际上并不是将.prototype属性与对象的内部[[Prototype]]混淆.

CMS*_*CMS 5

您得到第一个错误(mammal.prototype未定义)因为mammal是一个对象,该prototype属性在创建时添加到函数对象中,并且当您希望将函数作为构造函数时应该使用它.

我认为你把这个属性与内部[[Prototype]]财产混淆了.

[[Prototype]]属性只能由new操作员通过[[Construct]]内部操作设置.

此属性不可访问(尽管有一些方法,例如Mozilla实现obj.__proto__;或新的ECMAScript 5 Object.getPrototypeOf方法).

关于你的第二个问题,你会得到这些错误,因为你正在创建一个新对象,它继承自一个函数,而不是来自另一个对象.

关于什么 :

var mammal = {
  color: "brown",
  getColor: function(){
    return this.color;
  },
  kindOf: "mammal" // "base" value
};
// ...
var tiger = object(mammal);
tiger.roar = function(){return "roar";}
tiger.kindOf = "predator"; // specific value
Run Code Online (Sandbox Code Playgroud)

在上面的代码片段中,所有继承的实例都mammal将具有一个kindOf属性,以后您可以在创建更具体的哺乳动物对象时进行更改.

编辑:为了回应你的评论,是的,语言本身为你提供了工具,知道该Object.prototype.hasOwnProperty方法,它返回一个布尔结果,指示对象是否具有物理上指定的属性,例如:

var obj = {
  foo: 'bar'
};

obj.hasOwnProperty('foo'); // true
obj.hasOwnProperty('toString'); // false, inherited from Object.prototype
Run Code Online (Sandbox Code Playgroud)

你也可以直接调用这个方法Object.prototype,所以如果有人hasOwnProperty在一个对象上命名一个属性,它就不会失败:

Object.prototype.hasOwnProperty.call(obj, 'foo'); // true
Run Code Online (Sandbox Code Playgroud)