JavaScript入门【3】面向对象

news2025/5/18 20:09:58

1.对象:

1.概述:

   在js中除了5中基本类型之外,剩下得都是对象Object类型(引用类型),他们的顶级父类是Object;

2.形式:

   在js中,对象类型的格式为key-value形式,key表示属性,value表示属性的值

3.创建对象的方式:

方式1:通过new关键字创建(不常用)
    let person = new Object();
       // 添加属性  与 值
       person.name="张三";
       person.age = 22;
       console.log(person)      

方式2:通过{}类似于JSON字符串的形式创建:
     let person = {
        name: '张三',
        age: 20
    }
    console.log(person);   

4.对象的相关操作:

1.添加属性:
    let person = new Object();
       // 添加属性  与 值
       person.name="张三";
       person.age = 22;
       console.log(person)      

let person = {
        name: '张三',
        age: 20
    }
    console.log(person);
    // 添加属性
    person.sex = '男';
   

2.获取属性值:

对于new方式创建的对象,获取属性值的方式如下:

    let person = new Object();
       // 添加属性  与 值
       person.name="张三";
       person.age = 22;
       
       console.log(person.name)       

对于{}方式创建的对象,获取属性值得方式如下(上面得方式也适用):

let person = {
        name: '张三',
        age: 20
    }
    console.log(person['age']);
    
   

3.删除属性:通过delete关键字实现(两种创建方式都适用)
let person = {
        name: '张三',
        age: 20,
        sex:'男'
    }
   delete person.sex;
    console.log(person);
    
    

4.遍历对象属性:for-in循环
let person = {
        name: '张三',
        age: 20,
        sex:'男'
    }
    for (let personKey in person) {
        console.log(personKey,person[personKey]);
    }
    
      

2.函数:不依赖于实例对象

1.概述:

是由一连串的子程序(语句的集合)组成的,可以被 外部调用,向函数内部传入参数之后,函数可以返回的一定的值得代码集合;

2.函数对象的创建:

方式1;通过new关键字:(不常用)
let  函数名=new Function("执行的语句");

let funA = new Function("console.log('函数对象执行了')");
//调用函数:
funA();

方式2:声明式创建函数
function 函数名(形参1,形参2.....) {
        语句
    }
function sum(num1, num2, num3) {
        console.log("执行了sum函数:收到了参数:", num1, num2, num3)
        //可以使用return 返回结果
        return num1 + num2;
    }
    //调用函数
    let ret=sum(1,2);
    console.log(ret);

注意事项:

  •   调用有参函数时,传入的参数不受函数定义的函数列表影响,可以多传,少穿,或者不传;
    
  •   创建函数时,不涉及返回值(类似于Java中的构造方法),但函数体内可以return执行结果;
    

3.函数的类型:

1.常规函数:上述函数即为常规函数
function 函数名(形参1,形参2.....) {
        语句
    }   
2.匿名函数:没有函数名,而是由一个变量进行接收
 let 变量名(函数名)=function(形参1,形参2.....) {
         执行语句
    }
3.嵌套函数:即函数体内包含一个子函数
 function 父函数名(形参1,形参2.....) {
        function 子函数名(形参1,形参2.....) {
            语句
       }   
    }   

注意:直接调用父函数时,无法执行子函数

function fu() {
        function zi() {
            console.log("我是子函数");
        }
        父函数的其他执行语句
    }   
 //调用父函数
  fu();

如果需要执行子函数,则需要在父函数中手动调用子函数

function fu() {
        function zi() {
            console.log("我是子函数");
        }
        zi();
       // 父函数的其他执行语句
    }   
 //调用父函数
  fu();

4.立即执行函数:可理解为函数一创建出来就被调用执行
(function (形参1,.....) {
        执行语句
    })(实参.........)
(function (msg) {
        console.log("我是一个匿名函数",msg)
    })('我是一段消息');

3.方法:需依赖于示例对象

1.方法的定义:

      需要先创建对象,然后依赖对象在创建方法;
 let person = {
           name:'张三',
           age:23,
           //定义方法
           sayHello:function () {
               console.log(this.name+",Hello")
           }
       }
       console.log(person)
       //调用方法
       person.sayHello();     

2.this关键字:

1.this出现在函数中:被直接调用,则this表示window对象
 <script>
      function fun() {
          console.log(this.constructor+ ",Hello")
      }
      fun();
  </script>      

通过输出的构造方法名,可以看出此时的this表示window对象

2.this出现在方法中:this表示当前对象(谁调用,this就指代谁)
  function fun() {
        console.log(this.name + ",Hello")
    }

    let person = {
        name: '张三',
        age: 23,
        sayHello: fun
    }
    let person2 = {
        name: '李四',
        age: 23,
        sayHello: fun
    }
    person.sayHello(); //对象调用方法
    person2.sayHello();

通过测试结果可以看出,在方法中的this被那个对象调用,this就指代那个对象

4.创建对象的几种方式:

1.直接创建:

存在问题:
       如果需要创建的对象过多,直接创建无法实现代码的高复用性,代码冗余严重;

2.通过工厂模式,封装创建对象的方法:

实现:
 function createPerson(name, age) {
        let obj = new Object();
        obj.name = name;
        obj.age = age;

        obj.sayHello = function () {
            console.log(this.name)
        }
        return obj;
    }
    let person1 = createPerson('张三', 22); //Object 类型
    let person2 = createPerson('李四', 22); //Object 类型
    console.log(person1,person2)
       

存在问题:
通过下面测试结果可以看出,使用工厂模式创建的对象没有独立的类型,全部都是Object;
 function createPerson(name, age) {
        let obj = new Object();
        obj.name = name;
        obj.age = age;

        obj.sayHello = function () {
            console.log(this.name)
        }
        return obj;
    }
    let person1 = createPerson('张三', 22); //Object 类型
    let person2 = createPerson('李四', 22); //Object 类型
    console.log(typeof person1, typeof person2)
       

3.通过构造函数创建对象:

构造函数是什么:
  •    构造函数就是一个普通的函数,创建方式和普通函数没有区别;
    
  •    不同的是 构造函数一般首字母大写,调用时不同 需要使用new关键字;
    
构造函数的执行流程:
  •  1.调用构造函数,会立刻创建一个新的对象
    
  •  2.将新建的对象设置为函数中的this,在构造函数中可以使用this开引用新建的对象
    
  •  3.逐行执行函数中的代码
    
  •  4.将新建的对象返回
    
实现通过构造函数创建对象:
  function Person(name, age) {
        this.name = name;
        this.age = age;
        this.sayName = function () {
            console.log(this.name)
        }
    }

    let person1 = new Person('张三', 23);
    let person2 = new Person('李四', 23);
    console.log(person1, person2)

说明:

通过此种方式创建的对象,都有独立的类型,不再是object,而是与构造函数有关

  function Person(name, age) {
        this.name = name;
        this.age = age;
        this.sayName = function () {
            console.log(this.name)
        }
    }

    let person1 = new Person('张三', 23);
    let person2 = new Person('李四', 23);
    console.log(person1, person2) 
    function Person2(name, age) {
        this.name = name;
        this.age = age;
        this.sayName = function () {
            console.log(this.name)
        }
    }
    let person3 = new Person2('李四', 23); 
    //  判断 person3 是 Person2 / Person 创建的
    console.log(person3 instanceof Person)
    console.log(person2 instanceof Person)
    console.log(person3 instanceof Person2)

由于person3是通过Person2构造函数创建的,所以 console.log(person3 instanceof Person)输出为false,console.log(person3 instanceof Person2)输出为true;

5.原型:

1.概述:

  •    我们创建的每一个函数,解析器都会向函数中添加一个属性prototype,这个属性对应着一个对象,这个对象就是我们所谓的原型对象,即显式原型,
    
  •    原型对象就相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象,我们可以将对象中共有的内容,统一设置到原型对象中。
    
  •    普通函数调用prototype没有任何作用,当函数以构造函数的形式调用时,它所创建的对象中都会有一个隐含的属性,指向该构造函数的原型对象,我们可以通过__proto__(隐式原型)来访问该属性。
    

2.案例解析:

  //创建构造函数
  function Person(name, age) {
        this.name = name;
        this.age = age;
        this.sayName = function () {
            console.log(this.name)
        }
    }

    //将属性 或者 函数 存在原型中  共享的
    Person.prototype.xxx = "我是测试数据";
    Person.prototype.showInfo = function () {
        console.log(this.name, "我是原型中的方法")
    } 
    let person1 = new Person('张三', 23);
    let person2 = new Person('李四', 23);
    console.log(person1, person2);
     

    //创建构造函数
  function Person(name, age) {
        this.name = name;
        this.age = age;
        this.sayName = function () {
            console.log(this.name)
        }
    }

    //将属性 或者 函数 存在原型中  共享的
    Person.prototype.xxx = "我是测试数据";
    Person.prototype.showInfo = function () {
        console.log(this.name, "我是原型中的方法")
    } 
    let person1 = new Person('张三', 23);
    let person2 = new Person('李四', 23);
   //person1 访问xxx 先从person1对象自身寻找xxx属性
    //没有的 就去原型中找
    // 在没有  就通过父类找
    console.log(person1.xxx, person2.xxx)
    person2.showInfo();
      
          ![](https://cdn.nlark.com/yuque/0/2024/png/45532635/1731664800063-21502bd1-ec70-43a7-8239-67f169e58805.png)

因为在Person类的原型对象中添加了属性xxx和showinfo方法,而person1和person2作为它的实例对象,在访问时,由于从自身无法获取到,就向上在共享的原型对象中访问到了属性xxx和方法showinfo;

  //创建构造函数
  function Person(name, age) {
        this.name = name;
        this.age = age;
        this.sayName = function () {
            console.log(this.name)
        }
    }

    //将属性 或者 函数 存在原型中  共享的
    Person.prototype.xxx = "我是测试数据";
    Person.prototype.showInfo = function () {
        console.log(this.name, "我是原型中的方法")
    } 
    let person1 = new Person('张三', 23);
    let person2 = new Person('李四', 23);
     //使用 in 检查对象中是否 含有某个属性  有  true 没有 false
     console.log('name' in person1);
     console.log('xxx' in person1);

    console.log(person1.hasOwnProperty('name'))
    //true  xxx不是person1 自身的数据
    console.log(person1.hasOwnProperty('xxx'))
    console.log(person1.__proto__.hasOwnProperty('xxx'))
       

由于xxx属性是原型对象中的属性,而不是person1自身的属性,所以测试结果为false;

6.继承:

1.方式:

  • ** * 1.原型链继承**
    
  • **     * 2.构造方法继承**
    
  • **     * 3.组合继承**
    
  • **     * 4.原型式继承**
    
  • **     * 5.寄生继承**
    
  • **     * 6.寄生组合继承**
    

2.原型链继承:

实现:

 function SupperType() {
        this.supProp = "我是父类型中的属性"
    }

    //给父类的原型添加方法
    SupperType.prototype.showSupperProp = function () {
        console.log(this.supProp);
    }

    //创建子类原型
    function SubType() {
        this.subType = "我是子类的属性"
    }

    //继承  让子类的原型属性 指向 父类类型
    SubType.prototype = new SupperType();
    //将子类的原型的构造方法属性设置为子类自己
    SubType.prototype.constructor = SubType;
    //子类的原型对象添加方法
    SubType.prototype.showSubProp = function () {
        console.log(this.subType)
    }
    let subType = new SubType();
    //调用父类的原型中的方法
    subType.showSupperProp();
    //调用子类自己的原型中的方法
    subType.showSubProp();
    //获取父类中的属性
    console.log(subType.supProp)
    console.log(subType)
   

说明:

 上述代码中是通过将子类的原型对象指向父类对象来实现的,在子类访问父类属性或方法时,先在自身找,如果找不到,再在子类的原型对象中找,要是还找不到,就在父类对象中找,父类对象属性中也没有,就在父类的原型对象中找,就这样以引用链的形式查找,进而实现了继承;

存在问题:

  •    1.不能为父类传参;
    
  •    2.原型链继承多个实例的引用类型属性,且由于指向是相同的,一个实例修改了原型属性,另一个实例的原型属性也会被影响;
    

3.构造函数继承:

实现:

  //1.定义父类的构造函数
    function SupperType(name) {
        this.name = name;
        this.showSupperName = function (){
            console.log(this.name,"这是方法")
        }
    }
    SupperType.prototype.xxx= "父类原型属性";
    //2.创建子类构造函数
    function SubType(name,age) {
        //在子类中 调用call 继承父类中的属性与方法
        SupperType.call(this,name);
        this.age = age;
    }
    SubType.prototype.showInfo = function () {
        console.log(this.name,this.age)
    }

    let subType = new SubType('张三',20);
    subType.showSupperName();
    //子类原型中的方法
    subType.showInfo();
    //通过子类实例 调用父类原型中的属性
    console.log(subType.xxx);

    console.log(subType)

说明:

通过此方式实现继承与原型链的方式不同,此方式更像是把父类的属性和方法复制到子类中,虽然最后看似在调用父类的属性和方法,但其实是调用本类的属性和方法,因此通过此方式并没有建立完全的继承关系,所以subType的父类是Object,而非SupperType,因此子类SubType是无法访问到父类SupperType的原型对象中的属性和方法的;

存在问题:

 通过构造函数实现继承关系,解决了原型链继承的问题.但又出现了下面的新问题:
  •   无法访问父类原型对象中的方法或属性;
    

4.组合继承:

实现:

<script>
     //1.定义父类的构造函数
     function SupperType(name) {
         this.name = name;
         this.showSupperName = function (){
             console.log(this.name,"这是父类方法")
         }
     }
     SupperType.prototype.xxx= "父类原型属性";
     //2.创建子类构造函数
     function SubType(name,age) {
         //在子类中 调用call 继承父类中的属性与方法
         SupperType.call(this,name);
         this.age = age;
     }
     SubType.prototype=Object.create(new SupperType());
      SubType.prototype.constructor=SubType;
     SubType.prototype.showinfo=function(){
         console.log(this.name,this.age,"子类方法")
     }
      let sub=new SubType("张三",22);
       sub.showSupperName();
       sub.showinfo();
     console.log(sub.xxx);
     console.log(sub);
</script>   

说明:

此方式结合了引用链继承和构造方法继承的特点,解决了它们自身存在的问题

存在问题:

虽然组合继承解决了引用链继承和构造方法继承所存在的问题,但有出现了新的问题;

  • 父类中的实例属性和方法在子类实例中又在子类原型中,内存开销变大;
    

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

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

相关文章

软件安全检测报告:如何全面评估企业级办公软件安全性?

软件安全检测报告对软件的整体安全性进行了全面而细致的评估与呈现&#xff0c;既揭露了软件防范非法入侵的能力&#xff0c;同时也为软件的开发与优化提供了关键性的参考依据。 引言情况 撰写报告旨在明确呈现软件的安全性状态&#xff0c;并为后续的改进工作提供依据。在阐…

PySide6 GUI 学习笔记——常用类及控件使用方法(常用类颜色常量QColorConstants)

文章目录 一、概述二、颜色常量表标准 Qt 颜色SVG 颜色&#xff08;部分&#xff09; 三、Python 代码示例四、代码说明五、版本兼容性六、延伸阅读 一、概述 QColorConstants 是 Qt for Python 提供的一个预定义颜色常量集合&#xff0c;包含标准Qt颜色和SVG规范颜色。这些常…

大模型技术演进与应用场景深度解析

摘要 本文系统梳理了当前主流大模型的技术架构演进路径,通过对比分析GPT、BERT等典型模型的创新突破,揭示大模型在参数规模、训练范式、应用适配等方面的核心差异。结合医疗、金融、教育等八大行业的实践案例,深入探讨大模型落地的技术挑战与解决方案,为从业者提供体系化的…

鸿蒙5.0项目开发——鸿蒙天气项目的实现(主页1)

【高心星出品】 文章目录 页面效果&#xff1a;页面功能&#xff1a;页面执行流程&#xff1a;1. 页面初始化阶段2. 定位获取阶段3. 天气数据加载阶段 这个页面是整个天气应用的核心&#xff0c;集成了天气查询、定位、搜索等主要功能&#xff0c;提供了完整的天气信息服务。 …

【ESP32】ESP-IDF开发 | 低功耗蓝牙开发 | GATT规范和ATT属性协议 + 电池电量服务例程

1. 简介 低功耗蓝牙中最为核心的部分当属 GATT&#xff08;Generic Attribute Profile&#xff09;&#xff0c;全称通用属性配置文件。而 GATT 又是建立在 ATT 协议&#xff08;属性协议&#xff09;的基础之上&#xff0c;为 ATT 协议传输和存储的数据建立了通用操作和框架。…

2025 年九江市第二十三届中职学校技能大赛 (网络安全)赛项竞赛样题

2025 年九江市第二十三届中职学校技能大赛 &#xff08;网络安全&#xff09;赛项竞赛样题 &#xff08;二&#xff09;A 模块基础设施设置/安全加固&#xff08;200 分&#xff09;A-1 任务一登录安全加固&#xff08;Windows,Linux&#xff09;A-2 任务二 Nginx 安全策略&…

【记录】Windows|竖屏怎么调整分辨率使横竖双屏互动鼠标丝滑

本文版本&#xff1a;Windows11&#xff0c;记录一下&#xff0c;我最后调整的比较舒适的分辨率是800*1280。 文章目录 第一步 回到桌面第二步 右键桌面第三步 设置横屏为主显示器第四步 调整分辨率使之符合你的需求第五步 勾选轻松在显示器之间移动光标第六步 拖动屏幕符合物理…

开源项目实战学习之YOLO11:12.2 ultralytics-models-sam-decoders.py源码分析

👉 点击关注不迷路 👉 点击关注不迷路 👉 另外,前些天发现了一个巨牛的AI人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。感兴趣的可以点击相关跳转链接。 点击跳转到网站。 ultralytics-models-sam 1.sam-modules-decoders.pyblocks.py: 定义模型中的各…

数据结构*优先级队列(堆)

什么是优先级队列(堆) 优先级队列一般通过堆&#xff08;Heap&#xff09;这种数据结构来实现&#xff0c;堆是一种特殊的完全二叉树&#xff0c;其每个节点都满足堆的性质。如下图所示就是一个堆&#xff1a; 堆的存储方式 由于堆是一棵完全二叉树&#xff0c;所以也满足二…

汽车Wafer连接器:工业设备神经网络的隐形革命者

汽车Wafer连接器正在突破传统车载场景的边界&#xff0c;以毫米级精密结构重构工业设备的连接范式。这款厚度不足3毫米的超薄连接器&#xff0c;在新能源电池模组中承载200A持续电流的同时&#xff0c;仍能保持85℃温升的稳定表现&#xff0c;其每平方厘米高达120针的触点密度&…

微信小程序:封装表格组件并引用

一、效果 封装表格组件,在父页面中展示表格组件并显示数据 二、表格组件 1、创建页面 创建一个components文件夹,专门用于存储组件的文件夹 创建Table表格组件 2、视图层 (1)表头数据 这里会从父组件中传递表头数据,这里为columns,后续会讲解数据由来 循环表头数组,…

Conda 完全指南:从环境管理到工具集成

Conda 完全指南&#xff1a;从环境管理到工具集成 在数据科学、机器学习和 Python 开发领域&#xff0c;环境管理一直是令人头疼的问题。不同项目依赖的库版本冲突、Python 解释器版本不兼容等问题频繁出现&#xff0c;而 Conda 的出现彻底解决了这些痛点。作为目前最流行的跨…

安卓中0dp和match_parent区别

安卓中的 0dp 和 match_parent 的区别&#xff1f; 第一章 前言 有段时间&#xff0c;看到同事在编写代码的时候&#xff0c;写到的是 0dp 有时候自己写代码的时候&#xff0c;编写的是 match_parent 发现有时候效果很类似。 后来通过一个需求案例&#xff0c;才发现两者有着…

信贷风控笔记4——贷前策略之额度、定价(面试准备12)

1.贷前模型的策略应用 分类&#xff1a;审批准入&#xff08;对头尾部区分度要求高&#xff09;&#xff1a;单一规则&#xff08;找lift>3的分数做规则&#xff09;&#xff1b;二维交叉&#xff1b;拒绝回捞 额度定价&#xff08;对排序性要求高&#xff09;&am…

A级、B级弱电机房数据中心建设运营汇报方案

该方案围绕A 级、B 级弱电机房数据中心建设与运营展开,依据《数据中心设计规范》等标准,施工范围涵盖 10 类机房及配套设施,采用专业化施工团队与物资调配体系,强调标签规范、线缆隐藏等细节管理。运营阶段建立三方协同运维模式,针对三级故障制定30 分钟至 1 小时响应机制…

Linux中的域名解析服务器

一、DNS&#xff08;域名系统&#xff09;详解 1. 核心功能与特点 特性说明核心作用将域名&#xff08;如 www.example.com&#xff09;转换为 IP 地址&#xff08;如 192.168.1.1&#xff09;&#xff0c;实现人类可读地址与机器可读地址的映射。端口与协议- 默认端口&#…

CycleISP: Real Image Restoration via Improved Data Synthesis通过改进数据合成实现真实图像恢复

摘要 大规模数据集的可用性极大释放了深度卷积神经网络(CNN)的潜力。然而,针对单图像去噪问题,获取真实数据集成本高昂且流程繁琐。因此,图像去噪算法主要基于合成数据开发与评估,这些数据通常通过广泛假设的加性高斯白噪声(AWGN)生成。尽管CNN在合成数据集上表现优异…

Day28 Python打卡训练营

知识点回顾&#xff1a; 1. 类的定义 2. pass占位语句 3. 类的初始化方法 4. 类的普通方法 5. 类的继承&#xff1a;属性的继承、方法的继承 作业 题目1&#xff1a;定义圆&#xff08;Circle&#xff09;类 要求&#xff1a; 1. 包含属性&#xff1a;半径 radius。 2. …

Linux之Nginx安装及配置原理篇(一)

Nginx安装及配置 前情回顾 首先针对Nginx进程模型&#xff0c;我们回顾一下它的原理机制&#xff0c;我们知道它是通过Master通过fork分发任务节点给予work节点&#xff0c;然后work节点触发了event事件&#xff0c;之后通过一个access_muttex互斥锁&#xff0c;来单线程调用我…

【Linux网络】NAT和代理服务

NAT 之前我们讨论了&#xff0c;IPv4协议中&#xff0c;IP地址数量不充足的问题。 原始报文途径路由器WAN口时&#xff0c;对报文中的源IP进行替换的过程&#xff0c;叫做NAT。 NAT技术当前解决IP地址不够用的主要手段&#xff0c;是路由器的一个重要功能&#xff1a; NAT能…