Javascript-原型/原型链

news/2024/9/22 20:18:58/文章来源:https://www.cnblogs.com/newBuLashi/p/18397614

OOP 面向对象

对象是什么?为什么要面向对象?面向对象的优势?

特点:迁移更灵活、代码复用性高、高度模块化的体现,例如vue中new Vue()

对象

对象是对单个物体的简单抽象 =>怎么让多个对象产生关联

对象是基础 也是容器(可以承载其他的对象) => 属性、方法、对象

  • 字面量对象:直接通过对象字面量语法创建的对象。
  • 构造函数/函数对象:设计为使用new关键字来创建新对象的函数。
// 简单对象 - 本身开放
let person1 = {name: 'Alice',age: 18,speak: function(name) {return `My name id ${name}`}
}// 函数对象 - 构造实例的函数对象
function Person() {this.name = 'Alice'this.age = 18this.speak = function(name) {return `My name is ${name}`}
}let person2 = new Person()
// 下面的构造函数可以生成上面的对象,上面的对象是下面的产物
// => ES6 使用class代替function

使用new Person()时,JavaScript会创建一个新的空对象,将其this上下文指向这个新对象,并执行Person函数体中的代码。

构造函数 - 生成对象

  • 需要一个模板
  • 类就是对象模板
  • js对象的本质不是基于类,而是基于构造函数+原型链传递方式 => constructor + prototype

比如上面new Person()出来的对象,Person本身是一个对象(函数对象),所以person2既有构造函数内的属性,又有基本对象的一些默认属性和方法,例如hasOwnProperty。所以叫基于构造函数,又以某种方式(prototype)将原生对象的属性方法传递下来,才构成了对象,不能直接和类画等号。

所以我们创建的对象既具备了constructor的内容,也具备了prototype代代相传的内容

  1. 追问:new的过程发生了什么?new是什么?new的原理?
function Person(){}
const person1 = new Person()
  1. 结构上:使用new操作符时,JavaScript首先会创建一个空对象(即一个新的对象实例)。这个新创建的对象会被用作函数(在这里我们称之为构造函数)内部this的上下文。最终,如果构造函数没有显式返回一个对象,那么这个新创建的对象(即this所引用的对象)会被返回作为new表达式的结果。

  2. 属性上:这个新创建的对象的__proto__属性(在现代JavaScript中更推荐使用Object.getPrototypeOf()来获取,因为__proto__不是一个标准属性,但它是许多JavaScript引擎中实现原型链的方式)会被设置为构造函数的prototype属性的值。这意味着新创建的对象会继承构造函数原型上的属性和方法。

  3. 关系上:在构造函数执行期间,this关键字会被绑定到新创建的对象上。因此,构造函数内部对this的任何赋值或操作都会影响到这个新对象。这是如何设置新对象的属性和方法的关键。

  4. 生命周期上:一旦new操作符开始执行,它会首先创建新对象,然后设置这个新对象的原型,接着将this绑定到这个新对象上,并执行构造函数中的代码。如果构造函数返回了一个对象,那么这个返回的对象将成为new表达式的最终结果;否则,将返回新创建的对象。

  5. 追问:实例化生成的对象彼此之间有没有联系?

    彼此独立,没有关系。既是传参独立,又是属性独立。

  6. 追问:constructor的存在意义是什么?=>构造一类物品的模板

    1. 每个实例对象被创建时,会自动拥有一个证明身份的属性constructor
    2. constructor来自于原型对象,指向了构造函数的引用。

image-20240708221635176

image-20240708221847296

  1. 追问:使用构造函数创建对象有什么问题?怎么优化呢?原型对象又是什么?

    如果多个实例有类似的方法或属性,那么多次使用constructor则是一种资源浪费。那么我们可以把方法写到原型对象上,这样每个实例被创建后都会有这个方法。

原型对象

参考链接http://t.csdnimg.cn/UdUkv

  • 每个实例创建时都具备一个constructor
  • constructor 和 继承属性 来自于new => 形成了传递链条
  • 子类上生成__proto__,将父类的.prototype放入 => 原型链
function Person(){this.name = 'Alice'this.age = '20'
}

image-20240905061813588

在JavaScript中,当定义一个函数(如Person)时,该函数自动拥有一个prototype属性,它指向一个空对象。这个对象(通常称为原型对象)。原型对象上还有一个constructor属性,它指向构造函数本身(即Person)。

let p1 = new Person()

image-20240905071242042

当使用new Person()创建实例时,JavaScript会创建一个空对象,并将其内部[[Prototype]]链接到Person.prototype,然后执行Person函数,将this指向新对象以初始化其属性。这样,实例就可以通过原型链访问到Person.prototype上定义的属性和方法。

  1. 对象与构造函数的关系

    • 使用new Person()创建的p1对象,其内部[[Prototype]]链接到Person.prototype,而不是直接链接到Person构造函数。这意味着p1Person构造函数在对象创建后不再直接“关联”,但p1可以通过其原型链间接访问到Person.prototype上的属性和方法。
  2. 多个对象共享原型

    • 通过new Person()创建的多个对象(如p1, p2, p3...)都会共享同一个Person.prototype对象。这意味着你可以在Person.prototype上添加方法和属性,这些方法和属性将自动对所有实例可用。
  3. 属性查找机制

    • 当访问一个对象的属性时(如p1.name),JavaScript会首先在该对象本身查找该属性。如果找不到,它会继续在该对象的原型(Person.prototype)上查找,依此类推,直到找到属性或到达原型链的顶端(null)。
  4. 属性屏蔽

    • 如果在对象上直接定义了一个与原型中同名的属性(如p2.name = "Blone";),则这个新属性会“屏蔽”原型中的同名属性。此时,通过该对象访问该属性将返回对象上定义的值,而不是原型中的值。
  5. 修改属性的行为

    • 当给对象添加或修改一个属性时(如p1.name = "Alan";),实际上是在对象本身上创建或更新了一个属性,而不是修改原型上的属性。这意味着其他实例(如p2)不会受到影响,它们访问的仍然是原型上的旧值(如果之前未在它们自身上定义同名属性的话)。

简化上面描述后就是

  • 对象通过其[[Prototype]]链接到构造函数的原型对象,而非构造函数本身。
  • 多个实例共享同一个原型对象,允许在原型上定义共享的方法和属性。
  • 属性查找从对象本身开始,逐级向上至原型链顶端。
  • 对象上直接定义的属性会屏蔽原型上的同名属性。
  • 修改对象属性实际上是在对象上创建或更新属性,不会修改原型属性,除非显式地通过原型对象进行修改。

image-20240905080206085

image-20240905073510275

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/792417.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在keil中使用git

目录在keil中使用git搜集官方相关帮助1.application note2.软件附带帮助文件基础准备git命令行MDK版本操作步骤1.Abstract(摘要)2.Introduction3.Workflows3.1.Centralized Workflow4.Using Git with Vision4.1.Project Files under Version Control4.2.Files that do not need…

VMware ESXi 7.0U3q macOS Unlocker 标准版和厂商定制版更新 OEM BIOS 2.7 支持 Windows Server 2025

VMware ESXi 7.0U3q macOS Unlocker 标准版和厂商定制版更新 OEM BIOS 2.7 支持 Windows Server 2025VMware ESXi 7.0U3q macOS Unlocker 标准版和厂商定制版更新 OEM BIOS 2.7 支持 Windows Server 2025 VMware ESXi 7.0U3q macOS Unlocker & OEM BIOS 2.7 标准版和厂商定…

Nexpose 6.6.267 发布下载,新增功能概览

Nexpose 6.6.267 for Linux & Windows - 漏洞扫描Nexpose 6.6.267 发布下载,新增功能概览 Nexpose 6.6.267 for Linux & Windows - 漏洞扫描 Rapid7 Vulnerability Management, release Aug 28, 2024 请访问原文链接:https://sysin.org/blog/nexpose-6/,查看最新版。…

Kettle:HSQLDB使用教程

hsqldb客户端全名:HSQL Database Manager,它是一款能够通过JDBC来访问多种数据库的工具。HSQLDB使用教程 HyperSQL Database(HSQLDB)是一个关系型数据库系统 。它被数据库应用用来开发测试部署。HyperSQL使用Java语言编写,运行在JVM上。它支持数据库访问的JDBC接口。为了使用…

SQLite 由于 mscoree.dll 损坏导致 BadImageFormatException 试图加载格式不正确的程序

本文记录 SQLite.Interop.dll 由于 mscoree.dll 文件损坏而在加载时抛出 BadImageFormatException 错误,错误信息是 0x8007000B 试图加载格式不正确的程序对应的英文错误信息如下 An attempt was made to load a program with an incorrect format. (Exception from HRESULT: …

dotnet 已知问题 警惕 StreamReader 的 EndOfStream 卡住线程

在 dotnet 里面,咱会经常使用 StreamReader 辅助类读取 Stream 的内容,比如按行读取等。如果在判断是否读取完成时,使用的是 StreamReader 的 EndOfStream 属性,则可能破坏原本的异步出让逻辑,导致线程被卡住对于带 UI 的应用程序,如 WPF 等应用来说,如果 UI 线程被卡住…

使用 Dependify 工具探索 .NET 应用程序依赖项

在大型项目中,由于各种组件的复杂性和互连性,管理依赖项可能变得具有挑战性。如果没有适当的工具或文档,可能很难浏览项目并对依赖项做出假设。以下是在大型项目中难以导航项目依赖项的几个原因:复杂性:大型项目通常由许多模块组成。了解这些依赖项如何相互交互可能会让人…

读软件设计的要素01概念

概念1. 概念 1.1. 一个软件,从运行于手机上的最小程序到大型的企业系统,都是由概念组成的,每个概念都是独立的功能单元 1.2. 软件中的可用性问题,经常可以追溯到其底层概念1.2.1. 概念帮助识别软件的不可用性1.3. 概念都是以同样形式在各种软件中重复使用的1.3.1. 将设计分…

关于在powershell与cmd查找vue版本时结果不一致

在powershell中vue版本显示为2.9.6而在Cmd中显示为@vue/cli 5.0.8原因:这是由于博主先前旧版本下载了vue2.9.6,而在卸载旧版本2.9.6时候仅删除了vue与vue.cmd文件 而powershell会先运行vue.ps1(.ps1后缀为powershell文件)来获取你的版本号 解决方案:将vue,vue.cmd,vue.ps1…

LUNARiA

本文同步发布于我的网站也算是头一次在没有任何安利和剧透,仅在看了简介的情况下就直接下单并开始游玩一部gal了。果然,没有给我留下什么遗憾呢。 游玩日志 SKYOUT-FOREVER 《LUNARiA》的背景设定在科技腾飞、算力大幅增长、AI与VR遍及各行各业、一个名为Cozmo的虚拟世界已经…

Comfyui 基础教程(一) —— 本地安装部署

前言 前面一篇文章已经介绍过,ComfyUI 和 Stable Diffusion 的关系。不清楚的朋友,看传送门 Stable Diffusion 小白的入坑铺垫 。 WebUI 以及 ComfyUI 不等于 Stable Diffusion,可以简单粗暴一点的理解为方便运行某些大模型的工具。由于本人在接触过 ComfyUI 之后,就基本放…

337. 打家劫舍 III(leetcode)

https://leetcode.cn/problems/house-robber-iii/description/基础树形dp,要点是f的定义灵神讲的很好:https://www.bilibili.com/video/BV1vu4y1f7dn/?vd_source=1bb76d0400eba0d49ad4c1dd07bc4249 /*** Definition for a binary tree node.* public class TreeNode {* in…