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>
        // 例子1
        var obj1 = {
            a: 1,
            b: 2,
            c: 3
        };
        var obj2 = {
            a: 1,
            b: 2,
            c: 3
        };
        console.log(obj1 == obj2);      // false
        console.log(obj1 === obj2);     // false
        
        console.log({} == {});          // false
        console.log({} === {});         // false
        
        // 例子2
        var 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);
  // 遍历对象的key
  for (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);      // false
        
        obj1.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>

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【工具变量】“宽带中国”试点城市名单匹配数据集(2000-2023年)

参照秦文晋&#xff08;2022&#xff09;的《网络基础设施建设对数字经济发展的影响研究——基于"宽带中国"试点政策的准自然实验》一文中的做法&#xff0c;将选为“宽带中国”试点城市的虚拟变量作为核心解释变量&#xff0c;当一个城市被批复成为“宽带中国”试点…

Matlab车牌识别课程设计报告(附源代码)

Matlab车牌识别系统 分院&#xff08;系&#xff09; 信息科学与工程 专业 学生姓名 学号 设计题目 车牌识别系统设计 内容及要求&#xff1a; 车牌定位系统的目的在于正确获取整个图像中车牌的区域&#xff0c; 并识别出车牌号。通过设计实现车牌识别系…

基于OSS搭建在线教育视频课程分享网站

OSS对象存储服务是海量、安全、低成本、高持久的存储服务。适合于存储大规模非结构化数据&#xff0c;如图片、视频、备份文件和容器/虚拟机镜像等。 安装nginx wget https://nginx.org/download/nginx-1.20.2.tar.gz yum -y install zlib zlib-devel gcc-c pcre-devel open…

Edit Data. Create Cell Editors. Validate User Input 编辑数据。创建 Cell Editors。验证用户输入

Goto Data Grid 数据网格 Edit Data. Create Cell Editors. Validate User Input 编辑数据。创建 Cell Editors。验证用户输入 Get and Modify Cell Values in Code 在代码中获取和修改单元格值 仅当 Grid 及其列已完全初始化时&#xff0c;才使用以下方法。如果需要在表单仍…

【JavaEE初阶 — 多线程】Thread的常见构造方法&属性

目录 Thread类的属性 1.Thread 的常见构造方法 2.Thread 的几个常见属性 2.1 前台线程与后台线程 2.2 setDaemon() 2.3 isAlive() Thread类的属性 Thread 类是JVM 用来管理线程的一个类&#xff0c;换句话说&#xff0c;每个线程都有一个唯一的Thread 对象与之关联&am…

【设计模式】如何用C++实现依赖倒置

【设计模式】如何用C实现依赖倒置 一、什么是依赖倒置&#xff1f; 依赖倒置原则&#xff08;Dependency Inversion Principle&#xff0c;DIP&#xff09;是SOLID面向对象设计原则中的一项。它的核心思想是&#xff1a; 高层模块不应该依赖于低层模块&#xff0c;两者都应该…

【文献及模型、制图分享】中国城市家庭食物浪费行为及减量对策——以郑州市为例

文献介绍 减少食物浪费是保障粮食安全的重要途径。家庭是社会的基本单元&#xff0c;不仅是产生食物浪费的主要场景&#xff0c;也是开展反食品浪费教育的重要场所。本文以河南省郑州市为例&#xff0c;基于1315份城市家庭食物浪费一手调查数据&#xff0c;首次将城市家庭食物…

【Linux】从零开始使用多路转接IO --- poll

碌碌无为&#xff0c;则余生太长&#xff1b; 欲有所为&#xff0c;则人生苦短。 --- 中岛敦 《山月记》--- 从零开始使用多路转接IO 1 前言1 poll接口介绍3 代码编写4 总结 1 前言 上一篇文章我们学习了多路转接中的Select&#xff0c;其操作很简单&#xff0c;但有一些缺…

linux网络编程自定义协议和多进程多线程并发

1.三次握手及后面过程 计算机A是客户端, B是服务端 1.1三次握手&#xff1a; 1客户端给服务端SYN报文 2服务端返回SYNACK报文 3客户端返回ACK报文 客户端发完ACK后加入到服务端的维护队列中&#xff0c;accept()调用后就能和客户端建立连接&#xff0c;然后建立通讯 1.2关闭…

[CARLA系列--01]CARLA 0.9.15 在Windows下的安装教程(一)

Carla是一款开源的自动驾驶仿真器&#xff0c;它基本可以用来帮助训练自动驾驶的所有模块&#xff0c;包括感知系统&#xff0c;Localization, 规划系统等等.Carla这个产品目前已经更新到了最新的0.9.15版本,目前遇到好多人在windows系统上如何安装可编辑版的Carla遇到了好多问…

【Qt聊天室客户端】用户信息界面设置功能实现

1. 按钮禁用关系梳理 基本逻辑梳理 用户界面-申请好友按钮 只有当前用户不是你的好友时&#xff0c;该按钮才可以使用&#xff0c;否则是禁用状态 用户界面-发送消息与删除好友 当前用户是你的好友时&#xff0c;按钮才可以使用&#xff0c;否则这两个按钮禁用区分是否是你好…

一张图简单讲述Mamba的演进过程

这张图表提供了 RNN&#xff08;1986&#xff09;、LSTM&#xff08;1997&#xff09;、Transformer&#xff08;2017&#xff09;和 Mamba&#xff08;2024&#xff09;四种不同的神经网络架构在训练阶段、测试阶段和额外问题方面的对比。可以看出&#xff0c;Mamba 作为一种最…

redis v6.0.16 安装 基于Ubuntu 22.04

redis安装 基于Ubuntu 22.04 本文演示如何在ubuntu22.04下&#xff0c;安装redis v6.0.16&#xff0c;并配置测试远程访问。 Step1 更新环境 sudo apt updateStep2 安装redis sudo apt install redis-server -yStep3 启动 sudo systemctl restart redissudo systemctl sta…

Postman:高效的API测试工具

在现代软件开发中&#xff0c;前后端分离的架构越来越普遍。前端开发者与后端开发者之间的协作需要一种高效的方式来测试和验证API接口。在这个背景下&#xff0c;Postman作为一款强大的API测试工具&#xff0c;受到了广泛的关注和使用。 今天将介绍什么是Postman、为什么要使用…

Vue指令:v-else、v-else-if

目录 1.语法&#xff1a; 2. 题目 3.页面展示 4.结构 1.语法&#xff1a; 1.作用&#xff1a;辅助v-if进行判断渲染 2.语法&#xff1a;v-else 、v-esle-if"表达式" 2. 题目 <!DOCTYPE html> <html lang"en"> <head><meta chars…

RANSAC(随机抽样一致性算法)

RANSAC&#xff08;随机抽样一致性算法&#xff09;是一种用于估计数学模型参数的迭代方法&#xff0c;尤其适用于包含大量异常值的数据。使用 RANSAC&#xff0c;我们可以找到一个最优的线性拟合&#xff0c;同时最大限度地减少对异常值的影响。接下来&#xff0c;我将给出一个…

群控系统服务端开发模式-应用开发-业务架构逻辑开发第一轮测试

整个系统的第一个层次已经开发完毕&#xff0c;已经有简单的中控&#xff0c;登录、退出、延迟登录时长、黑名单、数据层封装、验证层封装、RSA加解密、Redis等功能&#xff0c;还缺获取个人、角色按钮权限、角色菜单权限功能。角色按钮权限以及角色菜单权限等明后天开发&#…

react基础之reactHooks

文章目录 React Hooks 使用指南常用 Hooks使用规则 小结 React Hooks 使用指南 React Hooks 是 React 16.8 引入的一种新特性&#xff0c;允许在函数组件中使用状态和其他 React 特性&#xff0c;而无需编写类组件。以下是一些基础的 Hooks 及其使用规则。 常用 Hooks useSta…

桑基图在医学数据分析中的更复杂应用示例

桑基图&#xff08;Sankey Diagram&#xff09;能够有效地展示复杂的流动关系&#xff0c;特别适合用于医学数据分析中的多种转归和治疗路径的可视化。接下来&#xff0c;我们将构建一个稍微复杂的示例&#xff0c;展示不同疾病患者在治疗过程中的流动&#xff0c;以及他们的治…

Android15音频进阶之Cuttlefish搭建音频开发环境(九十二)

简介: CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布:《Android系统多媒体进阶实战》🚀 优质专栏: Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏: 多媒体系统工程师系列【原创干货持续更新中……】🚀 优质视频课程:AAOS车载系统+…