You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript中Dog.prototype两种原型赋值写法的结果差异对比

JavaScript两种原型继承赋值写法的核心区别

在JavaScript实现构造函数原型继承的场景下,Dog.prototype = Object.create(Animal.prototype)是标准的原型链继承实现,而Dog.prototype = {...Animal.prototype}本质是属性浅拷贝,二者执行结果存在以下本质差异:

  • 原型链连通性完全不同
    Object.create(Animal.prototype)会创建一个空对象,将这个空对象的隐式原型(__proto__)指向Animal.prototype,赋值后Dog.prototype和Animal.prototype存在直接的原型链关联,new Dog() instanceof Animal会返回true,符合继承的原型链判定规则。
    展开运算符写法生成的是一个普通新对象,该对象的隐式原型默认指向Object.prototype,和Animal.prototype没有任何原型链绑定关系,赋值后new Dog() instanceof Animal会直接返回false,本质没有实现真正的原型链继承。
  • 属性继承的时效性不同
    Object.create的写法是建立原型引用关系,赋值完成后如果给Animal.prototype新增、修改属性或方法,所有Dog的实例都可以通过原型链实时访问到这些变更。
    展开运算符写法是赋值瞬间的一次性浅拷贝,仅会把执行那一刻Animal.prototype上的自有可枚举属性复制到新对象中,后续对Animal.prototype做的任何修改,Dog的实例都无法感知。
  • 可继承的属性范围不同
    Object.create的写法依托原型链查找规则,Animal.prototype上的所有属性(包括可枚举/不可枚举属性、赋值后新增的属性),都能被Dog实例访问到。
    展开运算符仅会拷贝Animal.prototype上的自有可枚举属性,原型链上的属性、不可枚举属性(比如默认挂载在原型上的不可枚举constructor、通过Object.defineProperty定义的不可枚举成员)都不会被拷贝,Dog实例无法访问这部分内容。
  • 属性存储层级不同
    Object.create写法下,Animal.prototype上的属性不会成为Dog.prototype的自有属性,访问时是沿原型链向上查找;如果在Dog.prototype上定义同名属性,会形成属性遮蔽,不会直接修改Animal.prototype上的原始值。
    展开运算符写法下,所有被拷贝的属性都会直接成为Dog.prototype的自有属性,遍历Dog.prototype时会直接枚举到这部分成员;由于是浅拷贝,拷贝得到的引用类型值和Animal.prototype上的对应属性指向同一块内存地址,直接修改这部分引用值的内容(比如给数组push元素、给对象追加属性),会同步影响Animal.prototype上的对应值。
  • 默认constructor指向不同
    两种写法都会覆盖Dog.prototype原有的自有constructor属性,未手动修正的前提下:Object.create写法生成的原型对象没有自有constructor,会沿原型链找到Animal.prototype上的constructor,最终指向Animal;展开写法生成的原型对象没有拷贝到不可枚举的constructor属性,会沿自身原型链找到Object.prototype上的constructor,最终指向Object。
function Animal() {}
Animal.prototype.say = function() { console.log('animal say') }
// 给Animal原型添加不可枚举方法
Object.defineProperty(Animal.prototype, 'breathe', {
  value: function() { console.log('breathe') },
  enumerable: false
})

// 写法1:Object.create 实现标准原型继承
function Dog1() {}
Dog1.prototype = Object.create(Animal.prototype)
const d1 = new Dog1()
console.log(d1 instanceof Animal) // 输出 true
d1.breathe() // 正常输出 'breathe'
// 赋值后给Animal原型新增方法
Animal.prototype.run = function() { console.log('run') }
d1.run() // 正常输出 'run'

// 写法2:展开运算符浅拷贝
function Dog2() {}
Dog2.prototype = {...Animal.prototype}
const d2 = new Dog2()
console.log(d2 instanceof Animal) // 输出 false
d2.breathe() // 抛出类型错误:d2.breathe is not a function
d2.run() // 抛出类型错误:d2.run is not a function

内容的提问来源于stack exchange,提问作者Michael K

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 19:36:45