深入JS原型、原型链和继承

article/2025/9/13 0:38:03

文章目录

  • 一、原型的理解
    • 1.对象的原型
    • 2.函数的原型
    • 3.constructor
  • 二、原型链
    • 1.概念和理解
    • 2.原型链中最顶层的原型
  • 三、继承
    • 1.原型链继承:
    • 2.借用构造函数继承:

一、原型的理解

1.对象的原型

JavaScript当中每个对象都有一个特殊的内置属性[[prototype]] ,这个特殊的对象可以指向另外-一个对象。那么这个对象有什么用呢?

  • 当我们通过引用对象的属性key来获取一个value时,它会触发[[Get]]的操作;
  • 这个操作会首先检查该属性是否有对应的属性,如果有的话就使用它;
  • 如果对象中没有改属性,那么会访问对象[[prototype]]内置属性指向的对象上的属性;

那么如果通过字面量直接创建一个对象,这个对象也会有这样的属性吗?如果有,应该如何获取这个属性呢?

答案是有的,只要是对象都会有这样的一个内置属性;

获取的方式有两种:

  • 方式一 :通过对象的_ proto_ 属性可以获取到 (但是这个是早期浏览器自己添加的,存在一定的兼容性问题) ;
  • 方式二:通过Object.getPrototypeOf方法可以获取到;

2.函数的原型

这里我们又要引入一个新的概念:

所有的函数都有一个prototype的属性 因为它是一个函数,才有了这个特殊的属性; 而不是它是一个对象,所以有这个特殊的属性;

3.constructor

事实上原型对象上面是有一个属性的:constructor
默认情况下原型上都会添加一个属性叫做constructor,这个constructor指向当前的函数对象

内存表现:
在这里插入图片描述

二、原型链

首先说一下:new关键字的步骤如下:

在内存中创建一个新的对象(空对象); 这个对象内部的__proto__属性会被赋值为该构造函数的prototype属性
那么也就意味着我们通过Person构造函数创建出来的所有对象的__proto__属性都指向Person.prototype:

1.概念和理解

首先,从一个对象上获取属性,如果在当前对象中没有获取到就会去它的原型上面获取。这样,如果在这个对象内部没找到这个属性,就会往上去他的原型上去寻找,还没找到则继续去原型的原型对象上去寻找。

2.原型链中最顶层的原型

var obj1 = {};
var obj2 = new Object()
console.log(obj1.__proto__ === obj2.__proto__);//true
console.log(obj1.__proto__ === Object.prototype);//true
console.log(obj1.__proto__);//null
console.log(Object.getOwnPropertyDescriptors(Object.prototype))

console.log(obj1.proto);//null
实际上obj1.__proto__也就是Object.prototype并不是空,只是Object.prototype对象里面的可枚举属性设置成false了,我们可以通过Object.getOwnPropertyDescriptors(Object.prototype)去输出这些属性,有valueOf,toString函数等等。
在这里插入图片描述
从我们上面的Object原型我们可以得出一个结论:原型链最顶层的原型对象就是Object的原型对象

三、继承

1.原型链继承:

// 父类: 公共属性和方法
function Person() {this.name = "why"this.friends = []
}Person.prototype.eating = function() {console.log(this.name + " eating~")
}// 子类: 特有属性和方法
function Student() {this.sno = 111
}var p = new Person()
Student.prototype = pStudent.prototype.studying = function() {console.log(this.name + " studying~")
}// name/sno
var stu = new Student()// console.log(stu.name)
// stu.eating()// stu.studying()// 原型链实现继承的弊端:
// 1.第一个弊端: 打印stu对象, 继承的属性是看不到的
// console.log(stu.name)// 2.第二个弊端: 创建出来两个stu的对象
var stu1 = new Student()
var stu2 = new Student()// 直接修改对象上的属性, 是给本对象添加了一个新属性
stu1.name = "kobe"
console.log(stu2.name)// 获取引用, 修改引用中的值, 会相互影响
stu1.friends.push("kobe")console.log(stu1.friends)
console.log(stu2.friends)// 3.第三个弊端: 在前面实现类的过程中都没有传递参数
var stu3 = new Student("lilei", 112)

原型链继承的弊端:

  • 1.第一个弊端: 打印stu对象, 继承的属性是看不到的
  • 2.第二个弊端: 创建出来两个stu的对象
  • 3.第三个弊端: 在前面实现类的过程中都没有传递参数

内存图:
在这里插入图片描述

2.借用构造函数继承:

做法:

在子类型构造函数的内部调用父类型构造函数. 因为函数可以在任意的时刻被调用;
因此通过apply()和call()方法也可以在新创建的对象上执行构造函数

实例:

// 父类: 公共属性和方法
function Person(name, age, friends) {// this = stuthis.name = namethis.age = agethis.friends = friends
}Person.prototype.eating = function() {console.log(this.name + " eating~")
}// 子类: 特有属性和方法
function Student(name, age, friends, sno) {Person.call(this, name, age, friends)// this.name = name// this.age = age// this.friends = friendsthis.sno = 111
}var p = new Person()
Student.prototype = pStudent.prototype.studying = function() {console.log(this.name + " studying~")
}// name/sno
var stu = new Student("why", 18, ["kobe"], 111)// console.log(stu.name)
// stu.eating()// stu.studying()// 原型链实现继承已经解决的弊端
// 1.第一个弊端: 打印stu对象, 继承的属性是看不到的
console.log(stu)// 2.第二个弊端: 创建出来两个stu的对象
var stu1 = new Student("why", 18, ["lilei"], 111)
var stu2 = new Student("kobe", 30, ["james"], 112)// // 直接修改对象上的属性, 是给本对象添加了一个新属性
// stu1.name = "kobe"
// console.log(stu2.name)// // 获取引用, 修改引用中的值, 会相互影响
stu1.friends.push("lucy")console.log(stu1.friends)
console.log(stu2.friends)// // 3.第三个弊端: 在前面实现类的过程中都没有传递参数
// var stu3 = new Student("lilei", 112)

内存图:
在这里插入图片描述

弊端:

1.第一个弊端: Person函数至少被调用了两次
2.第二个弊端: 可以看到,p对象的几个属性都是undefined,即stu的原型对象上会多出一些属性, 但是这些属性是没有存在的


http://chatgpt.dhexx.cn/article/lpa60DJx.shtml

相关文章

原型链与继承

目录 原型链 继承 Javascript为什么没有方法签名? 原型链继承 构造函数继承 组合继承 原型式继承 寄生继承 寄生组合继承 原型链 原型链是一种原型对象和实例对象的关系,通过属性__proto__进行联系。 继承 继承是一种允许我们在已有的类的基…

JS原型链和继承

JS原型链和继承 认识对象的原型 [[Get]]:JS的存取描述符——get方法,在获取对象属性时会自动调用 JavaScript当中每个对象都有一个特殊的内置属性[[prototype]],这个特殊的属性指向另外一个对象 [[prototype]]指向的对象: 当我…

JS原型链继承

再讲述JS原型链继承之前,我希望大家能够先理解 《函数,函数原型和函数实例之间的关系》,这样有助于大家理解JS原型链继承的原理,下面先看一张图吧,咱们看图说话: 如果大家看完了 《函数,函数原型和函数实…

原型链和继承的六种实现方式

一省:HTML 12. img标签的alt和title有什么不同? alt: 当图片加载不出来的时候,就会在图片未显示的地方出现一段 alt 设置的属性内容。浏览器的搜索引擎可以通过 alt 属性的文字描述来获取图片。 title: title是鼠…

原型,原型链,原型的继承

原型的作用? 1.节省内存空间 2.实现数据共享(继承) 什么是原型? 任何一个函数都有propotype属性,它本身是一个对象,我们称之为原型 构造函数,实例化对象与原型之间的关系? 1.任何一个函数都有prototype属性,它本身是一个对象,我们称之为原型 2.构造函数也是函数,也都…

JS原型、原型链和7种继承方法【白话文讲解】

前言 在学习JS原型、原型链和继承之前,我们必须先弄懂三个W,也就是我们常说的“学习三问” 学习三问: 1.它是什么?(What) 2. 为什么用它?(Why) 3. 什么时候用它&#xff…

原型链与常用继承方法

原型链:当访问一个对象的属性时,如果该对象内部不存在这个属性,就会去该对象的__proto__ 上(也就是它构造函数的prototype)查找 。该构造函数的prototype上也有一个自己的__proto__ 属性,然后继续向上查找,…

如何用原型链的方式实现一个 JS 继承?

大家好,我是前端西瓜哥。今天讲一道经典的原型链面试题。 原型链是什么? JavaScript 中,每当创建一个对象,都会给这个对象提供一个内置对象 [[Prototype]] 。这个对象就是原型对象,[[Prototype]] 的层层嵌套就形成了…

JS学习笔记 原型链和利用原型实现继承

原型链 原型链是一种关系,实例对象和原型对象之间的关系,关系是通过原型(__proto__)来联系的 实例对象中有__proto__,是对象,叫原型,不是标准的属性,浏览器使用,并且有的游览器不支持构造函数中有prototype属性,也是对象,叫原型 注意 原型中的方法是可…

Arduino基本知识(marlin固件配置)

初识arduino,根据mega2560(某宝可以买到)官网的100个管脚具体控制一句传输进行操作。 https://www.arduino.cc/en/Hacking/PinMapping2560 其管脚图如上所示。 首先在官网下载arduino的配套软件 https://www.arduino.cc/ 对于编程&#xf…

3D打印机硬件驱动-马林固件最新版本2.0.X中文注释(3)marlin 2.0.9.2 截至发稿时间2021年12月16日

/** * Marlin 3D Printer Firmware 头描述详见其他两个文件头描述 * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] * * Based on Sprinter and grbl. * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm * * This program is…

Marlin固件配置

文档来源自http://www.geek-workshop.com/thread-33314-1-1.html 1、基本配置基本配置是可选的,主要是给你的固件起个名字,如果你的配置很牛,让大家知道你是谁。据说这个在启动的时候会显示在显示屏中,应为我没有显示屏,所以无法验证。这个修改也很简单,通过搜索找到“S…

MKS MONSTER8 V1.0使用说明书(基于Marlin 2.0.X固件配置Voron 2.4)

广州谦辉信息科技有限公司 (基于Marlin 2.0.x 固件配置 Voron 2.4) 创客基地QQ群:489095605 232237692 邮箱:Huangkaidamakerbase.com.cn 主板购买链接:https://item.taobao.com/item.htm?spma1z10.5-c-s.w4002-23356668283.43.7eec55caLT…

ESP32烧录Marlin固件

安装platformIO 这点很简单,保证你拥有一个能够成功连接外网的环境即可。内网可能不太稳定有可能安装失败。 克隆代码 我这里采用的是fyset_e4的代码,这个代码开源在了https://github.com/FYSETC/FYSETC-E4,作者已经针对marlin固件做了一些配置。 更改…

i3型3D打印机制作详解——Marlin固件中文介绍

关注微信公众号:嵌入式基地 后台回复:3d打印机 获取资料 硬件框架搭建介绍 https://blog.csdn.net/qq_39020934/article/details/80380250 Marlin固件中文介绍 https://download.csdn.net/download/qq_39020934/10401251 …

3D打印机Marlin固件双Z轴设置

3D打印机Marlin固件双Z轴设置 在3D打印机Marlin固件的最新版本2.1.1中,设置双Z轴和老版本有一些改动。记录一下如何在最新版本的Marlin固件中设置双Z轴。 以MKS GEN_L V2.1的主板为例,硬件连接还是和原来一样,第二个Z轴的电动机连接到空闲的…

Marlin 固件配置手动退换料

换料的步骤首先把喷头加热,软化喷嘴里残余的线材,然后反转挤出机,把线材抽出来。最后装入新线材,并挤出余留在喷头里的材料。整个过程用一个命令 M600 就能完成。默认情况下 Marlin 固件并没有开启这个功能,但是可以修…

MKS_SGEN_L V1.0 marlin 固件编译

1.下载 Visual Studio Code 打开Visual Studio Code 安装插件 在应用商店搜索下载安装如下图: 安装完这些还是不行的 还要另外安装python 3.8.8 其他版本python 不行右下角会报错,提示安装python 3.8 python 3.8.8 百度网盘下载链接:https://pan.bai…

3D打印机硬件驱动-马林固件最新版本2.0.X中文注释(1)marlin 2.0.9.2 截至发稿时间2021年12月16日

马林固件最新版本翻译注释 /* Marlin Firmware 马林固件 (c) 2011-2020 MarlinFirmware Portions of Marlin are (c) by their respective authors. 马林部分程序来源于世界各地的开发者 All code complies with GPLv2 and/or GPLv3 所有源码依靠GPLv2 和 GPLv3架构编写…

Marlin固件学习总结(一)

接触过3D打印也有一段时间了,一直没有将学到的知识以文本的形式记录下来。现在也没有太多时间继续玩这个了,因此想慢慢把之前所接触到所学到的知识通过文本的形式记录一下,也分享给那些感兴趣的人。 既然是开篇我们先了解一下marlin固件的结构…