十五分钟上手JavaScript之 JavaScript面向对象
JavaScript面向对象(OOP)
JavaScript面向对象(OOP)
- 全文总计:9192字(含代码)预计阅读15分钟,实践+消化约为2小时
文章目录
对象时引用类型
数据类型
数据类型可以分为两类
- 基础类型:
string number boolean null undefined
- ES6加的:
symbol 唯一性
,bigInt大整形
- ES6加的:
- 引用类型:
object
基础类类型数据量小,引用类型数据量大————对象中可以存储任意个属性
JavaScript的数据处理
数据操作在内部的处理
计算机底层–内存中划分出两个存储去:堆和栈
栈:储存小型的数据,查询快—字典目录
堆:存储大数据,查询速度满—字典详情页
传递参数就为:
来看看下面的示例
var a=10
var b=a
a=20
console.log(b);
// ?
对象的浅拷贝
对象用” = “来赋值,是地址
/引用类型
能不能拷贝一份而不是转为对应地址呢?
浅拷贝
浅拷贝:创建一个新的对象,把要拷贝的对象的属性挨个赋值到新的对象里
浅拷贝图示
浅拷贝实例
首先要创建一个方法 把传入的对象进行克隆,返回出克隆的新的对象
function sim_clone(obj){
// 把传入的对象进行克隆,返回出克隆的新的对象
// 所以需要一个形参
}
把传入进来的每个属性,添加到空对象里,来遍历对象
var emp = { name: "qiushan", age: "19", phone: 1008611 };
function sim_clone(obj){
// 把传入的对象进行克隆,返回出克隆的新的对象
// 所以需要一个形参
// 1.先创建一个新的对象
var x ={}
// 2,把传入进来的每个属性,添加到空对象里
// 遍历对象
for(var key in obj){
// 转移参数
x[key]=obj[key];
}
}
浅拷贝原理
原理就是:
还有一种方法,可以这样写
// 浅拷贝:创建一个新的对象,把要拷贝的对象的属性挨个赋值到新的对象里
var emp = { name: "qiushan", age: "19", phone: 1008611 };
function sim_clone(obj) {
// 把传入的对象进行克隆,返回出克隆的新的对象
// 所以需要一个形参
// 1.先创建一个新的对象
var x = {};
// 2,把传入进来的每个属性,添加到空对象里
// 遍历对象
for (var key in obj) {
// 转移参数
x[key] = obj[key];
// var value = obj[key];
// 通过属性名获取对应的值
// x[key] = value;
// 把值赋值{插入} x对象中对应的属性
}
return x;
// 通过返回操作把x暴露给外部
}
接下来我们测试一下
// 使用sim_clone 来进行处理数据
console.log('emp',emp);
emp.age=110
console.log('emp1',sim_clone(emp));
我们可以看到
关于浅拷贝的疑问
为什么我写这个对象时,上面name是在前面的咋到后面去了呢?
对象是没有排序的,所以会按照ascii码来默认排序
为什么上面的数据上面简洁与下面列表显示的不相同呢?
浏览器后台,当点击三角符号 展开对象是,会临时读取数据的最新状态
浅拷贝:仅适用于 对象的属性都是普通数据类型的场景
如果对象的属性存在引用类型
关键词this在内部的操作
首先创建一个代表矩形的对象
表达式:
// 代表矩形的对象
var r1 ={length:10,width:20}
var r2 ={length:15,width:10}
接下来我们需要制作一个计算面积的方法
回调函数:
function area(r) {
// r.length:长
// r.width:宽
return r.length * r.width;
}
console.log(area(r1));
关键词this在内部的操作-举例
举个例子,这就相当于核酸检测就是回调函数,是固定的,而人就相当于长和宽,核酸检测点是固定的,而数据是不同的
现在我们来讲讲,上门的核酸检测:核算员流动检测,到谁家里就给谁做核酸
推到出:函数要传递到对象里,为所在的对象进行检测
关键词this在内部的操作-结论
由此areas()
这个方法就相当于核酸员,去业主(数组/对象
)家里做核酸(计算属性
)
所以代码可以写为:
// 核酸员
function areas() {
// 带着做核酸的工具(工具包) ...
console.log(this.width * this.length);
}
// 去业主家
r1.areas = areas;
// 做核酸
r1.areas()
this:这个函数所在的对象
结果显示为阴性我们去下一家r2业主家做核酸
function areas() {
// 带着做核酸的工具(工具包) ...
console.log(this.width * this.length);
}
// 来到了业主家
r2.areas = areas;
// 做核酸
r2.areas();
结果阳性,保安抓去隔离!【滑稽】(数值不同,说明方法是可用的
)
对象的原型设计–JS的核心设计
构造函数
构造函数:一类特殊功能的函数,用途是构建创造对象
构造函数示例
创建日期对象
// 日期对象
var d=new Date()
console.log("d:",d);
console.dir(d);
日期对象结果
数组对象案例
var nums = new Array(1,2,3,4,5,6,7,8,9,0);
console.log(nums);
console.dir(nums);
数组对象结果
构造函数的写法和字面量写法
// 字面量写法
function add(x,y){
return x + y;
}
// 构造写法
var add2 =new Function('x','y','return x+y')
console.log(add2);
console.log(add2(10,20));
构造函数和简化写法的区别
实际上JS中的所有对象
都是通过函数来生成的
这些生成这些对象
的函数**,都叫构造函数
**
从格式上,构造函数都搭配new关键词出现,有点类似TS的语法哈
基本上搭配了new关键词的代码段都可能是构造的哦 !
自定义构造函数
构造函数的命名规范
命名规范:大驼峰命名法
:首字母大写
系统构造函数名:Array Object Function Date...
目的:使用者通过观察函数名,就是到是构造函数
实践–生成矩形对象的函数
现在我们来做一个生成矩形对象的函数试试吧
分析:矩形(rectangle)必定带有的属性:长(length )和 宽(width)
即:
测试–生成的函数
构造函数的原理
简单说就是:类似一个回调函数,来生成一些事物
构造函数的扩展
即:我们可以使用this来进行更高级的操作
构造函数的“高级的操作”
function Rec(length, width) {
// 1,先做空对象
var obj = {};
// 2,把实参存入对象中,配上对应的属性名
obj.width = width;
obj.length = length;
// 3,返回对象
// 面积
obj.area=function(){
return this.width*this.length
}
return obj;
}
var r1=Rec(10,20);
console.log("r1",r1);
关于做核酸里面的this还不懂的可以去看看我的this讲解关于this的解析
我们也可以尝试调用一下这个方式:
var r1 = Rec(10, 20);
console.log("r1", r1);
var r2 = Rec(80, 200);
console.log("r2", r2.area());
解决资源过度的消耗怎么办?
现在问题来了——资源过度的消耗怎么办?
我们如何让其解决资源过度的资源 消耗 / 占用 呢?
解决
打个比方就是:
仔细看这张图,下面重点围绕着这个话题来说(知道你们爱听)
不懂也没关系看下面,知道你看不懂
原型
原型:prototype
空老师拍电影
小日本,呸…!,小日子过得不错的哪个国家的著名女演员 ,某某空正在策划下一场动作大片,借机重回巅峰
策划一部电影(看注释)
function Kon(where){
// where拍摄的地方,筹备拍摄(创建中转数组)
var obj={}
// 写邀请函,然后确定地点(转存数据)
obj.where=where
// 然后得把自己的包装简历(Kon.prototype)加入到作品(obj._proto_)里面
// 把数据共享给演员和剪辑师(whe1,whe2,...)剪辑师把信息包装进电影(_proto)里面(写入原型信息)
obj._proto_=Kon.prototype
// 注意 是__proto__不是_proto_,有两个’_‘
//大片定档(导出数据)
return obj
}
定档之后要给每个人剧本以及方案
// 第一个地点发过去拍的电影邀请函
var whe1=Kon('XX株式会社')
console.log('地点1',whe1);
// 第二个地点发过去拍的电影邀请函
var whe2=Kon('XX株式神社')
// 发布视频后,演员点开了电影信息
console.log('地点2',whe2);
由于某空只是一个18线小明星所以某空包装一下自己是不可少的所以打算在自己介绍和电影(prototype
)里添加一些信息
Kon.prototype.topball='36D'
Kon.prototype.height='150'
Kon.prototype.age='18'
Kon.prototype.title='xx的朋友'
由于是自己包装的电影信息发到聊天室(_proto_
)里面告诉大家信息,大家可以同过聊天信息,获取演员,剧情等来进行拍摄
现在我们作为吃瓜者是不是要看看邀请函(whe1,whe2…)和信息(共享信息__proto__
)呢 ?
// 摄影师拿到的邀请函
var whe1=Kon('XX株式会社')
// 摄影师拿到的邀请函
console.log('摄影师',whe1);
// 演员去拿邀请函
var whe2=Kon('XX株式神社')
// 演员拿到的邀请函
console.log('演员1',whe2);
// 剧本和信息
console.dir(Kon);
剧本(结果)如下
让我们期待最新电影的消息吧接下来我们看几个demo吧
制作立方体面积计算函数
制作一个立方体(Cube
)计算面积的构造函数接受三个参数
拥有两个方法
**volume:**计算体积
**zc:**计算周长
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
// 制作一个立方体(Cube)构造函数
// 接受三个参数
// 拥有两个方法
// volume:计算体积
// zc:计算周长
function Cube(x, y, z) {
obj = {};
obj.x = x;
obj.y = y;
obj.z = z;
obj.___proto___ = Cube.prototype;
return obj;
}
Cube.prototype.volume = function () {
return this.x * this.y * this.z;
};
Cube.prototype.zc = function () {
return (this.x + this.y + this.z) * 4;
};
var r1 = Cube(1, 2, 3);
console.log(r1.volume());
console.log(r1.zc());
var r2 = Cube(1213, 391801, 13014);
console.log(r2.volume());
console.log(r2.zc());
</script>
</body>
</html>
原型-传入两个值求面积
实验传入两个数据然后计算面积
// 矩形构造函数
function Rec(width, length) {
var obj = {};
obj.width = width;
obj.length = length;
// 要通过原型链__proto__链接来保存prototype
obj.__proto__ = Rec.prototype;
return obj;
}
// 共享的计算面积方式放在原型里面
Rec.prototype.aera = function () {
// console.log(this)
return this.width;
};
// 看一下是否有原型
console.dir(Rec);
// 使用原型
var r1 = Rec(30, 40);
console.log("r1", r1);
var r2 = Rec(60, 45);
console.log("r2", r2);
console.log("r2", r2.aera());
// 添加一个计算面积的方法
求面积的结果
我们可以看到上面的代码运行返回了数值,观察代码理解结构即可
原型总结
原型理论:主要的目的是节省内存 复用函数如何实现
构造函数自带一个
prototype 原型
:只是对象类型,用于存储共享的方法每个构造函数制作的对象都具有一个
__proto__
(原型链)用于保存原型的地址链接(prototype)原型链相当于狗链,一个是链接狗身上的一个是连接到
原型对象prototype
上面的
new运算符
new的好处:减少工作量,简化步骤,不再繁琐
new原型的步骤
- 声明变量this;
- 赋值为{};
- 设置对象的原型链;
- 返回对象;
使用和未使用new的对比
修改之前
<body>
<script>
function Rec(x, y, z) {
var obj = {};
obj.x = x;
obj.y = y;
obj.z = z;
obj.__proto__ = Rec.prototype;
return obj;
}
Rec.prototype.add=function(){
return this.x+this.y+this.z;
}
var obs= Rec(123,456,789)
console.log(obs.add());
</script>
</body>
修改之后
<body>
<script>
// 修改之后
function Rec(x, y, z) {
// var obj = {};
// obj.x = x;
// obj.y = y;
// obj.z = z;
this.x = x;
this.y = y;
this.z = z;
// obj.__proto__ = Rec.prototype;
// return obj;
}
Rec.prototype.add = function () {
return this.x + this.y + this.z;
};
// var obs = Rec(123, 456, 789);
var obs = new Rec(123, 456, 789);
console.log(obs.add());
</script>
</body>
使用和未使用的图示
new运算符的好处
可以让构造函数省略4行代码
- var this
- this = {}
- this.proto = 构造函数.prototype
- return this
简化了原型创建的流程,使开发难度降低