目录

  • 构造函数和原型
    • 构造函数
    • 实例成员和静态成员
    • 构造函数的问题
    • 构造函数原型 prototype
    • 对象原型 \_\_proto\_\_
    • constructor 构造函数
    • 构造函数、实例、原型对象三者之间的关系
    • 原型链
    • JavaScript 的成员查找机制(规则)
    • 原型对象的this指向
    • 扩展内置对象
  • 继承
    • call()
    • 借用构造函数继承父类型属性
    • 借用原型对象继承父类型方法
  • 类的本质
  • ES5中新增的方法
    • 数组方法
    • 字符串方法
    • Object.defineProperty方法
    • 对象方法

构造函数和原型

构造函数

构造函数是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与new一起使用。我们可以把对象中一些公共的属性和方法抽取出来,然后封装到这个函数里面。

值得注意的点:

  1. 构造函数用于创建某一类对象,其首字母要大写
  2. 构造函数要和new一起使用才有意义

new在执行时会做如下四件事情:

  1. 在内存中创建一个新的空对象
  2. 让this指向这个新的对象
  3. 执行构造函数里面的代码,给这个新对象添加属性和方法。
  4. 返回这个新对象(所以构造函数里面不需要return)

实例成员和静态成员

构造函数中的属性和方法称为成员,JavaScript的构造函数中可以添加一些成员,可以在构造函数本身上添加,也可以在构造函数内部的this上添加。通过这两种方式添加的成员,就分别称为静态成员实例成员

  • 静态成员:在构造函数本身添加的成员称为静态成员,只能由构造函数本身来访问
  • 实例成员:在构造函数内部创建的对象成员称为实例成员,只能由实例化的对象来访问

构造函数的问题

构造函数方法很好用,但是存在浪费内存的问题。

class Student{constructor(sname,sgender){this.sname = sname;this.sgender = sgender;this.sayHello = function(){console.log("你好我是"+this.sname+",我的性别是"+this.sgender);}}}
var s1 = new Student("张三","男");
var s2 = new Student("李四","女");
s1.sayHello();//你好我是张三,我的性别是男
s2.sayHello(); //你好我是李四,我的性别是女

在这里插入图片描述
上面的代码中每一个实例化对象都会对应一个内存空间但是使用的是同样的函数,存在内存浪费。
我们希望所有的对象使用同一个函数,这样就比较节省内存,那要怎么做呢。

构造函数原型 prototype

构造函数通过原型分配的函数是所有对象所共享的
JavaScript规定,每一个构造函数都有一个prototype属性,指向另一个对象。注意这个prototype就是一个对象,这个对象的所有属性和方法,都会被构造函数所拥有。

function Student(sname, sgender) {this.sname = sname;this.sgender = sgender;
}Student.prototype.sayHello = function () {console.log("你好我是" + this.sname + ",我的性别是" + this.sgender);
}var s1 = new Student("张三", "男");
var s2 = new Student("李四", "女");
s1.sayHello(); // 你好我是张三,我的性别是男
s2.sayHello(); // 你好我是李四,我的性别是女

对象原型 __proto__

对象都会有一个属性__proto__指向构造函数的prototype原型对象,之所以我们对象可以使用构造函数prototype原型对象的属性方法,就是因为对象有__proto__原型的存在。

  • __proto__对象原型和原型对象prototype是等价的
  • __proto__对象原型的意义就在于为对象的查找机制提供一个方向,或者说一条路线,但是它是一个非标准属性,因此实际开发中,不可以使用这个属性,它只是内部指向原型对象prototype
console.log(s1.__proto__ === Student.prototype); // true

在这里插入图片描述

constructor 构造函数

对象原型(__proto__)和构造函数(prototype)原型对象里面都有一个属性constructor属性,constructor我们称为构造函数,因为它指回构造函数本身。
constructor主要用于记录该对象引用于哪个构造函数,它可以让原型对象重新指向原来的构造函数。
如果我们修改了原来的原型对象,给原型对象赋值的是一个对象,则必须手动的利用construct指回原来的构造函数。

function Student(sname, sgender) {this.sname = sname;this.sgender = sgender;
}Student.prototype = {constructor: Student,// 修复构造函数指向问题sayHello: function () {console.log("你好我是" + this.sname + ",我的性别是" + this.sgender);},sayBye: function () {console.log("再见!");}
}
var s1 = new Student("张三", "男");
s1.sayHello(); // 你好我是张三,我的性别是男
s1.sayBye(); // 再见!

构造函数、实例、原型对象三者之间的关系

在这里插入图片描述

原型链

每个构造函数都有 prototype 属性,该属性指向其原型对象。原型对象的__proto__指向 Object.prototype,也就是 Object 的原型对象。Object.prototype 由 Object 构造函数创建,它是所有对象原型链的终点,其__proto__为 null,意味着原型链到此终止。

在这里插入图片描述

JavaScript 的成员查找机制(规则)

  1. 当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性
  2. 如果没有就查找它的原型(也就是__proto__指向的prototype原型对象
  3. 如果还没有就查找原型对象的原型(Object的原型对象
  4. 以此类推一直找到Object为止(null
  5. __proto__对象原型的意义就是在于为对象成员查找机制提供一个方向或者说一条路线

原型对象的this指向

通过如下的代码可以得出结论:无论是构造函数中的this还是原型对象函数中的this指向的都是对象实例

function Student(sname, sgender) {this.sname = sname;this.sgender = sgender;
}var that;
Student.prototype.sayHello = function () {console.log("你好我是" + this.sname + ",我的性别是" + this.sgender);that = this;
}
var s1 = new Student("张三", "男");
// 在构造函数中,里面this指向的是对象实例s1
s1.sayHello(); // 你好我是张三,我的性别是男
console.log(that === s1); //true
// 原型对象函数里面的this指向的是对象实例s1

扩展内置对象

可以通过原型对象,对原来的内置对象进行扩展自定义的方法。比如给数组增加自定义求和的功能。
注意:数组和字符串内置对象不能给原型对象覆盖操作Array.prototype={},只能是Array.prototype.xxx=function(){}的方式。

Array.prototype.sum = function () {var sum = 0;for (var i = 0; i < this.length; i++) {sum += this[i];}return sum;
}
var arr = [1, 2, 3, 4, 5];
console.log(arr.sum()); // 15
var arr1 = new Array(1, 2, 3, 4, 5);
console.log(arr1.sum()); // 15

继承

ES6之前并没有给我们提供extends继承。我们可以通过构造函数+原型对象模拟实现继承,被称为组合继承

call()

调用这个函数,并修改函数运行时this指向

fun.call(thisArg,arg1,arg2,...)
  • thisArg:当前调用函数this的指向对象
  • arg1,arg2:传递的其他参数
function fn() {console.log("hello world");console.log(this);
}
var obj = {name: "obj"
};
// 1.call() 可以调用函数
fn.call(); // window{...}
// 2.call() 可以改变函数的this指向
fn.call(obj); // obj{name: "obj"}

借用构造函数继承父类型属性

核心原理:通过call()把父类型的this指向子类型的this,这样就可以实现子类型继承父类型的属性。

//借用父构造函数继承属性
//1.父构造函数
function Parent(name, age) {//this指向父构造函数的实例对象this.name = name;this.age = age;
}
//2.子构造函数
function Child(name, age) {//this指向子构造函数的实例对象Parent.call(this, name, age); //借用父构造函数继承属性// Parent.apply(this, arguments); //借用父构造函数继承属性,使用apply可以传入任意数量的参数
}
//3.创建子构造函数的实例对象
var child = new Child('小明', 18);
console.log(child.name); //小明
console.log(child.age); //18

借用原型对象继承父类型方法

//1.父构造函数
function Parent(name, age) {this.name = name;this.age = age;
}
Parent.prototype.money = function () {console.log(100000);
}//2.子构造函数
function Child(name, age) {Parent.call(this, name, age); //借用父构造函数继承属性
}
// Child.prototype = Parent.prototype; //这样直接赋值会有问题,如果修改了子原型对象,如果修改了子原型对象,父原型对象也会被修改
Child.prototype = new Parent(); //借用父构造函数的原型对象
//如果利用对象的形式修改了原型对象,别忘了利用constructor指回原来的构造函数
Child.prototype.constructor = Child;
//3.创建子构造函数的实例对象
var child = new Child('小明', 18);
console.log(child.name); //小明
console.log(child.age); //18
child.money(); //100000

类的本质

  1. class本质还是function
  2. 类的所有方法都定义在类的prototype属性上
  3. 类创建的实例,里面也有__proto__指向类的prototype原型对象
  4. 所以ES6的类它的绝大部分功能,ES5都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已
  5. 所以ES6的类其实就是语法糖
class Student{}
//1. 类的本质其实还是一个函数 我们也可以简单的认为类就是构造函数的另外一种写法
console.log(typeof Student);// "function"
//(1).类有原型对象prototype
console.log(Student.prototype);// {constructor: ƒ}
//(2).类原型对象prototype里面有constructor指向类本身
console.log(Student.prototype.constructor);// ƒ Student() { [native code] }
//(3).类可以通过原型对象添加方法
Student.prototype.sayHello = function(){console.log("Hello, I am a student.");
}
var s = new Student();
console.dir(s);
//(4)构造函数创建的实例对象有__proto__属性指向类原型对象prototype
console.log(s.__proto__ === Student.prototype);

ES5中新增的方法

ES5中给我们新增了一些方法,可以很方便的操作数组或者字符串

数组方法

迭代(遍历)方法:forEach()、map()、filter()、some()、every()

  1. forEach()方法

    • 用于遍历数组中的每个元素
    • 不会改变原数组
    • 默认三个回调参数为value、index、array
    • 示例:[1,2,3].forEach(function(value){console.log(value)})
  2. map()方法

    • 对数组中的每个元素执行回调函数
    • 返回一个新数组
    • 示例:[1,2,3].map(function(value){return value*2})返回[2,4,6]
  3. filter()方法

    • 筛选数组中符合条件的元素
    • 返回一个新数组
    • 示例:[1,2,3].filter(function(value){return value>1})返回[2,3]
  4. some()方法

    • 检测数组中是否有元素满足条件
    • 返回布尔值
    • 示例:[1,2,3].some(function(value){return value>2})返回true
  5. every()方法

    • 检测数组中的所有元素是否都满足条件
    • 返回布尔值
    • 示例:[1,2,3].every(function(value){return value>0})返回true

字符串方法

trim()方法
从一个字符串的两端删除空白字符

Object.defineProperty方法

Object.defineProperty(obj, prop ,descriptor)
  • obj:必需,目标对象
  • prop:必需,需定义或修改的属性的名字
  • descriptor:必需,目标属性所拥有的特性
    第三个参数descriptor说明:以对象形式{ }书写
  • value:设置属性的值,默认为undefined
  • weitable:值是否可以重写。true|false 默认为false
  • enumerable:目标属性是否可以被枚举 true|false 默认为false
  • configurable:目标属性是否可以被删除或是否可以再次修改特性 true|false 默认为false
var obj = {name: 'zhangsan',age: 20 
};Object.defineProperty(obj, 'gender', {value: 'male',writable: true,enumerable: true,configurable: true
});console.log(obj); // {name: "zhangsan", age: 20, gender: "male"}

对象方法

  1. Object.keys()用于获取对象自身所有的属性
object.keys(obj)
  • 效果类似for…in
  • 返回一个由属性名组成的数组

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

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

相关文章

项目进度与预算脱节,如何进行同步管理

项目进度与预算脱节会导致资源浪费、成本超支和项目延期。进行同步管理的方法包括&#xff1a;建立统一的项目进度预算管理体系、实施实时监控与反馈机制、采用项目管理工具辅助同步管理。尤其是实施实时监控与反馈机制&#xff0c;通过持续监测进度与预算的匹配情况&#xff0…

TCP半关闭

理解TCP半关闭&#xff1a;像水管一样的网络连接控制 从全关闭到半关闭&#xff1a;为什么需要这种机制&#xff1f; 想象你和朋友正在通电话讨论一个重要项目&#xff1a; 全关闭&#xff1a;就像突然挂断电话&#xff0c;双方都无法再说话半关闭&#xff1a;你说"我说完…

衡石科技技术手册--仪表盘过滤控件详解

过滤控件说明 过滤控件 的定义 过滤控件用于在仪表盘中过滤图表数据&#xff0c;分为仪表盘内过滤控件和全局过滤控件。 过滤控件结构说明 字段类型描述uidSTRING过滤控件唯一识别 idappIdLONG过滤控件所属的应用 iddataAppIdLONG字段来源是数据包时的数据包 iddashboar…

ASP.NET Core中数据绑定原理实现详解

在ASP.NET Core 中&#xff0c;数据绑定是将 HTTP 请求中的数据&#xff08;如表单、查询字符串、请求体等&#xff09;映射到控制器动作方法参数或模型对象的过程。以下将从原理、核心组件、执行流程及关键机制等方面详细解析其实现逻辑。 一、数据绑定的核心原理与组件 1. 数…

牛客:HJ24 合唱队[华为机考][最长递增子集][动态规划]

学习要点 求最长递增字列求最长递减子列 题目链接 合唱队_牛客题霸_牛客网 题目描述 解法&#xff1a;动归求最长递增子列 #include <iostream> #include <vector> using namespace std;int main() {int n;while (cin >> n) {// 输入的数组int tmp;vect…

C语言的相关基础概念和常用基本数据类型

1.相关概念变量与常量的定义常量&#xff1a;在程序运行中其值不能改变的量。变量&#xff1a;在程序运行中其值可以改变的量。存储器的区分 RAMROM中文名易失存储器不易失存储器特点掉电丢失数据&#xff0c;但存取快掉电不丢失数据&#xff0c;但存取幔标识符标识符只能…

Spring boot整合dubbo+zookeeper

Spring boot整合dubbozookeeper 下文将简述springboot整合dubbozookeeper实现apiproviderconsumer模式&#xff0c;Api用于定于interface,provider和consumer依赖Api,provider实现api接口&#xff0c;consumer调用provider。 spring boot版本&#xff1a;3.5.3 jdk版本&#xf…

ImportError: /lib/x86_64-linux-gnu/libc.so.6: version GLIBC_2.32‘ not found

简介&#xff1a;在复现 VLM-R1 项目并尝试将其中的 GRPO 算法应用到自己的任务时&#xff0c;按照官方文档配置好环境后&#xff0c;运行过程中遇到了一个非常离谱的错误&#xff1a; ImportError: /lib/x86_64-linux-gnu/libc.so.6: version GLIBC_2.32 not found 这个问题极…

基于Spring Boot的生活用品电商网站的设计与实现

第1章 摘要随着电商行业的飞速发展&#xff0c;生活用品电商网站作为线上购物的一部分&#xff0c;逐渐成为消费者日常购物的重要渠道。为提升网站的管理效率和用户体验&#xff0c;设计并实现了一款基于Spring Boot的生活用品电商网站。该系统通过合理的架构设计&#xff0c;提…

数据结构 单链表(1)

1.概念和结构概念&#xff1a;链表是一种物理存储结构上非连续、非顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接次序实现的。通过指针链接次序实现的要怎么理解呢?这是一张链表的结构图:与顺序表不同的是&#xff0c;链表里的每节“车厢” (仔细观察这…

Python爬虫实战:研究PyMongo库相关技术

1. 引言 在当今信息爆炸的时代,互联网上存在着海量的有价值数据。如何高效地获取这些数据并进行存储和分析,成为了数据科学领域的重要研究方向。网络爬虫作为一种自动化的数据采集工具,可以帮助我们从网页中提取所需的信息。而 MongoDB 作为一种流行的 NoSQL 数据库,能够灵…

【世纪龙科技】迈腾B8汽车整车检测与诊断仿真实训系统

在汽车技术日新月异的今天&#xff0c;如何培养既懂理论又精实践的高素质汽修人才&#xff0c;成为职业教育领域亟待突破的课题。江苏世纪龙科技凭借深厚的技术积淀与教育洞察&#xff0c;重磅推出《汽车整车检测与诊断仿真实训系统》&#xff0c;以迈腾B8为原型&#xff0c;通…

.net服务器Kestrel配置Nginx作为反向代理

.NET服务器Kestrel配置Nginx作为反向代理 在ASP.NET Core应用程序的部署过程中&#xff0c;Kestrel是一款轻量级的跨平台Web服务器。不过&#xff0c;直接将其暴露在互联网上并非明智之举。为了增强安全性、提升性能以及提高可伸缩性&#xff0c;我们可以借助Nginx作为反向代理…

MyBatis 在执行 SQL 时找不到名为 name 的参数

MyBatis 在执行 SQL 时找不到名为 name 的参数&#xff0c;因为当接口方法有多个参数时&#xff0c;没有使用 Param(“name”) 明确指定参数名。 其他人说只有springboot1.x的版本才会出现该问题&#xff0c;但是我在使用2.x的版本时也出现了该问题Not found 参数 于是便回根溯…

【Git】git的回退功能

Git 的回退功能非常强大&#xff0c;但因为有多个命令&#xff0c;初学者很容易混淆。我们来系统地梳理一下最核心的几个“回退”指令&#xff1a;git reset、git revert 和 git restore。 我会按照使用场景和安全级别来为你讲解。核心区别&#xff1a;reset vs revert 这是最重…

STM32新建工程

1、新建工程 Keil5中&#xff0c;新建Project&#xff0c;选择STM32Project文件夹&#xff0c;在此文件夹下新建一个文件夹“STM32工程模板”&#xff0c;然后给工程文件起名字“Project”选择器件型号 2、添加启动文件 新建start文件夹复制启动文件&#xff1a;固件库文件夹……

网络传输过程

https传输过程客户端发起HTTPS请求操作&#xff1a;用户在浏览器输入 https://www.example.com 技术细节&#xff1a; 客户端向服务器443端口发起TCP连接 发送Client Hello消息&#xff08;包含支持的TLS版本、加密套件、客户端随机数&#xff09; 安全意义&#xff1a;建立安全…

【LeetCode 3440. 重新安排会议得到最多空余时间 II】解析

目录LeetCode中国站原文原始题目题目描述示例1&#xff1a;示例2&#xff1a;示例3&#xff1a;示例4&#xff1a;讲解1. 新规则&#xff0c;新挑战2. 收益从何而来&#xff1f;两种可能性的诞生3. 我们的终极策略4. 当策略被压缩到极致第一次遍历&#xff1a;从左到右&#xf…

C++卸载了会影响电脑正常使用吗?解析C++运行库的作用与卸载后果

卸载C运行库可能导致常用软件瘫痪&#xff01;这些不起眼的组件为Photoshop、游戏等提供关键支持&#xff0c;多个版本共存是正常现象&#xff0c;随意清理会引发程序报错甚至闪退。一、前言&#xff1a;C不是“编程语言”那么简单很多用户在电脑中看到“Microsoft Visual C Re…

前端vue对接海康摄像头流程

1、拆包摄像头、插电源2、下载SADP&#xff08;设备网络搜索&#xff09;&#xff0c;连接设备&#xff0c;获取ip地址 下载地址&#xff1a;https://partners.hikvision.com/tools 找到自己的设备类型DS开头3、摄像头链接wifi、网线 登录设备预览配置网页-配置网络-可预览等 4…