JavaScript面向对象详解(一)

一. JavaScript的对象

传统的面向对象
面向对象语言的一个标志就是类类是所有对象的统称, 是更高意义上的一种抽象. 对象是类的实例.通过类我们可以创建任意多个具体的对象.

在学习C++/OC/Java/Python等编程语言的时候, 都可以按照这种方式去创建类和对象.JavaScript的面向对象JavaScript中没有类的概念(ES6之前),

因此我们通常称为基于对象,而不是面向对象.虽然JavaScript中的基于对象也可以实现类似于类的封装、继承、甚至是多态。
但是和传统意义的面向对象还是稍微有一些差异(后面我们会讲解它是如何实现的)ECMA中定义对象是这样: 无序属性的集合, 属性可以包含基本值, 对象或者函数.

也就是对象是一组没有顺序的值组成的集合而已.对象的每个属性或者方法都有一个名字, 而名字对应一个值. 有没有觉得非常熟悉?

没错, 其实就是我们经常看到和使用的映射(或者有些语言称为字典, 通常会使用哈希表来实现).

1.2. 简单的方式创建对象

创建自定义对象最简单的方式就是创建一个Object实例, 然后添加属性和方法

// 1.创建person的对象
var person = new Object()
// 2.给person对象赋值了一些动态的属性和方法person.name = "wulin"
person.age = 21
person.height = 1.8
person.sayHello = function () {    alert("Hello, My name is " + this.name)
}
// 3.调用方法, 查看结果person.sayHello()

代码解析:

步骤一: 创建一个名为person的对象.
步骤二: 给对象动态的赋值了一些属性包括一个方法
步骤三: 调用sayHello()方法, 主要看一下this.name会获取到谁呢?
wulin

插播一个信息: 函数和方法的关系

很多人在学习编程的时候, 会分不清楚什么是函数, 什么又是方法. 或者在什么情景下称为函数, 什么情景下称为方法.

首先, 如果你看的是英文文档, 会有明显的区分: Function被称为函数, Method被称为方法.
但是英文中, 为什么需要有这两个称呼呢?

在早期的编程语言中, 只有函数(类似于数学中函数的称呼)

后来有了面向对象语言, 面向对象语言中, 类中也可以定义函数. 但是人们为了区分在类中定义的函数, 通常称类中的函数为方法.

还有一个非常重要的原因是, 通常方法中会携带一个调用者的当前对象(会将调用者作为参数一起传递进去), 也就是说this(有些语言中是self. 比如OC/Swift/Python等)
当然, 你从这个角度来说, JavaScript中就没有函数了, 因为函数中都有this这样的参数. 但是通常来说, 我们还是会将封装到类中的函数称为方法, 而全局定义的函数称为函数.

如果接触过Java的同学可能会知道Java中只有方法的程序, 没有函数的称呼.

学习过C语言的同学可能知道, C语言中只有函数的称呼, 没有方法的称呼.
这就是因为Java中通常不定义全局函数, 但是在类中定义的. 而C语言不支持面向对象的编程.

对象字面量称为创建这种对象的首选方式

// 1.创建对象的字面量
var person = {    name: "wulin",   age: 21,   height: 1.8,   sayHello: function () {        alert("My name is " + this.name)    }}
// 2.调用对象的方法person.sayHello()

1.3. JavaScript中属性的特性

根据特性的不同,可以把属性分成两种类型:数据属性和访问器属性。

[[Configurable]] // true or false

表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。
像前面例子中那样直接在对象上定义的属性,它们的这个特性默认值为true。

[[Writable]] // true or false

表示能否修改属性的值。像前面例子中那样直接在对象上定义的属性,它们的这个特性默认值为true。

[[Enumerable]] // true or false表示能否通过for-in循环返回属性。像前面例子中那样直接在对象上定义的属性,它们的这个特性默认值为true。

[[Value]] // everty thing包含这个属性的数据值。读取属性值的时候,从这个位置读;写入属性值的时候,把新值保存在这个位置。这个特性的默认值为undefined。

[[set]] // function or undefined在写入属性时调用的函数。默认值为undefined。

[[get]] // function or undefined在读取属性时调用的函数。默认值为undefined。这些属性特性是什么东西呢?

从上面, 我们对这些特定的解释, 你会发现, 每个特定都会有自己特定的用途.
比如Configurable当我们配置为false时, 就无法使用delete来删除该属性.

设置属性特定obj: 将要被添加属性或修改属性的对象prop: 对象的属性descriptor: 对象属性的特性要想修改属性的特性,必须通过两个Object方法,

即Object.defineProperty和Object.defineProperties正如其字面意思,这两个方法都是用来定义(修改)属性的,前者一次只能定义一个属性,后者则可以多个。

var person = {}
Object.defineProperty(person, "birth", {    writable: false,    
value: 2000}
)
alert(person.birth) // 2000
person.birth = 1999alert(person.birth) // 2000

数据属性:

数据属性包含一个数值的位置,在这个位置可以读取和写入值。
数据属性拥有4个特性: [[Configurable]]/[[Enumerable]]/[[Writable]]/[[Value]]

按照上面的方式, 我们定义的属性就是数据属性
访问器属性:

访问器属性不包含数据值,它们包含一对getter和setter函数。
访问器属性不能直接定义,需要使用后面提到的Object.defineProperty函数定义。
访问器属性也拥有4个特性:

[[Configurable]]/[[Enumerable]]/[[Get]]/[[Set]]
定义一个访问器属性:

二. JavaScript创建对象

2.1. 使用工厂模式

工厂模式是一种非常常见的设计模式, 这种模式抽象了创建具体对象的过程.因为JavaScript中没法创建类, 开发人员就发明了一种函数, 用函数来封装以特定接口创建对象的细节.
下面展示一些 内联代码片

// 创建工厂函数
function createPerson(name, age, height) {    var o = new Object()    
o.name = name    
o.age = age   o.height = height    o.sayHello = function () {        alert("Hello, My name is " + this.name)    }    return o}// 创建两个对象var person1 = createPerson("wulin", 21, 1.8)var person2 = createPerson("wulin2",21, 1.8)person1.sayHello() // Hello, My name is wulinperson2.sayHello() // Hello, My name is wulin2

2.2. 构造函数模式

JavaScript中的构造函数可用来创建特定类型的对象。

像Object和Array这样的原生构造函数,在运行时会自动出现在执行环境中。
此外,也可以创建自定义的构造函数,从而定义自定义对象类型的属性和方法。
使用构造函数模式创建对象:

// 构造函数
function Person(name, age, height) {    this.name = name    
this.age = age    
this.height = height    
this.sayHello = function () {        alert(this.name)    }}
// 使用构造函数创建对象
var person1 = new Person("wulin", 21, 1.8)
var person2 = new Person("wulin2", 21, 1.8)
person1.sayHello() 
// wulinperson2.sayHello() 
// wulin2

在这个例子中,Person()函数取代了createPerson()函数。

我们会发现这个函数有一些不太一样的地方:

没有显式地创建对象;(比如创建一个Object对象)
直接将属性和方法赋给了this对象;
没有return语句
另外, 我们还注意到函数名Person使用的是大写字母P。

按照惯例,构造函数始终都应该以一个大写字母开头,而非构造函数则应该以一个小写字母开头;
这个做法借鉴自其他面向对象语言,主要是为了区别于ECMAScript中的其他函数;
因为构造函数本身也是函数,只不过可以用来创建对象而已;
还有, 我们在调用函数时, 不再只是简单的函数+(), 而是使用了new关键字

这种方式调用构造函数实际上会经历以下4个步骤:

创建一个新对象, 这个新的对象类型其实就是Person类型.
将构造函数的作用域赋给新对象(因此this就指向了这个新对象,也就是this绑定);
执行构造函数中的代码(为这个新对象添加属性和方法);
返回新对象, 但是是默认返回的, 不需要使用return语句;

我们也可以通过instanceof来查看它的类型
注意: 我们会发现person1和person2既是Person类型, 也是Object类型.这是因为默认所有的对象都继承自Object.

// 使用instanceof查看是否是person或者Object类型
alert(person1 instanceof Object) // true
alert(person1 instanceof Person) // true
alert(person2 instanceof Object) // true
alert(person2 instanceof Person) // true

2.3. 关于构造函数

关于构造函数

我们知道, 构造函数也是一个函数, 只是使用的方式和别的函数不太一样.(使用new)
但是, 构造函数毕竟也是函数, 因此也可以像普通的函数一样去使用.
而且, 其他任何的函数, 也可以通过new关键字来调用, 这个时候这个函数也可以被称为构造函数.
把构造函数当做普通的函数去调用

// 当做构造函数使用
var person = new Person("wulin", 21, 1.8) // person对象
person.sayHello()// 作为普通的函数调用Person("wulin2", 21, 1.8) 
// window对象
window.sayHello()
// 在另外一个对象的作用域调用
var o = new Object()Person.call(o, "wulin", 21, 1.8)// o对象o.sayHello()

构造函数来创建对象的缺陷:

构造函数模式虽然好用,但也并非没有缺点。
使用构造函数的主要问题,就是每个方法都要在每个实例上重新创建一遍。
在前面的例子中,personl和person2都有一个名为sayName()的方法,但那两个方法不是同一个Function的实例。
JavaScript中的函数也是对象,因此每定义一个函数,也就是实例化了一个对象

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

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

相关文章

(四)Android布局类型(线性布局LinearLayout)

线性布局(LinearLayout):按照一定的方向排列组件,方向主要分为水平方向和垂直方向。方向的设置通过属性android:orientation设置 android:orientation 其取值有两种 水平方向:android:orientation"horizontal&…

Lua-Lua与C的交互3

Lua与C的交互是指在Lua脚本中调用C语言编写的函数或者在C语言中调用Lua脚本中定义的函数。这种交互可以实现Lua和C语言之间的数据传递和函数调用。 Lua提供了一组API函数,可以在C语言中使用这些函数来与Lua进行交互。通过这些API函数,C语言可以将数据传…

Java中如何解决if-else(策略+枚举)

最近接到了一个新需求,按照不同的编码去执行不同的逻辑,但最后返回的数据类型是一致的,都是相同对象的List集合。 完成这个需求的话可以使用if-else来执行不同的方法,虽然if-else可以实现,但if-else是一种面向过程的实…

MongoDB——linux中yum命令安装及配置

一、创建mongodb-org-3.4.repo文件 vi /etc/yum.repos.d/mongodb-org-3.4.repo 将下面内容添加到创建的文件中 [mongodb-org-3.4] nameMongoDB Repository baseurlhttps://repo.mongodb.org/yum/amazon/2013.03/mongodb-org/3.4/x86_64/ gpgcheck1 enabled1 gpgkeyhttps://www…

本地用AIGC生成图像与视频

最近AI界最火的话题,当属Sora了。遗憾的是,Sora目前还没开源或提供模型下载,所以没法在本地跑起来。但是,业界有一些开源的图像与视频生成模型。虽然效果上还没那么惊艳,但还是值得我们体验与学习下的。 Stable Diffu…

Ubuntu Linux - Primavera P6 EPPM 安装及分享

引言 根据计划,近日我制作了基于Ubuntu Linux 的P6虚拟机环境,同样里面包含了全套P6 最新版应用服务 此虚拟机仅用于演示、培训和测试目的。如您在生产环境中使用此虚拟机,请先与Oracle Primavera销售代表取得联系,以获取所需的应…

无人机助力智慧农田除草新模式,基于YOLOv5全系列【n/s/m/l/x】参数模型开发构建无人机航拍场景下的农田杂草检测识别系统

科技发展到今天,无人机喷洒药物已经不是一件新鲜事情了,在很多高危的工作领域中,比如高空电力设备除冰,电力设备部件传送更换等等,无人机都可以扮演非常出色的作用,前面回到老家一段时间,最近正…

吴恩达deeplearning.ai:使用多个决策树随机森林

以下内容有任何不理解可以翻看我之前的博客哦:吴恩达deeplearning.ai专栏 文章目录 为什么要使用树集合使用多个决策树(Tree Ensemble)有放回抽样随机森林XGBoost(eXtream Gradient Boosting)XGBoost的库实现何时使用决策树决策树和树集合神经网络 使用单个决策树的…

数据预处理在数据挖掘中的重要性

数据挖掘作为从大量数据中提取有用信息和知识的过程,其结果的准确性和可靠性直接受到数据质量的影响。因此,数据预处理在数据挖掘中扮演着至关重要的角色。让我们探讨数据质量对数据挖掘结果的影响,并介绍常见的数据预处理方法以及它们如何提…

2024.3.14每日一题

LeetCode 合并数组中的最大元素 题目链接&#xff1a;2789. 合并后数组中的最大元素 - 力扣&#xff08;LeetCode&#xff09; 题目描述 给你一个下标从 0 开始、由正整数组成的数组 nums 。 你可以在数组上执行下述操作 任意 次&#xff1a; 选中一个同时满足 0 < i …

【开源】SpringBoot框架开发房屋出售出租系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 房屋销售模块2.2 房屋出租模块2.3 预定意向模块2.4 交易订单模块 三、系统展示四、核心代码4.1 查询房屋求租单4.2 查询卖家的房屋求购单4.3 出租意向预定4.4 出租单支付4.5 查询买家房屋销售交易单 五、免责说明 一、摘…

短视频矩阵系统/短视频矩阵系统技术saas研发

短视频矩阵系统SaaS研发是一个复杂且需要技术专业知识的工作。以下是一些关键步骤和建议&#xff0c;帮助你开发一个成功的短视频矩阵系统SaaS&#xff1a; 1. 明确需求&#xff1a;首先&#xff0c;你需要明确你的短视频矩阵系统的具体需求&#xff0c;例如用户规模、视频内容…

力扣100热题:两、三、四数之和,哈希+数组+双指针+排序

目录 一、两数之和 二、两数之和 II - 输入有序数组 三、两数之和 III - 数据结构设计 四、两数之和 IV - 输入 BST&#xff08;二叉搜索树&#xff09; 五、三数之和 六、四数之和 一、两数之和 题目&#xff1a;1. 两数之和 参考力扣题解&#xff1a;. - 力扣&#x…

数据库——书籍+内容0.1版本

背景&#xff1a;将一本书&#xff0c;存入我们的数据库中&#xff0c;并可以查出来 采用&#xff1a;第三范式&#xff08;3NF&#xff09;设计模式 设计数据库模板 第一范式&#xff08;1NF&#xff09;&#xff1a;确保表的每一列都是不可分割的原子数据项。 第二范式&…

软件测试-------Web(性能测试 / 界面测试 / 兼容性测试 / 安全性测试)

Web&#xff08;性能测试 / 界面测试 / 兼容性测试 / 安全性测试&#xff09; 一、Web性能测试&#xff1a;&#xff08;压力测试、负载测试、连接速度测试&#xff09;1、压力测试&#xff1a;      并发测试 &#xff08;如500人同时登录邮箱&#xff09; 2、负载测试…

上位机图像处理和嵌入式模块部署(qmacvisual结束判断)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 在qmacvisual软件当中&#xff0c;这个判断结束很容易会给大家造成误会&#xff0c;因为它会让大家认为&#xff0c;这和是判断语句一起使用的。但…

PaaS家族的中坚力量——aPaaS

aPaaS是什么&#xff1f;接下来无雀科技为大家介绍一下。aPaaS作为一种先进的云服务模式&#xff0c;为用户提供了无缝的应用程序和部署环境。以SDK、API以及构建的组件为基础&#xff0c;通过零代码或低代码的方式大大地降低了软件开发的技术门槛&#xff0c;使得业务人员不需…

智慧能源管理系统在大学校园的应用-安科瑞 蒋静

1 背景 为贯彻落实《中共中央国务院关于完整准确全面贯彻新发展理念做好碳达峰碳中和工作的意见》和《国务院关于印发2030年前碳达峰行动方案的通知》要求&#xff0c;把绿色低碳发展纳入国民教育体系。 2 传统模式的痛点 传统项目模式下的系统方案缺乏整体的能源监测和管控…

AI在编程中的作用:提升效率、改善代码质量与未来发展趋势

引言 随着科技的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;已逐渐渗透到我们生活的方方面面&#xff0c;而在编程领域&#xff0c;AI的应用正带来革命性的变革。从代码生成到错误检测&#xff0c;再到自动化测试&#xff0c;AI的身影无处不在。本文将深入探讨AI…

前端 网络相关事件 交互

前端 网络相关事件 交互 设置断线、上线提示 这里可以做断线重连 使用online表示在线事件使用offline表示离线事件 当前是否离线 /*** * 判断是否离线* 如果是在线将值改为在线*/ window.addEventListener("offline", function (event) {onlineStatus.innerHTML…