在 JavaScript 的世界中,prototype
和 __proto__
是两个关键概念,特别是当你在理解原型链和继承时。本文将通过不同的视角来解释它们的区别和关系。
一、背景介绍
JavaScript 中的引用类型包括 Object
、Function
、Array
、Date
等。其中,Object
和 Function
是 JavaScript 语言中的基础。尽管 JavaScript 没有类的概念,但函数被用来模拟类的行为。因此,理解 prototype
和 __proto__
对于掌握 JavaScript 的面向对象编程至关重要。
二、prototype
和 [[Prototype]]
prototype
是用来区分函数与普通对象的一个重要属性:
-
当一个函数被创建时,JavaScript 会自动为该函数添加一个
prototype
属性。这个属性的值是一个对象,该对象默认包含一个constructor
属性,指向函数本身。function Example() {} console.log(Example.prototype.constructor === Example); // true
-
每个对象都有一个隐藏的内部属性
[[Prototype]]
,它指向对象的原型。这一属性不能直接访问,但可以通过__proto__
访问器属性来获取和修改。
三、prototype
和 __proto__
的关系
__proto__
存在于所有对象上,而prototype
只存在于函数对象上。- 对象通过其
__proto__
属性指向构造它的函数的prototype
对象,从而实现继承。 - 当你使用
new
操作符创建一个对象时,构造函数的prototype
属性会被赋值给新对象的__proto__
属性。
例如:
function Person(name) {
this.name = name;
}
var john = new Person('John');
console.log(john.__proto__ === Person.prototype); // true
console.log(Person.prototype.constructor === Person); // true
在这个例子中,当我们使用 new
操作符创建 john
对象时,Person
的 prototype
属性就成为 john
对象的 __proto__
。
四、标准与非标准属性
__proto__
是非标准的,尽管很多浏览器实现了它以提供对对象原型的访问。现代 JavaScript 提供了标准的Object.getPrototypeOf
和Object.setPrototypeOf
方法来获取和设置对象的原型。prototype
是标准的,是每个函数(作为构造函数)所特有的属性,用于定义由该函数创建的对象的原型。
五、总结
prototype
是构造函数的属性,用于定义实例对象的共享属性和方法。__proto__
是实例对象的属性,用于指向其构造函数的prototype
,从而形成原型链。- 现代 JavaScript 推荐使用
Object.getPrototypeOf
和Object.setPrototypeOf
代替__proto__
进行原型操作,以确保代码的兼容性和规范性。