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区别于传统面向对象语言的重要特点。

相关推荐
摸鱼仙人~23 分钟前
styled-components:现代React样式解决方案
前端·react.js·前端框架
sasaraku.1 小时前
serviceWorker缓存资源
前端
RadiumAg2 小时前
记一道有趣的面试题
前端·javascript
yangzhi_emo2 小时前
ES6笔记2
开发语言·前端·javascript
yanlele2 小时前
我用爬虫抓取了 25 年 5 月掘金热门面试文章
前端·javascript·面试
中微子3 小时前
React状态管理最佳实践
前端
烛阴4 小时前
void 0 的奥秘:解锁 JavaScript 中 undefined 的正确打开方式
前端·javascript
中微子4 小时前
JavaScript 事件与 React 合成事件完全指南:从入门到精通
前端
Hexene...4 小时前
【前端Vue】如何实现echarts图表根据父元素宽度自适应大小
前端·vue.js·echarts
初遇你时动了情4 小时前
腾讯地图 vue3 使用 封装 地图组件
javascript·vue.js·腾讯地图