JS核心知识-原型和原型链

JS设计之初借鉴了多种语言的特性。如Java的语法结构、表达式和语句;Scheme的函数式编程思想;Self的基于原型的继承面向对象;将众多语言特性融合在一起形成了现JavaScript语言的雏形。本文将讲述从Self语言借鉴而来的原型原型链

原型

每个JavaScript对象(除null外)都有一个内置属性 [[Prototype]](在语言规范中如此称呼)。这个属性指向另一个对象,也就是该对象的"原型"。

在大多数浏览器环境中,可以通过非标准的 __proto__ 属性来访问或设置一个对象的原型。但更推荐使用ES6引入的 Object.getPrototypeOf(obj)Object.setPrototypeOf(obj, prototype) 方法来操作原型,以保证代码的规范性和兼容性。

js 复制代码
var animal = {
    isEat: true
};
var bird = {
    isFly: true
};
bird.__proto__ = animal; // 将 animal 设置为 bird 的原型
console.log(bird.isFly); // true, 访问 bird 自身的属性
console.log(bird.isEat); // true, 通过原型链访问 animal 的属性

构造函数与prototype属性

函数也是对象,是一种可调用的对象。除了普通对象的特性外,函数还有一个特殊的属性 prototype(箭头函数没有此属性)。当这个函数被作为构造函数 (使用 new 关键字调用)时,这个 prototype 属性将发挥至关重要的作用。

js 复制代码
function Person(name) {
  this.name = name;
}
Person.prototype.study = true;
var p = new Person('john');
console.log(p.name); // 'jhon'
console.log(p.study); // true

当执行 new Person(...) 时,会发生以下几件事:

  1. 创建一个新的空对象。
  2. 将这个新对象的 [[Prototype]] 内部属性指向 Person.prototype
  3. 将构造函数中的 this 绑定到这个新对象上,并执行构造函数中的代码(通常用于初始化属性)。
  4. 如果构造函数没有显式返回一个对象,则返回这个新创建的对象。

这样就建立了一个关键关系:实例对象(p)的 [[Prototype]] 指向其构造函数(Person)的 prototype 对象 。同时,Person.prototype 对象上有一个 constructor 属性,指回构造函数 Person 本身。这就构成了经典的"实例-原型-构造函数"三角关系。

原型链

现在我们将视野扩大。Person.prototype 本身也是一个对象,它也有自己的 [[Prototype]] 属性。默认情况下,一个普通函数的 prototype 属性是一个继承自 Object.prototype 的对象。

因此,对于 Person 的实例 p 来说:

  • p[[Prototype]] 指向 Person.prototype
  • Person.prototype[[Prototype]] 指向 Object.prototype
  • Object.prototype[[Prototype]] 指向 null(原型链的尽头)。

这就形成了一条通过 [[Prototype]] 链接起来的链式结构,即原型链

属性查找机制

JavaScript的属性访问机制正是基于原型链。当试图访问一个对象的属性时,引擎会遵循以下步骤:

  1. 首先在对象自身属性中查找。
  2. 如果未找到,则在其原型 (即[[Prototype]]指向的对象)中查找。
  3. 如果仍未找到,则继续在原型的原型中查找,依此类推。
  4. 直到找到该属性或到达原型链的顶端(null)为止,如果到null还未找到,则返回undefined

小结

总而言之,JavaScript从Self语言借鉴的原型 概念,是其实现对象继承的核心机制。每个对象都有一个指向其原型的内部链接([[Prototype]]),而通过构造函数创建的实例,其原型指向构造函数的prototype属性。这些原型对象之间通过[[Prototype]]连接起来,形成了原型链

属性查找会沿着这条链自下而上进行,这正是JavaScript实现继承和共享属性的方式。理解原型和原型链,是掌握JavaScript面向对象编程的关键一步。

下次将介绍一下JS的继承方式。┏(^0^)┛

相关推荐
●VON5 小时前
使用 Electron 构建天气桌面小工具:调用公开 API 实现跨平台实时天气查询V1.0.0
前端·javascript·electron·openharmony
码上成长5 小时前
包管理提速:pnpm + Workspace + Changesets 搭建版本体系
前端·前端框架
Bigger5 小时前
Tauri(十九)——实现 macOS 划词监控的完整实践
前端·rust·app
穷人小水滴6 小时前
使用 epub 在手机快乐阅读
javascript·deno·科幻
ganshenml6 小时前
【Web】证书(SSL/TLS)与域名之间的关系:完整、通俗、可落地的讲解
前端·网络协议·ssl
这是个栗子7 小时前
npm报错 : 无法加载文件 npm.ps1,因为在此系统上禁止运行脚本
前端·npm·node.js
爱学习的程序媛7 小时前
《深入浅出Node.js》核心知识点梳理
javascript·node.js
HIT_Weston7 小时前
44、【Ubuntu】【Gitlab】拉出内网 Web 服务:http.server 分析(一)
前端·ubuntu·gitlab
华仔啊7 小时前
Vue3 如何实现图片懒加载?其实一个 Intersection Observer 就搞定了
前端·vue.js
JamesGosling6668 小时前
深入理解内容安全策略(CSP):原理、作用与实践指南
前端·浏览器