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

相关推荐
万少9 小时前
端云一体 一天开发的元服务-奇趣故事匣经验分享
前端·ai编程·harmonyos
WindrunnerMax9 小时前
从零实现富文本编辑器#11-Immutable状态维护与增量渲染
前端·架构·前端框架
不想秃头的程序员9 小时前
Vue3 封装 Axios 实战:从基础到生产级,新手也能秒上手
前端·javascript·面试
数研小生9 小时前
亚马逊商品列表API详解
前端·数据库·python·pandas
你听得到119 小时前
我彻底搞懂了 SSE,原来流式响应效果还能这么玩的?(附 JS/Dart 双端实战)
前端·面试·github
不倒翁玩偶9 小时前
npm : 无法将“npm”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。
前端·npm·node.js
奔跑的web.9 小时前
UniApp 路由导航守
前端·javascript·uni-app
EchoEcho9 小时前
记录overflow:hidden和scrollIntoView导致的页面问题
前端·css
Cache技术分享9 小时前
318. Java Stream API - 深入理解 Java Stream 的中间 Collector —— mapping、filtering 和 fla
前端·后端