prototype和proto的区别

在 JavaScript 中,prototype 和 __proto__ 都与原型链和继承机制有关,但它们的含义和作用是不同的。下面来详细讲解它们的区别。


一、prototype 和 proto 的区别

特性 prototype __proto__
作用 构造函数的原型对象 实例对象的隐式原型
类型 对象 对象
访问方式 构造函数.prototype 实例对象.proto
作用场景 为构造函数定义方法和属性 用于实例对象访问原型链
修改影响 修改后影响所有实例 修改后仅影响该实例及其后代

二、prototype 和 proto 的详细解析

1. prototype 的作用

  • 每个构造函数 都有一个名为 prototype 的属性,它指向一个对象。
  • 这个对象是用来共享方法和属性的。
  • 当通过构造函数创建对象时,实例会继承 prototype 上的方法和属性。

示例:

复制代码
// 构造函数
function Person(name) {
    this.name = name;
}

// 给构造函数的 prototype 添加方法
Person.prototype.sayHello = function() {
    console.log("Hello, my name is " + this.name);
};

// 创建实例
const person1 = new Person("Alice");
const person2 = new Person("Bob");

person1.sayHello(); // 输出:Hello, my name is Alice
person2.sayHello(); // 输出:Hello, my name is Bob
注意:
  • 通过修改 Person.prototype,所有实例都能访问到新的方法或属性。
  • prototype 只有在构造函数上存在,实例本身没有 prototype 属性。

2. proto 的作用

  • 每个对象实例 都有一个 __proto__ 属性,指向创建该实例的构造函数的原型对象。
  • 这个属性是隐式原型 ,用于查找属性和方法。

示例:

复制代码
console.log(person1.__proto__ === Person.prototype); // true
console.log(person2.__proto__ === Person.prototype); // true
作用:
  • 当我们访问对象的属性或方法时,JavaScript 会先查找对象本身 ,如果没有,则沿着**__proto__** 继续查找,直到 null。
  • 这种链式查找机制 称为原型链。

三、构造函数、实例、原型三者关系

  1. 构造函数:

    • Person.prototype:原型对象。
    • Person.prototype.constructor:指向构造函数本身。
  2. 实例对象:

    • person1.__proto__:指向构造函数的原型对象,即 Person.prototype。

关系图:

复制代码
Person --> prototype --> { sayHello, constructor }
                   ↑
                 __proto__
                   ↑
              person1 / person2

四、示例验证原型链

复制代码
console.log(person1.__proto__ === Person.prototype);  // true
console.log(Person.prototype.constructor === Person); // true
console.log(Object.getPrototypeOf(person1) === Person.prototype); // true

五、修改 prototype 和 proto 的区别

修改 prototype:影响所有实例

复制代码
Person.prototype.greet = function() {
    console.log("Greetings from " + this.name);
};

person1.greet(); // Greetings from Alice
person2.greet(); // Greetings from Bob

修改 proto:仅影响当前对象

复制代码
const obj = {};
obj.__proto__ = {
    customMethod: function() {
        console.log("I am custom!");
    }
};

obj.customMethod(); // I am custom!

六、在类中的表现(ES6+)

在 ES6 中,使用 class 语法定义类,原型机制依然有效:

复制代码
class Animal {
    speak() {
        console.log("Animal speaks");
    }
}

const dog = new Animal();

console.log(dog.__proto__ === Animal.prototype);  // true
console.log(Animal.prototype.constructor === Animal); // true

七、为什么 proto 不推荐使用?

  1. 性能问题: __proto__ 是非标准特性,访问速度较慢。

  2. 兼容性问题: 早期版本的 IE 不支持。

  3. 规范性: 建议使用 Object.getPrototypeOf() 代替:

    复制代码
    console.log(Object.getPrototypeOf(person1) === Person.prototype); // true

八、总结

比较项 prototype proto
作用 构造函数的原型对象 实例对象的隐式原型
类型 对象 对象
修改效果 修改后影响所有实例 修改后仅影响该实例及其后代
使用场景 批量定义共享方法和属性 查找实例对象原型链中的属性和方法
推荐使用 是 否,建议使用 Object.getPrototypeOf() 代替

面试高频问题

  1. prototype 和 proto 有什么区别?

    • prototype 是构造函数的属性,__proto__ 是实例对象的属性。
    • prototype 用于定义共享方法和属性 ,__proto__ 用于访问原型链。
  2. 如何修改实例的原型?

    • 可以直接使用 Object.setPrototypeOf(obj, newProto); 或 obj.__proto__ = newProto;,但前者性能更优。
  3. 为什么不推荐使用 proto?

    • 性能差且非标准化,推荐使用 Object.getPrototypeOf()。

希望这些讲解能帮你彻底搞清楚 prototype 和 __proto__ 的区别!

相关推荐
lyz246859几秒前
vue3页面因参数未声明而报错的常犯错误
前端·javascript·vue.js
Hilaku15 分钟前
我重写了整个项目,但没人感谢我!
前端·javascript·程序员
“AI国潮设计-小江”32 分钟前
【SDXL实战】用AI生成“财神爷蛋糕×英歌舞人物”潮汕国潮甜品IP,附Prompt与批量生成思路
开发语言·人工智能·python·aigc
繁华的地方不一定留下你的脚印33 分钟前
C++线程如何安全停止与唤醒:std::jthread、stop_token与condition_variable
开发语言·c++
caoerzhong42 分钟前
跨境海外仓怎么管:JeeWMS 开源 Java 仓库管理系统打通头程、海外仓与尾程
java·开发语言·开源
码云数智-大飞1 小时前
新手写 Python 代码,如何规范命名、减少 Bug
开发语言·python·php
福兮说1 小时前
JS 正则的六个坑:带 g 的 test() 一真一假、空匹配死循环、replace 里的 $
开发语言·前端·javascript·正则表达式
miss1 小时前
给规则引擎加一个拖拽画布:Vue Flow 单向投影 + 布局语义分离
javascript·vue.js·canvas
码艺-Alimjan1 小时前
Web 网站打包桌面应用的另一种方式,超级简单(C# exe 33Kb)
开发语言·前端·c#
沫璃染墨1 小时前
《从零入门Linux系统篇(五十一):线程篇·四——pthread线程库详解:从线程创建到终止与分离》
linux·运维·服务器·开发语言·c++·系统架构·线程