JS中的object prototypes是否本质是存储methods与properties的载体?
JS原型核心概念澄清
你的理解方向符合日常使用的直观感受,但把原型单纯定义为“存储方法和属性的存储空间”并不准确,核心机制可以拆解为以下几点:
- 所有JS对象(除手动创建的无原型对象,比如
Object.create(null))都自带一个隐藏内置属性[[Prototype]],这个属性指向另一个对象,也就是当前对象的原型。日常开发中你可以通过Object.getPrototypeOf(obj)或者非标准但广泛实现的obj.__proto__访问到它。 - 原型本身确实是一个普通对象,上面挂载的属性和方法,可以被所有关联到这个原型的对象访问到。但这个访问能力不是因为对象把原型上的内容“拷贝到了自身”,而是来自JS的原型链委托查找规则:当你访问某个对象的属性/方法时,JS会先找对象自身的自有属性,如果找不到,就自动去它的
[[Prototype]]指向的原型对象上找,要是原型上也找不到,就继续找原型的原型,一直顺着链条往上,直到找到目标属性、或者走到链条末端的null返回undefined。 - 我们常说的构造函数的
prototype属性,本质就是构造函数生产出来的所有实例的公共原型:当你用new关键字调用构造函数创建实例时,会自动把实例的[[Prototype]]指向构造函数的prototype属性对应的对象,这也是为什么所有实例都能共享构造函数原型上挂载的方法。
你可以通过下面的代码直观理解这个机制:
function User(nickname) { // 实例自身的自有属性 this.nickname = nickname } // 在构造函数的原型上挂载公共方法 User.prototype.sayHello = function() { console.log(`你好,我是${this.nickname}`) } const userA = new User('张三') // 自有属性存在于对象自身 console.log(userA.hasOwnProperty('nickname')) // true // 原型上的方法不是实例的自有属性 console.log(userA.hasOwnProperty('sayHello')) // false // 调用时会顺着原型链找到原型上的sayHello方法,正常执行 userA.sayHello() // 你好,我是张三 // 原型的查找是动态的,哪怕实例已经创建完成,给原型新增的方法也能被现有实例访问 User.prototype.getNickname = function() { return this.nickname } console.log(userA.getNickname()) // 张三
如果从工程使用的角度,你完全可以把原型理解成所有关联实例共享的公共属性/方法存储区域,但一定要记住两个核心特性,避免踩坑:
- 原型上的属性是所有实例共享的,如果你直接修改原型上的引用类型值(比如数组、普通对象),所有关联实例都会受到影响
- 属性查找是运行时顺着原型链动态遍历的,不存在实例创建时的属性拷贝行为,这也是原型相比拷贝继承内存开销更低的核心原因
补充:所有普通对象的原型链最终都会走到
Object.prototype,这也是为什么所有JS对象都能调用toString、hasOwnProperty这类通用方法——这些方法都挂载在Object.prototype上,所有对象都能通过原型链找到它们。
内容的提问来源于stack exchange,提问作者Rhys Jaggan
相关产品推荐
相关产品推荐

