当前位置: 首页 > news >正文

JS中面向对象

一、对象

1.认识对象

在JavaScript中,对象(Object)是一种复合数据类型,它允许你存储键值对。对象的属性是连接到对象的变量,而函数或方法是属于对象的函数。
JavaScript中的对象类似于哈希表,其中键可以是字符串或符号,值可以是任意类型的值,包括其他对象。对象字面量是用花括号 {} 包围的,其中冒号 : 用于分隔键和值,逗号 , 用于分隔不同的键值对。 

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script>var xiaoming = {name: '小明',age: 12,sex: '男',hobbies: ['足球', '编程'],'favorite-book': '舒克和贝塔'};console.log(xiaoming.name);console.log(xiaoming.age);console.log(xiaoming.sex);console.log(xiaoming.hobbies);console.log(xiaoming['favorite-book']);var key = 'sex';console.log(xiaoming[key]);console.log();Math.ceil();</script>
</body>
</html>

对象属性的修改

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script>var obj = {a: 10,b: 20};// 对象属性的修改obj.b = 40;obj.b++;console.log(obj.b);// 对象属性的增加obj.c = 60;console.log(obj);// 对象属性的删除delete obj.a;console.log(obj);</script>
</body>
</html>

2.对象的方法

在JavaScript中,面向对象的方法通常是在构造函数或者类中定义的。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script>var xiaoming = {name: '小明',age: 12,sex: '男',sayHello: function () {console.log('你好我是小明,我12岁了,我是一个男生');},sleep: function () {console.log('小明开始睡觉zzzzz');}};var xiaohong = {name: '小红',age: 11,sex: '女',sayHello: function () {console.log('你好我是小红,我11岁了,我是一个女生');},sleep: function () {console.log('小红开始睡觉zzzzz');}};xiaoming.sayHello();xiaohong.sayHello();xiaohong.sleep();</script>
</body>
</html>

3.遍历对象

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>var obj = {a: 11,b: 22,c: 88};for (var k in obj) {console.log('对象obj的属性' + k + '的值是' + obj[k]);}</script>
</body></html>

4.对象的深浅克隆

对象是引用类型

在 JavaScript 中,对象是通过引用传递的,这意味着当我们将一个对象赋值给另一个变量时,我们实际上是在复制该对象的引用,而不是复制整个对象。因此,当我们改变通过引用访问的对象时,所有对该对象的引用都会看到这种变化。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script>// 例子1var obj1 = {a: 1,b: 2,c: 3};var obj2 = {a: 1,b: 2,c: 3};console.log(obj1 == obj2);      // falseconsole.log(obj1 === obj2);     // falseconsole.log({} == {});          // falseconsole.log({} === {});         // false// 例子2var obj3 = {a: 10};var obj4 = obj3;obj3.a ++;console.log(obj4);      // {a: 11}</script>
</body>
</html>

在JavaScript中,对象的克隆可以通过浅克隆和深克隆来实现。以下是两种克隆方法的实现方式:

浅克隆

浅克隆只会复制对象的第一层属性,如果属性值是基本类型,则拷贝的是基本类型的值;如果属性值是引用类型,则拷贝的是内存地址,因此如果原始对象或克隆对象中的引用类型属性发生变化,另一个对象也会受到影响。

以下是实现浅克隆的一种简单方法:

function shallowClone(obj) {const cloneObj = {};for (const key in obj) {if (obj.hasOwnProperty(key)) {cloneObj[key] = obj[key];}}return cloneObj;
}const original = { a: 1, b: { c: 2 } };
const cloned = shallowClone(original);
console.log(cloned); // { a: 1, b: { c: 2 } }
cloned.b.c = 3;
console.log(original); // { a: 1, b: { c: 3 } } // 原始对象也被修改了
<script>var obj1 = {a: 1,b: 2,c: [44, 55, 66]};// 实现浅克隆var obj2 = {};for (var k in obj1) {// 每遍历一个k属性,就给obj2也添加一个同名的k属性// 值和obj1的k属性值相同obj2[k] = obj1[k];}// 为什么叫浅克隆呢?比如c属性的值是引用类型值,那么本质上obj1和obj2的c属性是内存中的同一个数组,并没有被克隆分开。obj1.c.push(77);console.log(obj2);                  // obj2的c属性这个数组也会被增加77数组console.log(obj1.c == obj2.c);      // true,true就证明了数组是同一个对象</script>

深克隆

深克隆会复制对象的所有层级属性。对于每个引用类型的属性,都会创建一个新的对象或数组,从而不会相互影响。

以下是实现深克隆的一种方法,它考虑了数组和对象,但并不包含对函数、循环引用或特殊对象(如Date、RegExp等)的处理:

function deepClone(obj, hash = new WeakMap()) {if (obj === null) return null; // 处理null值if (obj instanceof Date) return new Date(obj); // 处理日期if (obj instanceof RegExp) return new RegExp(obj); // 处理正则if (typeof obj !== 'object') return obj; // 如果不是复杂数据类型,直接返回// 如果是对象或数组,先检查hash中是否克隆过,解决循环引用问题if (hash.has(obj)) {return hash.get(obj);}// 初始化返回结果,保证数组和对象的原型不丢失let cloneObj = Array.isArray(obj) ? [] : {};// 将对象或数组存入hash中hash.set(obj, cloneObj);// 遍历对象的keyfor (const key in obj) {if (obj.hasOwnProperty(key)) {// 递归克隆每个值cloneObj[key] = deepClone(obj[key], hash);}}// 返回克隆后的对象return cloneObj;
}const original = { a: 1, b: { c: 2, d: { e: 3 } } };
const cloned = deepClone(original);
console.log(cloned); // { a: 1, b: { c: 2, d: { e: 3 } } }
cloned.b.d.e = 4;
console.log(original); // { a: 1, b: { c: 2, d: { e: 3 } } } // 原始对象未被修改

需要注意的是,上述深克隆方法并不完美,它没有处理函数、循环引用、特殊对象类型等复杂情况。在实际应用中,你可能需要使用更完善的库,比如 lodash 的 _.cloneDeep 方法,来处理这些情况。

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>var obj1 = {a: 1,b: 2,c: [33, 44, {m: 55,n: 66,p: [77, 88]}]};// 深克隆function deepClone(o) {// 要判断o是对象还是数组if (Array.isArray(o)) {// 数组var result = [];for (var i = 0; i < o.length; i++) {result.push(deepClone(o[i]));}} else if (typeof o == 'object') {// 对象var result = {};for (var k in o) {result[k] = deepClone(o[k]);}} else {// 基本类型值var result = o;}return result;}var obj2 = deepClone(obj1);console.log(obj2);console.log(obj1.c == obj2.c);      // falseobj1.c.push(99);console.log(obj2);                  // obj2不变的,因为没有“藕断丝连”的现象obj1.c[2].p.push(999);console.log(obj2);                  // obj2不变的,因为没有“藕断丝连”的现象</script>
</body></html>

二、认识函数上下文

这个this.a+this.b=? 不是3 而是不知道 为什么不知道呢 因为函数只有被调用的时候才知道上下文。如果是obj.fn()那么答案是3;

但如果是var fn =obj.fn;

fn();

还是输出NaN不知道;因为圆括号直接调用,函数中的this指代windows对象。

    <script>var obj = {a: 1,b: 2,fn: function() {console.log(this.a + this.b);console.log(this === window);}};// var a = 4;// var b = 9;obj.fn();console.log('---------');var fn = obj.fn; //不加圆括号,代表提炼函数本身fn();</script>

函数的上下文由调用函数的方式决定

规则1:对象.方法();对象打点调用它的方法函数,则函数的上下文是这个打点的对象;

 规则2:函数();圆括号直接调用函数,则函数的上下文是window对象

var fn=obj1.fn;这是把这个函数提取出来,和obj1中的属性值就没有关系了。fn()在调研这个fn函数。

规则3:数组[下标]();数组(类数组对象)枚举出进行调用,上下文是这人数组(类数组对象)

规则4:立即可执行函数,上下文是window对象

规则5:定时器、延时器调用函数,上下文是window对象

规则6:事件处理函数的上下文是绑定事件的DOM元素

Demo1:点击哪个盒子哪个盒子就变红
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>div{width: 200px;height: 200px;float: left;border: 1px solid #000;margin-right: 10px;}</style>
</head>
<body><div id="box1"></div><div id="box2"></div><div id="box3"></div><script>function setColorToRed() {this.style.backgroundColor = 'red';}var box1 = document.getElementById('box1');var box2 = document.getElementById('box2');var box3 = document.getElementById('box3');box1.onclick = setColorToRed;box2.onclick = setColorToRed;box3.onclick = setColorToRed;</script>
</body>
</html>
Demo2:点击哪个盒子哪个盒子2000ms后就变红

延时器中的this指代的是window对象,所以要备份自身。可以使用self、_this表示备份

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>div{width: 200px;height: 200px;float: left;border: 1px solid #000;margin-right: 10px;}</style>
</head>
<body><div id="box1"></div><div id="box2"></div><div id="box3"></div><script>function setColorToRed() {// 备份上下文var self = this;setTimeout(function() {self.style.backgroundColor = 'red';}, 2000);}var box1 = document.getElementById('box1');var box2 = document.getElementById('box2');var box3 = document.getElementById('box3');box1.onclick = setColorToRed;box2.onclick = setColorToRed;box3.onclick = setColorToRed;</script>
</body>
</html>

call和apply

call和apply能指定函数的上下文

    <script>function sum() {alert(this.c + this.m + this.e);};var xiaoming = {c: 100,m: 90,e: 80,sum:sum};//小明是不能直接打点调用sum的,必须要在xiaoming对象里面添加sum方法。xiaoming.sum();</script>
    <script>function sum() {alert(this.c + this.m + this.e );};var xiaoming = {c: 100,m: 90,e: 80};sum.call(xiaoming);sum.apply(xiaoming);</script>

call和apply的区别

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script>function sum(b1, b2) {alert(this.c + this.m + this.e + b1 + b2);};var xiaoming = {c: 100,m: 90,e: 80};sum.call(xiaoming, 3, 5);sum.apply(xiaoming, [3, 5]);</script>
</body>
</html>

这道题会显示77

总结


http://www.mrgr.cn/news/65574.html

相关文章:

  • 鸿蒙进阶-AlphabetIndexer组件
  • Docker部署Portainer CE结合内网穿透实现容器的可视化管理与远程访问
  • 头歌——数据库系统原理(数据高级查询实验1)
  • 一种基于GPU的归并排序并行实现
  • Spring @RequestMapping 注解
  • WPS查询函数VLOOKUP,匹配寻找值自动带入值
  • 源码阅读心得---如何从零开始阅读一个框架的源码
  • (七)Python运算符和优先级
  • 心觉:人每日60000念头,如何让你的时间精力只专注于核心目标?
  • R 语言数据导入与导出
  • 贝尔不等式的验证
  • “代码世界的必修课:Git完整指南“(3)
  • SSD201 SSD202D SigmaStar智能高清显示芯片
  • 「Mac畅玩鸿蒙与硬件15」鸿蒙UI组件篇5 - Slider 和 Progress 组件
  • 北京美信时代渠道代理:运维后期维保服务策略
  • 跳表原理笔记
  • TensorRT-LLM笔记
  • 高效内容营销策略提升品牌影响力与客户忠诚度
  • RAC 添加redo log group
  • 惊喜!RFID技术的应用竟如此多元?
  • springboot使用kafka推送数据到服务端,带认证
  • php代码审计--常见函数整理
  • SpringBoot启动器
  • unity游戏开发之--人物打怪爆材料--拾进背包的实现思路
  • React系列教程(2)React哲学
  • 开源呼叫中心系统 FreeIPCC:WebRTC 详解