为什么继承Shape类时需要使用Shape.prototype而非Shape?
Shape.prototype而不是直接用Shape? 嘿,这个问题问到点子上了!咱们来把这个逻辑掰扯明白,为什么这里非得用Shape.prototype,而不能直接赋值Shape给Rectangle.prototype。
首先得搞清楚JavaScript里构造函数和原型对象的核心区别:
Shape本身是一个构造函数,你用new Shape()创建实例的时候,这个函数负责初始化实例的自身属性(比如你的代码里的x和y)。但它本质上就是个普通函数,自身并没有包含move这类实例要共享的方法。Shape.prototype才是所有Shape实例共享的原型对象,你定义的move方法就挂在这里——所有通过new Shape()创建的实例,都会通过原型链找到这个方法。
回到你的代码里的关键行:Rectangle.prototype = Object.create(Shape.prototype)
这一步的核心是让Rectangle的实例能继承Shape原型上的共享方法。Object.create(Shape.prototype)会创建一个新对象,这个新对象的原型指向Shape.prototype,然后把它赋值给Rectangle.prototype,这样Rectangle的实例就能顺着原型链找到move方法了。
那如果直接写Rectangle.prototype = Shape会怎么样?
那Rectangle的原型就变成了Shape这个构造函数本身,而不是它的原型对象。这时候Rectangle的实例会继承到的是函数对象自带的属性(比如length、name这些),完全找不到move方法——因为move根本不在Shape函数上,而是在Shape.prototype上。
你提到“Shape是基础类,没有继承属性”,其实就算是基础类,它的prototype依然是实例共享方法的“仓库”。继承的本质就是让子类的原型链连接到父类的原型对象上,这样才能拿到父类实例的共享能力。
另外补充一句:你代码里的Shape.call(this)是另一个关键——它是在Rectangle的构造函数里调用Shape的构造逻辑,给Rectangle的实例初始化x和y这些自身属性,和原型链继承共享方法的步骤是互补的,两者缺一不可。
举个反例对比一下:
// 错误写法:直接赋值Shape给Rectangle.prototype function Rectangle() { Shape.call(this); } Rectangle.prototype = Shape; const rect = new Rectangle(); rect.move(10, 20); // 会报错:rect.move is not a function
因为此时rect的原型是Shape函数,上面根本没有move方法;而用Shape.prototype的话,就能正常调用move啦。
内容的提问来源于stack exchange,提问作者O.O

