JavaScript中__proto__与prototype的关系深入理解


在JavaScript中,`__proto__` 和 `prototype` 是两个密切相关但又有所区别的概念,它们共同构成了JavaScript原型链的基础。下面我将对这两个概念进行深入的解析。

### `__proto__`

- `__proto__` 是一个非标准但广泛支持的属性,它指向了对象内部原型(prototype)的链接。每个对象在创建时都会自动获得这个属性,并指向其构造函数的 `prototype` 对象。

- 需要注意的是,由于 `__proto__` 不是标准属性,虽然它在大多数JavaScript环境中都可用,但使用它可能会带来兼容性问题或未来的不确定性。因此,更推荐使用 `Object.getPrototypeOf()` 方法来获取对象的原型。

### `prototype`

- `prototype` 是函数对象的一个属性,它指向了一个对象,这个对象将被用作由该构造函数创建的所有实例的原型。

- 当使用构造函数创建新对象时,新对象的内部原型(`__proto__`)会被设置为构造函数的 `prototype` 属性的值。这样,新对象就可以继承构造函数原型对象上的属性和方法。

- `prototype` 属性主要用于实现基于原型的继承。

### 关系

- 简而言之,一个对象的 `__proto__` 指向了创建它的构造函数的 `prototype` 属性。

- 换句话说,当你访问一个对象的属性或方法时,如果该对象本身没有这个属性或方法,JavaScript 引擎就会去查找对象的原型(即 `__proto__` 指向的对象),看是否有这个属性或方法。这个过程会一直沿着原型链向上查找,直到找到该属性或方法,或者到达原型链的顶端(通常是 `Object.prototype` 的原型,即 `null`)。

### 示例


function Person(name) {
    this.name = name;
}

Person.prototype.sayHello = function() {
    console.log("Hello, my name is " + this.name);
};

var person1 = new Person("Alice");

// person1 的 __proto__ 指向 Person.prototype
console.log(person1.__proto__ === Person.prototype); // true

// 通过原型链访问 sayHello 方法
person1.sayHello(); // 输出: Hello, my name is Alice

在这个示例中,`person1` 对象是通过 `Person` 构造函数创建的。`person1` 的 `__proto__` 属性指向了 `Person.prototype`,这使得 `person1` 能够继承 `Person.prototype` 上的 `sayHello` 方法。