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

相关推荐
PineappleCoder2 小时前
搞定用户登录体验:双 Token 认证(Vue+Koa2)从 0 到 1 实现无感刷新
前端·vue.js·koa
Min;2 小时前
cesium-kit:让 Cesium 开发像写 UI 组件一样简单
javascript·vscode·计算机视觉·3d·几何学·贴图
EveryPossible3 小时前
展示内容框
前端·javascript·css
伊织code3 小时前
WebGoat - 刻意设计的不安全Web应用程序
前端·安全·webgoat
子兮曰3 小时前
Vue3 生命周期与组件通信深度解析
前端·javascript·vue.js
拉不动的猪3 小时前
回顾关于筛选时的隐式返回和显示返回
前端·javascript·面试
yinuo3 小时前
不写一行JS!纯CSS如何读取HTML属性实现Tooltip
前端
gnip4 小时前
脚本加载失败重试机制
前端·javascript
遗憾随她而去.4 小时前
Uni-App 页面跳转监控实战:快速定位路由问题
前端·网络·uni-app
码农学院4 小时前
MSSQL字段去掉excel复制过来的换行符
前端·数据库·sqlserver