JS面向对象的三大特性简述

article/2025/1/19 3:17:25

1.语法

1.1 对象的声明语法

1.1.1通过字面量方式新建对象

    var obj = {}var obj1 = {name: 'hhupp',call: function() {console.log('CALL')}}console.log('obj', obj)console.log('obj1', obj1)obj1.call()

 1.1.2通过new关键词新建对象(不推荐--和通过字面量方式新建对象并无差别--且使用esLint会有eslint(no-new-object)提示报错)

    var obj = new Object()console.log('obj',obj)var obj1 = new Object()obj1.name = 'hhupp'obj1.call = function (){console.log('CALL');}console.log(obj1)obj1.call()

1.1.3 通过构造函数新建对象

    function mySelfObject (name,method) { // 自己编写的构造函数this.name = namethis.method = method}//  实例化1var obj = new mySelfObject()console.log('obj',obj)//  实例化2var obj1 = new mySelfObject('hhupp',function (){console.log('CALL')})console.log('obj1',obj1)obj1.method()

2.特性

 面向对象的三大特性:封装、继承、多态。

2.1 封装

        我们举个例子,有两只小狗A和B这两只狗都属于“狗”这个种族,但是它们是相对独立的,A和B拥有自己的名字,品种,年龄,会跑,会叫等等,一只狗就是一个单位,一个整体,然后才会有A和B之间的关系。我们平时所用的方法和类都是一种封装,当我们在项目开发中,遇到一段功能的代码在好多地方重复使用的时候,我们可以 把他单独封装成一个功能的方法,这样在我们需要使用的地方直接调用就可以了。

优点:封装的优势在于定义只可以在类内部进行对属性的操作,外部无法对这些属性指手画脚,要想修改,也只能通过你定义的封装方法;

2.2.1 工厂模式封装

工厂模式的原理:在方法内部创建一个object对象,对象的属性由参数指定,方法直接挂载在对象上,最后返回这个对象。相当于Dog方法是一个造狗工厂,创造了A和B两只狗,

function Dog(name, age, color) {var dog = new Object()dog.name = namedog.age = agedog.color = colorreturn dog
}
var dogA = Dog('A', '1', '白色')
var dogB = Dog('B', '5', '黑色')
console.log('小狗A的属性 == ', dogA)
console.log('小狗B的属性 --> ', dogB)

缺点: 无法知道对象的具体的类型

2.2.2 构造函数模式封装

构造函数模式可以知道小狗A和小狗B这两只狗是Dog类型,原理是new关键字进行了以下的操作。

1. 创建一个全新的对象

2.这个对象会被执行[[prototype]]连接原型

3.方法调用中的this会绑定到新的对象

4.如果构造函数里没有返回其他对象,那么new构造会自动返回这个新的对象

function Dog(name, age, color) {this.name = namethis.age = agethis.color = color
}
var dogA = new Dog('A', '1', '白色')
var dogB = new Dog('B', '5', '黑色')
console.log('小狗A的属性 == ', dogA)
console.log('小狗B的属性 --> ', dogB)

上述的原型链图示如下: 

 

2.2 继承

        继承可以解决代码复用的问题,让代码更加接近人类的思维。当多个类存在相同的属性和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,子类只需要通过继承,就可以拥有父类中的属性和方法,不需要重新进行定义。

2.2.1 通过原型链实现继承

让一个构造函数的原型是另一个类型的实例,那么这个构造函数new出来的实例就具有该实例的属性。

当我们试图访问一个对象的属性时,优先从对象本身查找,若未找到,则沿着该对象的原型链逐级往上查找,直到查询到对应的属性或者达到原型链的末尾。

   // 父类的构造函数function Parent() {this.flag = falsethis.info = {name: 'hhupp',age: '18'}}Parent.prototype.getInfo = function() {console.log('flag', this.flag)console.log('info', this.info)}// 子类的构造函数function Children() {};// 将子类的原型指向父类的实例Children.prototype = new Parent()// 实例化一个子类1var children1 = new Children()children1.info.name = 'children1'// 实例化一个子类2var children2 = new Children()children2.flag = truechildren2.sex = '女'children2.info.name = 'children2'children1.getInfo() // 获取children1的数据children2.getInfo() // 获取children2的数据

 

优点:代码方便简洁,便于理解

缺点:对象实例共享所有继承的属性和方法,创建子类型实例时不能传递参数,因为这个对象是一次性创建的(无法进行定制化操作)

2.2.2 借用构造函数继承

        在子类型的构造函数中调用父类型的构造函数,通过apply()或者call()将父类的构造函数绑定在子对象上

    // 父类的构造函数function Parent(sex) {this.info = {name: 'hhupp',age: '18',sex: sex}}// 子类的构造函数function Children(sex) {Parent.call(this, sex)};var children1 = new Children('男')children1.info.name = 'children1'var children2 = new Children('女')children2.info.name = 'children2'console.log(children1)console.log(children2)

 

 优点:解决了原型链实现继承不能传参的问题和父类原型共享的问题。

 缺点:借用构造函数实现继承的缺点是方法都在构造函数中定义,无法实现函数复用。在父类型的原型中定义的方法对子类型来说都是不可见的,导致所有类型只能使用构造函数的模式。

2.2.3 组合继承 (经典继承)

将原型链和借用构造函数的方式组合到一块,使用原型链实现对原型属性和方法的继承,通过借用构造函数来实现对实例属性的继承,这样既通过再原型上定义方法实现了函数复用,又能保证每个实例都有自己的属性。

     // 父类的构造函数function Parent(sex) {console.log('执行父类构造函数' + sex)this.info = {name: 'hhupp',age: '18',sex: sex}}Parent.prototype.getStaffInfo = function() {console.log(this.info.name, this.info.sex)}// 子类的构造函数function Children(sex) {Parent.call(this, sex)};Children.prototype = new Parent()var children1 = new Children('男')children1.info.name = 'children1'var children2 = new Children('女')children2.info.name = 'children2'children1.getStaffInfo()console.log(children1)children2.getStaffInfo()console.log(children2)

 

 

 优点:解决了原型链继承和借用构造函数继承造成的影响

 缺点:无论在什么情况下,都会调用两次超类型构造函数:一次是在创建子类型原型的时候,另一次是在子类型构造函数的内部。

2.2.4 原型式继承

方法一:借用构造函数在一个函数A内部创建一个临时的构造函数,将传入的对象作为这个构造函数的原型,返回这个临时类型的一个新实例。 函数A本质上是对传入的对象进行了一次浅拷贝。

    function createObject(obj) {function Fun() {}Fun.prototype = objreturn new Fun()}let person = {name: 'HHUPP',age: 18,hoby: ['唱', '跳'],showHoby() {console.log('my hoby is:', this.hoby)}}let child1 = createObject(person)child1.name = 'LSY'child1.hoby.push('rap')let child2 = createObject(person)child2.name = 'ZQJ'child2.hoby.push('篮球')console.log(child1)console.log(child2)console.log(person)

 方法二:Object.create()

Object.create ()是吧现有对象的属性,挂到新建对象的原型上, 新建对象为空对象ES5通过增加Object.create()方法将原型式继承的概念规范化了,这个方法接收两个参数,作为新对象原型的对象,以及给新对象定义额外属性的对象(可选),在只有一个参数时,Object.create()与上述的方法A效果相同。

    let person = {name: 'HHUPP',age: 18,hoby: ['唱', '跳'],showHoby() {console.log('my hoby is:', this.hoby)}}let child1 = Object.create(person)child1.name = 'LSY'child1.hoby.push('rap')let child2 = Object.create(person)child2.name = 'ZQJ'child2.hoby.push('篮球')console.log(child1)console.log(child2)console.log(person)

 2.2.5 ES6 Class实现继承

原理和ES5的继承一样,实质上是先创造子类的实例对象this,然后将父类的方法添加到this上。ES6的继承机制完全不同,实质是先将父类实例对象的属性和方法,加到this上面(所以必须先调用super方法),然后再用子类的构造函数修改this

优点: 语法简单易懂,操作方便。

 缺点:存在浏览器不支持ES6语法。

2.3 多态

js的多态:

        子类对父类的方法进行重写,调用这个方法时,会默认执行子类的方法,即实现多态。不同子类这行父类的同名方法会有不同的结果,除了子类重写父类的方法外,还有函数参数个数,和参数类型的多态。

    function Person() {Person.prototype.initfun = function() {this.init()}}function Sun1 () {this.init = function() {console.log('1')}}function Sun2() {this.init = function() {console.log('2')}}Sun1.prototype = new Person()Sun2.prototype = new Person()new Sun1().initfun() // Sun1的init方法 // 1new Sun2().initfun() // Sun2的init方法 // 2

 参数个数不同, 执行不同的代码

利用arguments.length判断来实现

    function fun() {if (arguments.length === 0) {console.log('参数为0')} else if (arguments.length === 1) {console.log('一个参数', arguments[0])} else if (arguments.length === 2) {console.log('两个参数', arguments[0], arguments[1])}}fun()fun(1)fun(1, 2)

 参数类型不同的多态

利用typeof判断argument的类型进行判断

function fun2() {if (typeof arguments[0] === 'object' && typeof arguments[1] === 'string') {console.log('类型1')}else {console.log('类型2')}}
fun2({a: 1}, 's')
fun2({a: 1}, 1)

 


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

相关文章

一个小实验告诉你,内存速度到底比硬盘快多少!!!

近期在Linux下做了一个小实验,亲身体会了内存的速度到底比硬盘快多少。 实验步骤如下: 1. df #查看磁盘信息 2. dd if/dev/zero of /dev/shm/file bs1M count3000 3. dd if/dev/zero of/mnt/file bs1M count3000由此可见,内存的读取速…

硬盘和内存的速度

1. 简介 随着电子技术的发展,内存和硬盘的速度都在提高,但同时,旧技术因为应用场景依然存在,速度上有个大致的理解上有必要的。 2. 内存的速度 3. 存储介质的速度 操作平台 读 写 NVME PCIE SSD(gen3 4x) 2.1 GB/s 1.2 GB/s…

CPU、寄存器、内存、磁盘、网络性能分析

介绍 寄存器 最靠近 CPU 的控制单元和逻辑计算单元的存储器,就是寄存器了,它使用的材料速度也是最快的,因此价格也是最贵的,那么数量不能很多。 存储器的数量通常在几十到几百之间,每个寄存器可以用来存储一定的字节…

《手机网速、CPU、内存和闪存》的速度制衡之道

一、手机网速、CPU、内存与闪存的速度制衡之道: 手机响应速度的快慢很大程度上是多方面因素共同作用的结果,例如高性能的处理器、快速的内存和闪存标准、良好的网络链接性能、优化完善的操作系统等等,这就是Iphone手机的流畅体验要远远好于大…

类比 -高速缓存Cache/内存/磁盘读写速度类比

1、计算机设备、组件数据传输速度类比 计算机设备、组件读类比机械硬盘0.1G/S蜗牛量级(60m/h) , 以机械盘为基准固态盘1.3G/S龟速量级(780m/h),13倍机械硬盘内存30G/S跑步量级(23.4km/h&#x…

内存的速度和CPU缓存速度比较

转载于:https://blog.csdn.net/moyeshuier/article/details/103943355 这之前,我必须先讲一下cpu cache 内存三个组件在运行程序时候的关联,有了这个基础我后面才能讲锁。 那今天讲的是缓存一致性,首先要理解我说的缓存是什么意思…

计算机内存加速,电脑内存运行速度如何提升

电脑内存运行速度如何提升是一个经常提到的话题,需要了解一些基本的电脑知识来处理,下面学习啦小编介绍内存升级提高电脑运行速度的办法。 电脑内存运行速度提升方法 1.调整高速缓存区域的大小。所谓高速缓存,是指系统在读取磁盘、光盘上的数据时,采取“预读取”技术,也 就…

GPU 内存结构

GPU 和CPU通过 VLink 或者PCLe 相连。 每个SM 又含有多个cuda core,多个SM共享全局内存,通过L2 高速缓存和全局内存进行相连,不同代的GPU之间的体系结构有所不同。 右边是一个SM 上的 内存,有共享内存,局部内存&…

计算机专业电脑内存,电脑内存大小是否和速度有关?

我们总觉得内存大一点,就是运行速度一定是快。现在市面上的电脑,配置已经很强大了,动不动内存就上12G、16G的笔记本、一体机电脑随处可见。电脑已经到了瓶颈且性能过剩的年代,其实内存越大就代表电脑速度越快,这里有些误区,今天就让小编跟大家说说内存这点事儿。 计算机运…

linux怎么看内存时序,内存速度和时序重要么

描述 最近是跟内存耗上了,其一是手里没有其它硬件可测,更重要的是想趁着这段时间,把内存与性能之间的影响都慢慢测一下。今天测的就是时序与内存性能之间的关系了。时序很重要吗?答案是肯定的,但是时序对内存性能的影响到底有多大呢?下面就详细的测试一下。 用来测试的内…

手机测试内存速度的软件,如何查看手机内存速度?手机内存读取速度测试_手机内存速度多少算正常...

如何查看手机内存速度?手机内存速度多少算正常?下面小编就给大家介绍下手机内存读取速度测试发方法! 今早,手机内存问题再度引起热潮,很多朋友都在讨论手机内存速度问题。那么问题来了,如何正确测试自己手机…

双倍数据率同步動態隨機存取記憶體(英語:,簡稱DDR SDRAM)

双倍数据率同步動態隨機存取記憶體(英語:,簡稱DDR SDRAM)為具有雙倍資料傳輸率的SDRAM,其資料傳輸速度為系統時脈的兩倍,由於速度增加,其傳輸效能優於傳統的SDRAM。 DDR SDRAM 研發商SamsungJED…

古风排版java_古风排版java版-Go语言中文社区

7-7 古风排版(20 分) 中国的古人写文字&#xff0c;是从右向左竖向排版的。本题就请你编写程序&#xff0c;把一段文字按古风排版。 输入格式&#xff1a; 输入在第一行给出一个正整数N(<100)&#xff0c;是每一列的字符数。第二行给出一个长度不超过1000的非空字符串&#…

古风排版问题

7-7 古风排版 中国的古人写文字&#xff0c;是从右向左竖向排版的。本题就请你编写程序&#xff0c;把一段文字按古风排版。 输入格式&#xff1a; 输入在第一行给出一个正整数N&#xff08;<100&#xff09;&#xff0c;是每一列的字符数。第二行给出一个长度不超过1000…

古风排版 (

中国的古人写文字&#xff0c;是从右向左竖向排版的。本题就请你编写程序&#xff0c;把一段文字按古风排版。 输入格式 输入在第一行给出一个正整数 NN&#xff0c;是每一列的字符数。第二行给出一个长度不超过 10001000 的非空字符串&#xff0c;以回车结束。 输出格式 按…

开源中文古风排版样式,简约美观,超级好用!

只推荐用过的好用工具&#xff0c;关注DD帮你提高效率 如果有一篇古诗&#xff0c;要放在Web页面上&#xff0c;你会如何排版呢&#xff1f;如果要实现类似语文书中的那种效果&#xff0c;有没有办法快速实现呢&#xff1f; 今天给大家推荐一个非常好用的开源项目&#xff0c;就…

微分和导数的关系是什么?

在初学微分和导数时&#xff0c;虽然感觉概念不复杂&#xff0c;但是我对两者的关系有点模糊&#xff0c;比如以下问题就觉得模棱两可&#xff1a; 对于导数链式法则&#xff0c; d y d x d y d u d u d x \frac {dy}{dx} \frac {dy}{du} \frac {du}{dx} dxdy​dudy​dxdu​…

重新认识微分和导数

之前写过不少关于微分和导数的文章&#xff1a; 微分是什么&#xff1f; dx&#xff0c;dy是什么&#xff1f; 微分和导数的关系是什么&#xff1f; 今天这篇文章再换一个角度来谈论微分和导数&#xff0c;让我们从微分出现的原因说起。 1 微分出现的原因 出于种种原因…

第七章——微分方程

目录 一、求常系数线性齐次微分方程的通解 二、可分离变量的一阶微分方程 三、齐次方程 四、一阶线性微分方程 五、 可降解的高阶微分方程 六、常系数非齐次线性微分方程的特解形式 注&#xff1a;//之后的都是注释&#xff0c;不是过程。 一、求常系数线性齐次微分方程…