推荐答案
访问一个对象的原型主要有两种方式:
__proto__属性: 这是每个对象(除了null)都拥有的一个内部属性,指向创建该对象的构造函数的prototype属性。它可以直接访问到对象的原型。Object.getPrototypeOf(obj)方法: 这是一个标准方法,接受一个对象作为参数,返回该对象的原型。
__proto__ 和 prototype 的区别如下:
__proto__:- 是对象的属性。
- 指向该对象的原型对象(即创建该对象的构造函数的
prototype属性)。 - 主要用于在对象实例上访问其原型链。
- 不推荐在生产环境中使用,因为不是所有环境都支持,且可能影响性能。
prototype:- 是函数的属性。
- 指向该函数通过
new关键字创建的实例的原型对象。 - 主要用于定义构造函数创建的实例的原型,实现继承。
本题详细解读
访问对象原型的方式
__proto__ 属性
每个 JavaScript 对象都有一个内部属性 [[Prototype]],在早期 JavaScript 中没有直接访问这个内部属性的途径。为了方便开发者,浏览器厂商实现了 __proto__ 属性,使得我们可以通过 object.__proto__ 来访问对象的原型。
// www.javascriptcn.com code example
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
console.log('Hello, ' + this.name);
};
const person1 = new Person('Alice');
console.log(person1.__proto__ === Person.prototype); // true
console.log(person1.__proto__.constructor === Person) // true上面的例子中, person1 的 __proto__ 属性指向 Person.prototype。 需要注意的是,虽然现在 __proto__ 属性已被标准化,但依然建议使用 Object.getPrototypeOf() 方法。
Object.getPrototypeOf(obj) 方法
Object.getPrototypeOf() 方法是获取对象原型的标准方法。
// www.javascriptcn.com code example
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
console.log("Generic animal sound");
}
const dog = new Animal("Buddy");
const prototypeOfDog = Object.getPrototypeOf(dog);
console.log(prototypeOfDog === Animal.prototype); // true__proto__ 和 prototype 的区别
| 特性 | __proto__ |
prototype |
|---|---|---|
| 类型 | 对象的属性 | 函数的属性 |
| 作用 | 指向该对象实例的原型对象 | 指向通过该构造函数创建的实例的原型对象 |
| 使用场景 | 用于在对象实例上访问原型链 | 用于定义构造函数创建实例的原型 |
| 兼容性 | 浏览器实现,标准化但仍不推荐直接使用 | 标准属性 |
| 修改能力 | 可以修改对象的原型(不推荐) | 可以修改构造函数的原型 |
总结来说:
__proto__是对象实例上的属性,用于访问原型链上的原型对象,相当于查找当前对象的“爸爸”。prototype是函数(构造函数)上的属性,用于定义将来通过该构造函数创建的对象的原型,相当于给未来的“儿子”设定共同的特征。