prototype 和 __proto__的区别

prototype__proto__ 在 JavaScript 中都与对象的原型链有关,但它们各自有不同的用途和含义。

prototype

  • prototype 是函数对象的一个属性,它指向一个对象,这个对象包含了可以由特定类型的所有实例共享的属性和方法。
  • 当我们创建一个新的对象实例时,这个实例会继承其构造函数的 prototype 对象上的属性和方法。
  • 我们可以使用 Constructor.prototype.methodName = function() { ... } 的方式来给构造函数的所有实例添加新的方法或属性。

proto

  • __proto__ 是一个非标准的属性,但在大多数现代浏览器中都可用,它指向对象的原型对象。
  • 当你访问一个对象的属性时,如果该对象自身没有这个属性,JavaScript 就会在该对象的原型链上查找这个属性。
  • 需要注意的是,由于 __proto__ 是非标准的,因此在生产环境中应避免使用它,而是使用 Object.getPrototypeOf()Object.setPrototypeOf() 这样的标准方法来访问和修改对象的原型。

区别

  • prototype 是函数对象的一个属性,而 __proto__ 是对象的一个属性(尽管是非标准的)。
  • prototype 用于定义构造函数的所有实例可以共享的属性和方法,而 __proto__ 用于在运行时访问或修改对象的原型。
  • 当你使用 new 关键字创建一个新的对象实例时,这个实例的 __proto__ 会被设置为构造函数的 prototype

示例

function Person() {}
// 通过 prototype 添加方法
Person.prototype.sayHello = function() {
  console.log("Hello, I am a person!");
};
var person1 = new Person();
// 访问 sayHello 方法,它存在于 person1 的原型链上
person1.sayHello(); // 输出 "Hello, I am a person!";
// 访问 __proto__ 来查看 person1 的原型对象
console.log(person1.__proto__ === Person.prototype); // 输出 true
// 注意:不推荐在生产环境中使用 __proto__
var a = {}, b = Object.prototype;
console.log(a.prototype === b, Object.getPrototypeOf(a)===b);// false, true
// 1、只有函数对象才有prototype,a是普通对象,没有prototype,所以a.prototype是undefined
// 2、当使用字面量 `{}` 或 `new Object()` 来创建一个对象时,这个对象会继承自`Object.prototype`。
// 3、`Object.getPrototypeOf(a)` 是一个方法,它返回指定对象的原型。对于普通对象(如通过 `{}` 或 `new Object()` 创建的对象),这个方法会返回 `Object.prototype`。

总结

prototype__proto__ 都是 JavaScript 原型链机制的一部分,但它们的用途和用法是不同的。在编写健壮和可维护的代码时,应优先使用标准方法(如 Object.getPrototypeOf()Object.setPrototypeOf())来操作对象的原型。

### JavaScript 中 `prototype` `__proto__` 的区别 #### 定义与作用范围 `prototype` 是函数对象独有的属性,用于定义该函数作为构造器创建的对象实例所继承的方法属性。当通过构造函数使用 `new` 关键字创建新对象时,这些对象会自动获得访问其构造函数的 `prototype` 属性中定义的所有方法属性的能力[^3]。 ```javascript function Animal(type) { this.type = type; } Animal.prototype.speak = function() { console.log(`The ${this.type} speaks.`); }; const dog = new Animal('dog'); dog.speak(); // 输出 "The dog speaks." ``` 相反,`__proto__` 并不是特定于任何类型的对象;几乎所有的对象都拥有此内部链接指向它们各自的原型对象。对于由构造函数产生的对象而言,`__proto__` 默认指向构造函数的 `prototype` 属性对应的对象。这使得对象能够沿着这条链向上查找未在其自身上找到的属性或方法[^4]。 ```javascript console.log(dog.__proto__ === Animal.prototype); // true ``` #### 创建方式的不同影响 由于 ES6 引入了类的概念,在现代浏览器环境下可以更直观地看到两者之间的关系: - 类声明中的静态成员会被添加到类自身的 `prototype` 上; - 实例化后的对象则持有对其构造器 `prototype` 的引用,即 `__proto__` 指向的地方。 ```javascript class Vehicle { constructor(wheels) { this.wheels = wheels; } move() { console.log(`${this.wheels}-wheeled vehicle moving`); } } // 静态方法被挂载到了Vehicle.prototype上 console.log(Vehicle.prototype.move); let bike = new Vehicle(2); // 自动设置bike.__proto__ -> Vehicle.prototype console.log(bike.__proto__.move === Vehicle.prototype.move); // true ``` 值得注意的是,尽管可以通过操作 `__proto__` 来改变现有对象的行为模式,但这通常被认为是不推荐的做法,因为它可能导致性能下降以及难以调试的问题。相比之下,利用好 `prototype` 可以为开发者提供一种更加优雅的方式来扩展功能而不破坏原有结构[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值