关于js对象继承的问题?

function Animal(){
    this.species = "动物";
  }
function Cat(name,color){
    this.name = name;
    this.color = color;
  }
    Cat.prototype = new Animal();
  Cat.prototype.constructor = Cat;
  var cat1 = new Cat("大毛","黄色");
  alert(cat1.species); // 动物

使用prototype完成继承,
1,Cat和Animal的属性都是构造函数定义的为什么可以通过prototype去设定,两个对象的prototype应该都是空的啊?
2,为什么 Cat.prototype = new Animal();之后prototype会包含三个属性(name,color,species)呢?我想的是把cat的prototype赋给了animal,应该只有animal的属性了?

阅读 2.5k
2 个回答

问题1:
并不是空的, prototype是一个对象,他也有自己的原型链
问题2:
当Cat.prototype = new Animal()执行后,cat1继承的就是animal对象了,cat1本身有color和name属性,cat1的原型有animal属性,并不是,并不是题主所说的三个属性在一个对象中。因此当访问cat1的属性时,如果这个属性在cat1中,就直接得到,不在的话,从原型链对象中获取,直到找到这个属性为止(),或者直到顶层也没有找到,就返回undefined;

-----------------附上我前几天自己总结的,一起学习,

基于__proto__属性的原型链继承

javascript 每个对象 都有原型,是通过一个叫做__proto__属性来连接起来的,这个属性是每个对象都有的(包括函数),最顶层的为Object.prototype(更严谨地说,应该是图中的null,不过,这不是重点),从整体上来看,倒像是一棵以Object.prototype对象为根的"原型链树"。大致长这样:

img
(不要觉得javascript的原型链很深很复杂,其实事实上,一般原型链也就几层子,因为层数多了,效率就低,同时也难以维护(因为过于复杂),所以对于这棵树,更多的是拓展宽度,而不是高度)

note: 更准确的说,应该称之为"原型链森林",因为我们可以更改一个对象的__proto__属性值(尽管ES5中不建议这么做),不一定最终指向 Object.prototype

  • 现在我们知道,所有普通的原型链一般最终会指向内置的 Object.prototype,显然,这个 Object.prototype 对象不就可以内置一些比较通用的功能吗,这样如:

    • .toString()

    • .valueOf()

    • .hasOwnProperty(...)

    • .isPrototypeOf(...)

prototype属性与原型链的关系

至此,更常见到的 protoType属性没有提到,这个属性和原型链有什么关系呢。

先举个例子吧,富士康(类)生产苹果手机(实例化对象),富士康就要对它生产出来的手机负责,那么就有一个质量规范来针对于产品,同理,通过函数的构造调用来实例化一个或多个对象,那么这些新对象的原型链是不是应该由这个函数工厂来负责呢,既然如此,直觉的看,有两种方法可以让这些新对象加入到“原型链森林”的家族中。

  1. 函数也是对象啊,那也有原型链,这简单,你原型链着谁我也链着谁,反正我是你生产出来的,不行的话,我链你也行啊。

  2. 给函数一个属性,指向一个对象,用来规定通过该函数构造出来的新对象统统指向这个对象。(事实上,函数的prototype属性干的就是这个,同时,也意味着只有函数才有prototype属性)。

先来说说,为什么方法1不可以,首先,我们不是为了原型链而原型链,算了,还是直接看代码吧:(切换一下风格)

// IPone: 我要加入原型链家族,我不管,我不管
// FSK: 我虽然生产了你,但我有自己的属性
FSK.name = "fushikang"; // 名字--富士康
FSK.coordinate = "中国";// 坐标--中国
FSK.productName = "IPone"; // 产品--IPone
...

// FSK: 你看,很明显,我的属性与你的属性之间没有任何关系,你链着我没有任何用处,
// 我给你指条明路,我有一个属性,叫做prototype, 你们都跟着它吧,这也是上头的意思。

// 哦,对了,如果某一天你忘了我,在你的上一层原型链上又一个constructor属性,
// 通过它,你可以找到我。

( 切换回来 )
就这样,所有通过函数构造出来的对象(即通过new),统统指向函数的prototype属性指向的对象。

function myFun(){
    ...
}
var a = new myFun();
console.log( a.__proto__ === myFun.prototype ); // true
console.log( myFun ==== a.__proto__.constructor ); // true;
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏