JavaScript原型与原型链:深入浅出指南

JavaScript原型与原型链:深入浅出指南

本文通过代码实例和通俗解释,带你彻底理解JavaScript中最核心的概念之一

什么是原型?

在JavaScript中,原型(Prototype) 是函数天生拥有的一个属性(prototype),它是一个对象,用于存放可以被所有实例共享的属性和方法。

ini 复制代码
// 定义构造函数
function Car(color) {
  this.color = color;
}

// 在原型上添加共享属性
Car.prototype.name = 'su7-Ultra';
Car.prototype.height = 1.4;

const car1 = new Car('orange');
const car2 = new Car('green');

console.log(car1.name); // 'su7-Ultra'(来自原型)
console.log(car2.height); // 1.4(来自原型)

原型存在的意义

  1. 将构造函数中固定的属性和方法挂载到原型上
  2. 实例创建时无需重复执行这些属性和方法
  3. 节省内存,提高性能

对象原型(隐式原型)

每个对象都有一个内置属性 __proto__(隐式原型),它的值指向创建该对象的构造函数的原型(prototype)。

ini 复制代码
function Person(name) {
  this.name = name;
}

const p1 = new Person('超超');

console.log(p1.__proto__ === Person.prototype); // true

关键概念 :实例对象的隐式原型(__proto__)等于构造函数的显示原型(prototype

new关键字的内部原理

当使用 new 调用构造函数时,会发生以下步骤:

kotlin 复制代码
function _new(constructor, ...args) {
  // 1. 创建一个空对象
  const obj = {};
  
  // 2. 将构造函数的this指向这个空对象
  // 3. 执行构造函数中的代码
  constructor.apply(obj, args);
  
  // 4. 将空对象的隐式原型指向构造函数的原型
  obj.__proto__ = constructor.prototype;
  
  // 5. 返回这个对象
  return obj;
}

// 实际使用
const car = _new(Car, 'blue');

原型链:JavaScript的继承机制

当访问对象的属性时,JavaScript引擎会:

  1. 先在对象自身属性中查找
  2. 如果找不到,则沿着 __proto__ 向上查找
  3. 直到找到 null 为止

这种查找路径形成的链条就是原型链

ini 复制代码
function GrandParent() {
  this.name = 'grandparent';
}

function Parent() {
  this.lastName = '张';
}

function Child() {
  this.firstName = '三';
}

// 设置原型链
Parent.prototype = new GrandParent();
Child.prototype = new Parent();

const child = new Child();

console.log(child.name); // 'grandparent'(来自GrandParent)
console.log(child.lastName); // '张'(来自Parent)

原型链的终点

所有原型链的终点都是 Object.prototype,而 Object.prototype.__proto__null

javascript 复制代码
console.log(Object.prototype.__proto__); // null

没有原型的对象

使用 Object.create() 可以创建没有原型的对象:

javascript 复制代码
const obj = Object.create(null); // 没有原型的对象
console.log(obj.toString); // undefined(没有继承Object的方法)

实际应用:数组方法

为什么我们创建的空数组可以直接使用 push()pop() 等方法?

javascript 复制代码
const arr = []; // 相当于 const arr = new Array()

console.log(arr.__proto__ === Array.prototype); // true
console.log(Array.prototype.hasOwnProperty('push')); // true

数组的所有方法都存在于 Array.prototype 中,所以所有数组实例都可以访问这些方法。

总结:原型与原型链要点

概念 描述 示例
prototype 函数特有的属性,存放共享方法 Car.prototype.run = function(){}
__proto__ 对象特有的属性,指向其原型 car.__proto__ === Car.prototype
原型链 通过 __proto__ 连接的链条 child -> Parent.prototype -> GrandParent.prototype -> Object.prototype -> null
属性查找 沿原型链向上查找属性 child.name 查找过程
constructor 指向创建对象的构造函数 car.constructor === Car

理解原型和原型链是掌握JavaScript面向对象编程的核心。通过原型,JavaScript实现了高效的属性共享和继承机制,这也是JavaScript区别于传统面向对象语言的重要特点。

相关推荐
小小小小宇1 小时前
前端 Service Worker
前端
只喜欢赚钱的棉花没有糖2 小时前
http的缓存问题
前端·javascript·http
小小小小宇2 小时前
请求竞态问题统一封装
前端
loriloy2 小时前
前端资源帖
前端
源码超级联盟2 小时前
display的block和inline-block有什么区别
前端
GISer_Jing2 小时前
前端构建工具(Webpack\Vite\esbuild\Rspack)拆包能力深度解析
前端·webpack·node.js
让梦想疯狂2 小时前
开源、免费、美观的 Vue 后台管理系统模板
前端·javascript·vue.js
海云前端3 小时前
前端写简历有个很大的误区,就是夸张自己做过的东西。
前端
葡萄糖o_o3 小时前
ResizeObserver的错误
前端·javascript·html
AntBlack3 小时前
Python : AI 太牛了 ,撸了两个 Markdown 阅读器 ,谈谈使用感受
前端·人工智能·后端