JavaScripts入门篇————js原型的底层原理

前言

之前,我们已经通过学习对象与构造函数了解到v8 在对象中查找属性,会先查找对象自己的属性,找不到再查找原型上的属性,那么该句中的原型到底所指何物,那就是我们今天探讨的主题。在这篇文章中,我们将从原型的基础概念讲起,逐步深入到原型链的工作原理、 proto 与 prototype 的区别,以及如何利用原型实现继承等核心话题。希望通过这篇文章,能帮你彻底揭开 JavaScript 原型系统的神秘面纱。

prototype(显示原型)

protype是函数天生就拥有的一个属性, 我们可以将一些属性和方法挂载在原型上,在创建实例后,实例就可以调用这个属性和方法,我们可以将一些公用的属性和方法添加在原型上,减少构造函数在执行时的性能开销。听起来是不是晦涩难懂,举个代码例子让你深刻理解:

js 复制代码
Array.prototype.abc = function(){
    console.log('abc')
}

const arr = []  //new Array()
arr.unshift(1)
console.log(arr)
arr.abc()

由对象的知识我们认识到,v8在创建一个数组开始时,其实是new了一个对象数组,而该对象中存在一个显示存在的属性即unshift函数,插入1,接着我们自己在原型上自己定义了一个abc方法,从而做到为arr这一基本类型添加操作,输出abc。这就是设计显示原型的方便之处,便于扩展对象功能。

作用体现

再举一个用了显示原型便利实现扩展功能的例子,

js 复制代码
function Car(color){
    // var this = {}  //1
    this.color = color
    this.name = 'su7'
    this.long = 5000
    this.height = 1000
    this.color = color//2


    // this.__proto__ = Car.prototype  //3__proto__是实例对象的显示原型,prototype是构造函数的隐式原型,两个指向同一个对象
    // return this //4

}
const car = new Car('red')
console.log(car)

可以预见,当我们要批量访问car函数时,我们的v8引擎会重复new car函数,使函数内的前几个属性一直被调用,从而失去时间性能。而当我们引入原型时:

js 复制代码
Car.prototype.name = 'su7'  
Car.prototype.long = 5000
Car.prototype.height = 1000
function Car(color){
    // var this = {}  //1
    this.color = color
    this.name = 'su7'
    this.long = 5000
    this.height = 1000
    this.color = color//

}
const car = new Car('red')
car.name = 'benz'
console.log(car)

console.log(car.__proto__)

我们通过在原型上添加属性从而实现了复用,每次new一个car时,这些属性会被"隐藏"在prototype里,可以访问。 通俗的说

prototype 是构造函数的 :制造商的零件库(给所有实例共享用的)

proto(隐式原型)

1.每个对象都有一个隐式的原型__proto__属性,该属性也是一个对象

  1. v8 在访问对象中的一个属性时,会先访问对象中显示存在的属性,如果不存在,会去对象的隐式原型上查找
  2. 实例对象的隐式原型 === 构造函数的现实原型
  3. onstructor 构造器属性,记录该实例对象是由谁创建的,接着看例子 5
js 复制代码
Person.prototype.age = function(){
    console.log('18岁')
}

function Person(){
    this.name = '张三'
}
const p = new Person()
// console.log(p);
p.age()
console.log(p.__proto__===Person.prototype)

可以看到11行打印true,那我们结合代码来拆解原理:

第一步:创建构造函数和原型对象,- p.proto 是实例的「隐形指针」,指向那个仓库 -第 11 行的 === 就是在验证这个指针是否真的指向了仓库 这就是 JavaScript 原型系统的核心原理!即

一表区分:

概念 prototype proto
所属者 构造函数(如 Person ) 实例对象(如 p )
别称 显示原型 隐式原型
作用 存放共享属性/方法的仓库 指向构造函数的 prototype

原型链

说完prototype(显示原型)和__proto__(隐式原型),我们聊聊他们之间查找关系,v8在访问对象中的一个属性时,会先访问对象中的显示存在的属性,如果没有,就会去对象的隐式原型上查找,如果还没有,就顺着隐式原型一直往上找,直到找到null ,这个查找关系,就叫做原型链,通俗的讲,- 一层一层往上找 : 自己没有 → 爸爸 → 爷爷 → ... → null

  • proto 是链条 :把所有原型对象串起来
  • null 是终点 :找到 null 还没找到,就返回 undefined 接下来看一段示例
js 复制代码
GrandFather.prototype.house=function(){
    console.log('汤臣一品')
}

function GrandFather() {
  this.card = '1234567890123456'
}
Father.prototype = new GrandFather()

function Father() {   //{card: '1234567890123456'}
  this.lastName = '张'
}
Child.prototype = new Father( )    //{lastName: '张'}
function Child() {
  this.age = 18
}
                                    //new Object()
const p = new Child() //p.__proto__ = Child.prototype.__proto__ = Object.prototype.__proto__ = null

p.house()

可以看到最后输出的是GrandFather.prototype.house里的函数属性,那么我们来梳理一下逻辑:

console.log(xiaoming.name) // 1. 先找自己 → '小明' ✅

console.log(xiaoming.car) // 2. 自己没有 → 找爸爸 → '特斯拉' ✅

console.log(xiaoming.money) // 3. 爸爸也没有 → 找爷爷 → 1000000 ✅

xiaoming.house() // 4. 继续找 → 爷爷的原型 → '🏠 汤臣一品' ✅

看看原型链结构

console.log(p.proto === Child.prototype) // true

console.log(Child.prototype.proto === Father.prototype) // true

console.log(Father.prototype.proto === GrandFather.prototype) // true

console.log(GrandFather.prototype.proto === Object.prototype) // true(终点前)

console.log(Object.prototype.proto === null) // true(终点!)

接下来看一张原型链图片,理解之后你就能彻底知道这种查找关系背后的逻辑:

过程参考:const f1 = new Foo()

  1. f1.proto = Foo.prototype

  2. Foo.prototype.proto = Object.prototype

  3. Object.prototype.proto = null

  4. Foo.proto = Function.prototype

  5. Function.prototype.proto = Object.prototype

  6. Function.proto = Function.prototype

相关推荐
ZJU_统一阿萨姆36 分钟前
【DSH】如何将 DeepSeek Harness 嵌入生产环境?万字解构 DeepSeek Agent Harness 的运行机制与安全边界
前端·javascript·安全
用户9210802628639 分钟前
4. 前端地图大量点位实时更新优化:后端推增量,前端做 diff
前端
SoaringHeart1 小时前
Flutter最佳实践:Web项目中文字体首次加载乱码问题解决
前端·flutter
西安小哥2 小时前
破局与重生:大厂前端如何借力 AI 转型“超级全栈“
前端·人工智能
sunly_2 小时前
TypeScript总结:16、面向对象速查
前端·javascript·typescript
张元清2 小时前
React useInterval Hook:没有过期闭包的 setInterval (2026)
javascript·react.js
MXN_小南学前端2 小时前
React超长文本域中实现“返回顶部”浮动按钮
前端·javascript·react.js
学习嵌入式的小周2 小时前
Notepad++8.8.7下载安装(附安装包)
前端·notepad++
gs801403 小时前
解构 Cordis:面向“时空可组合性”的 TypeScript 元框架深度剖析
前端·javascript·typescript
Highcharts.js3 小时前
Highcharts大数据渲染模块Boost实战与参数最佳实践表
javascript·数据可视化·boost·highcharts·大数据渲染·加速配置·参数表