【JS笔记】JavaScript语法 《基础+重点》 知识内容,快速上手(六)

面向对象OOP

  • 首先,我们要明确,面向对象不是语法,是一个思想,是一种 编程模式
  • 面向: 面(脸),向(朝着)
  • 面向过程: 脸朝着过程 =》 关注着过程的编程模式
  • 面向对象: 脸朝着对象 =》 关注着对象的编程模式
  • 实现一个效果
    • 在面向过程的时候,我们要关注每一个元素,每一个元素之间的关系,顺序,。。。
    • 在面向对象的时候,我们要关注的就是找到一个对象来帮我做这个事情,我等待结果
  • 例子 🌰: 我要吃面条
    • 面向过程
      • 用多少面粉
      • 用多少水
      • 怎么和面
      • 怎么切面条
      • 做开水
      • 煮面
      • 吃面
    • 面向对象
      • 找到一个面馆
      • 叫一碗面
      • 等着吃
    • 面向对象就是对面向过程的封装
  • 我们以前的编程思想是,每一个功能,都按照需求一步一步的逐步完成
  • 我们以后的编程思想是,每一个功能,都先创造一个 面馆,这个 面馆 能帮我们作出一个 面(完成这个功能的对象),然后用 面馆 创造出一个 ,我们只要等到结果就好了

面向对象的编程语言 c++ java js python php 大前端 安卓(java) iOS(swift oc) js跨端框架

面向过程编程语言 c

面向对象的三大特点

封装、继承、多态

封装函数 封装对象(属性和方法)

Math.random new Array a.push

创建对象的方式

  • 因为面向对象就是一个找到对象的过程
  • 所以我们先要了解如何创建一个对象

调用系统内置的构造函数创建对象

  • js 给我们内置了一个 Object 构造函数

  • 这个构造函数就是用来创造对象的

  • 当 构造函数 和 new 关键字连用的时候,就可以为我们创造出一个对象

  • 因为 js 是一个动态的语言,那么我们就可以动态的向对象中添加成员了

    // 就能得到一个空对象
    var o1 = new Object() // 正常操作对象
    o1.name = 'Jack'
    o1.age = 18
    o1.gender = '男'
    

字面量的方式创建一个对象

  • 直接使用字面量的形式,也就是直接写 {}

  • 可以在写的时候就添加好成员,也可以动态的添加

    // 字面量方式创建对象
    var o1 = {name: 'Jack',age: 18,gender: '男'
    }// 再来一个
    var o2 = {}
    o2.name = 'Rose'
    o2.age = 20
    o2.gender = '女'
    

使用工厂函数的方式创建对象

  • 先书写一个工厂函数

  • 这个工厂函数里面可以创造出一个对象,并且给对象添加一些属性,还能把对象返回

  • 使用这个工厂函数创造对象

    // 1. 先创建一个工厂函数
    function createObj() {// 手动创建一个对象var obj = new Object()// 手动的向对象中添加成员obj.name = 'Jack'obj.age = 18obj.gender = '男'// 手动返回一个对象return obj
    }// 2. 使用这个工厂函数创建对象
    var o1 = createObj()
    var o2 = createObj()
    

使用自定义构造函数创建对象

  • 工厂函数需要经历三个步骤

    • 手动创建对象
    • 手动添加成员
    • 手动返回对象
  • 构造函数会比工厂函数简单一下

    • 自动创建对象
    • 手动添加成员(属性和方法)
    • 自动返回对象
  • 先书写一个构造函数

  • 在构造函数内向对象添加一些成员

  • 使用这个构造函数创造一个对象(和 new 连用)

  • 构造函数可以创建对象,并且创建一个带有属性和方法的对象

  • 面向对象就是要想办法找到一个有属性和方法的对象

  • 面向对象就是我们自己制造 构造函数 的过程

    // 1. 先创造一个构造函数
    function Person(name, gender) {this.age = 18this.name = namethis.gender = gender
    }// 2. 使用构造函数创建对象
    var p1 = new Person('Jack', 'man')
    var p2 = new Person('Rose', 'woman')
    

构造函数详解

  • 我们了解了对象的创建方式
  • 我们的面向对象就是要么能直接得到一个对象
  • 要么就弄出一个能创造对象的东西,我们自己创造对象
  • 我们的构造函数就能创造对象,所以接下来我们就详细聊聊 构造函数

构造函数的基本使用

  • 和普通函数一样,只不过 调用的时候要和 new 连用,不然就是一个普通函数调用

    function Person() {}
    var o1 = new Person()  // 能得到一个空对象
    var o2 = Person()      // 什么也得不到,这个就是普通函数调用
    
    • 注意: 不写 new 的时候就是普通函数调用,没有创造对象的能力
  • 首字母大写

    function person() {}
    var o1 = new person() // 能得到一个对象function Person() {}
    var o2 = new Person() // 能得到一个对象
    
    • 注意: 首字母不大写,只要和 new 连用,就有创造对象的能力
  • 当调用的时候如果不需要传递参数可以不写 (),建议都写上

    function Person() {}
    var o1 = new Person()  // 能得到一个空对象
    var o2 = new Person    // 能得到一个空对象 
    
    • 注意: 如果不需要传递参数,那么可以不写 (),如果传递参数就必须写
  • 构造函数内部的 this,由于和 new 连用的关系,是指向当前实例对象的

    function Person() {console.log(this)
    }
    var o1 = new Person()  // 本次调用的时候,this => o1
    var o2 = new Person()  // 本次调用的时候,this => o2
    
    • 注意: 每次 new 的时候,函数内部的 this 都是指向当前这次的实例化对象
  • 因为构造函数会自动返回一个对象,所以构造函数内部不要写 return

    • 你如果 return 一个基本数据类型,那么写了没有意义
    • 如果你 return 一个引用数据类型,那么构造函数本身的意义就没有了

使用构造函数创建一个对象

  • 我们在使用构造函数的时候,可以通过一些代码和内容来向当前的对象中添加一些内容

    function Person() {this.name = 'Jack'this.age = 18
    }var o1 = new Person()
    var o2 = new Person()
    
    • 我们得到的两个对象里面都有自己的成员 name 和 age
  • 我们在写构造函数的时候,是不是也可以添加一些方法进去呢?

    function Person() {this.name = 'Jack'this.age = 18this.sayHi = function () {console.log('hello constructor')}
    }var o1 = new Person()
    var o2 = new Person()
    
    • 显然是可以的,我们的到的两个对象中都有 sayHi 这个函数
    • 也都可以正常调用
  • 但是这样好不好呢?缺点在哪里?

    function Person() {this.name = 'Jack'this.age = 18this.sayHi = function () {console.log('hello constructor')}
    }// 第一次 new 的时候, Person 这个函数要执行一遍
    // 执行一遍就会创造一个新的函数,并且把函数地址赋值给 this.sayHi
    var o1 = new Person()// 第二次 new 的时候, Person 这个函数要执行一遍
    // 执行一遍就会创造一个新的函数,并且把函数地址赋值给 this.sayHi
    var o2 = new Person()
    
    • 这样的话,那么我们两个对象内的 sayHi 函数就是一个代码一摸一样,功能一摸一样
    • 但是是两个空间函数,占用两个内存空间
    • 也就是说 o1.sayHi 是一个地址,o2.sayHi 是一个地址
    • 所以我们执行 console.log(o1 === o2.sayHi) 的到的结果是 false
    • 缺点: 一摸一样的函数出现了两次,占用了两个空间地址
  • 怎么解决这个问题呢?

    • 就需要用到一个东西,叫做 原型,后面讲

es6新增的类和继承

class的写法及继承JavaScript 语言中,生成实例对象的传统方法是通过构造函数。下面是一个例子

function Point(x, y) {this.x = x;this.y = y;}Point.prototype.toString = function () {return '(' + this.x + ', ' + this.y + ')';};var p = new Point(1, 2);

上面这种写法跟传统的面向对象语言(比如 C++ 和 Java)差异很大,很容易让新学习这门语言的程序员感到困惑。

定义类

ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。 基本上,ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。上面的代码用 ES6 的class改写,就是下面这样。

//定义类
class Point {constructor(x, y) {this.x = x;this.y = y;}toString() {return '(' + this.x + ', ' + this.y + ')';}}

上面代码定义了一个“类”,可以看到里面有一个constructor方法,这就是构造方法,而this关键字则代表实例对象。也就是说,ES5 的构造函数Point,对应 ES6 的Point类的构造方法 point类除了构造方法,还定义了一个toString方法。注意,定义“类”的方法的时候,前面不需要加上function这个关键字,直接把函数定义放进去了就可以了。另外,方法之间不需要逗号分隔,加了会报错。

/

point.hasOwnProperty('x') // true

point.hasOwnProperty('y') // true

ES6 的类,完全可以看作构造函数的另一种写法 class Point {// ...} typeof Point // "function"上面代码表明,类的数据类型就是函数,类本身就指向构造函数

let methodName = 'getArea';class Square {//构造函数constructor(length) {// ...}//实例方法 对象方法[methodName]() {// ...}}//实例方法 对象方法wang(){}

上面代码中,Square类的方法名getArea,是从表达式得到的。

类内部,默认就是严格模式,所以不需要使用use strict指定运行模式。只要你的代码写在类或模块之中,就只有严格模式可用。 考虑到未来所有的代码,其实都是运行在模块之中,所以 ES6 类实际上把整个语言升级到了严格模式。

constructor 方法

constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。 class Point {}// 等同于class Point { constructor() {}}上面代码中,定义了一个空的类Point,JavaScript 引擎会自动为它添加一个空的constructor方法。 constructor方法默认返回实例对象(即this

类必须使用new调用,否则会报错。这是它跟普通构造函数的一个主要区别,后者不用new也可以执行。

class Foo { constructor() { }} Foo()// TypeError: Class constructor Foo cannot be invoked without 'new'

生成类的实例对象的写法,与 ES5 完全一样,也是使用new命令。前面说过,如果忘记加上new,像函数那样调用Class,将会报错。 class Point {// ...}// 报错var point = Point(2, 3);// 正确var point = new Point(2, 3);

类不存在变量提升(hoist),这一点与 ES5 完全不同。 new Foo(); // ReferenceErrorclass Foo {}

类方法

加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。

class Foo { static classMethod() { return 'hello'; }} Foo.classMethod() // 'hello'var foo = new Foo();foo.classMethod()// TypeError: foo.classMethod is not a function

上面代码中,Foo类的classMethod方法前有static关键字,表明该方法是一个静态方法,可以直接在Foo类上调用(Foo.classMethod()),而不是在Foo类的实例上调用。如果在实例上调用静态方法,会抛出一个错误,表示不存在该方法。

继承

类的继承Class 可以通过extends关键字实现继承 这比 ES5 的通过修改原型链(在后面章节会讲解)实现继承,要清晰和方便很多。

class Point {}class ColorPoint extends Point {}

上面代码定义了一个ColorPoint类,该类通过extends关键字,继承了Point类的所有属性和方法。但是由于没有部署任何代码,所以这两个类完全一样,等于复制了一个Point类。下面,我们在ColorPoint内部加上代码。

class ColorPoint extends Point {constructor(x, y, color) {super(x, y); // 调用父类的constructor(x, y)this.color = color;}toString() {return this.color + ' ' + super.toString(); // 调用父类的toString()}}

上面代码中,constructor方法和toString方法之中,都出现了super关键字,它在这里表示父类的构造函数,用来新建父类的this对象。 ES6 要求,子类的构造函数必须执行一次super函数

子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用super方法,子类就得不到this对象。

class Point { /* ... */ }class ColorPoint extends Point {constructor() {}}let cp = new ColorPoint(); // ReferenceEr

上面代码中,ColorPoint继承了父类Point,但是它的构造函数没有调用super方法,导致新建实例时报错。

需要注意的地方是,在子类的构造函数中,只有调用super之后,才可以使用this关键字,否则会报错。这是因为子类实例的构建,是基于对父类实例加工,只有super方法才能返回父类实例

class Point {constructor(x, y) {this.x = x;this.y = y;}}class ColorPoint extends Point {constructor(x, y, color) {this.color = color; // ReferenceErrorsuper(x, y);this.color = color; // 正确}}

上面代码中,子类的constructor方法没有调用super之前,就使用this关键字,结果报错,而放在super方法之后就是正确的。

总结

  • 到了这里,我们就发现了面向对象的思想模式了

    • 当我想完成一个功能的时候
    • 先看看内置构造函数有没有能给我提供一个完成功能对象的能力
    • 如果没有,我们就自己写一个构造函数,能创造出一个完成功能的对象
    • 然后在用我们写的构造函数 new 一个对象出来,帮助我们完成功能就行了
  • 比如: tab选项卡

    • 我们要一个对象
    • 对象包含一个属性:是每一个点击的按钮
    • 对象包含一个属性:是每一个切换的盒子
    • 对象包含一个方法:是点击按钮能切换盒子的能力
    • 那么我们就需要自己写一个构造函数,要求 new 出来的对象有这些内容就好了
    • 然后在用构造函数 new 一个对象就行了

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

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

相关文章

shell脚本发布docker springboot项目示例

docker、git、Maven、jdk8安装略过。 使git pull或者git push不需要输入密码操作方法 约定: 路径:/opt/springbootdemo, 项目:springbootdemo, 打包:springbootdemo.jar, docker容器名字&#x…

Netty 代理TCP 转发集群方案

使用 Netty 自定义协议连接物联网设备,业务增大之后,势必需要使用集群方案。 #nginx负载均衡 Nginx 1.9 已经支持 TCP 代理和负载均衡,并可以通过一致性哈希算法将连接均匀的分配到所有的服务器上。 修改配置文件 http{ … } stream{ ups…

Android ImageView以及实现截图

实现效果 截图前 截图后 代码 package cn.jj.huaweiad;import android.annotation.SuppressLint; import android.graphics.Bitmap; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.view.View; import android.view.ViewGro…

硬件项目中的turn-key 是啥意思?案例应用

在硬件项目中,turn-key是指一种工程项目模式,即交钥匙工程。这种模式通常由独立的第三方软件厂商直接与芯片厂商合作,基于芯片厂商的硬件方案和协议,集成成熟的上层软件和应用,并整套提供给电子产品生产厂商。这种模式…

LLM之RAG实战(三十五)| 使用LangChain的3种query扩展来优化RAG

RAG有时无法从矢量数据库中检索到正确的文档。比如我们问如下问题: 从1980年到1990年,国际象棋的规则是什么? RAG在矢量数据库中进行相似性搜索,来查询与国际象棋规则问题相关的相关文档。然而,在某些情况下&#xff0…

Ioc容器创建 和 读取组件的测试类

A接口 package com.atguigu.Ioc_03;public interface A {void dowork(); }HappyComponent.java package com.atguigu.Ioc_03;public class HappyComponent implements A {// 默认包含无参的构造方法Overridepublic void dowork() {System.out.println("我是:…

平台介绍-搭建赛事运营平台(3)

上文介绍了品牌隔离的基本原理,就是通过不同的前端和微服务来实现。但是确实很多功能是类似的,所以从编程角度还是有些管理手段的。 前端部分:前端部分没有什么特别手段,就是两个独立的项目工程,分别维护。相同的部分复…

I.MX6ULL_Linux_驱动篇(55)linux 网络驱动

网络驱动是 linux 里面驱动三巨头之一, linux 下的网络功能非常强大,嵌入式 linux 中也常常用到网络功能。前面我们已经讲过了字符设备驱动和块设备驱动,本章我们就来学习一下linux 里面的网络设备驱动。 嵌入式网络简介 网络硬件接口 首先…

LeetCode_Java_字符串相加(题目+思路+代码)

415.字符串相加 给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和并同样以字符串形式返回。 你不能使用任何內建的用于处理大整数的库(比如 BigInteger), 也不能直接将输入的字符串转换为整数形式。 思路: 1…

如何降低 BlueNRG-LPS 的开机峰值电流

1. 前言 BlueNRG 系列存在开机瞬间会出现很大的峰值电流的现象,预计有 20ma 左右。针对此现象,经常有客户询问该峰值电流会不会导致设备工作异常?会不会导致电池使用寿命缩短(考虑到一般纽扣电池能承受的峰值电流大概在 15ma 左右…

深度剖析MySQL锁:解开数据库并发控制的神秘面纱

MySQL 锁是 MySQL 数据库管理系统中为了实现并发控制和数据一致性的机制。在多用户并发访问数据库时,锁可以确保多个事务在对同一数据进行操作时不会相互干扰,以防止数据不一致的现象发生。 一、锁分类 MySQL支持多种类型的锁,主要包括…

NGINX安装Stream模块

一.前言 Stream模块是Nginx的一个核心模块,它提供了一种处理TCP和UDP流量的方式。它可以将传入的TCP或UDP流量代理到后端服务器,实现负载均衡和反向代理的功能。它可以根据自定义的规则将流量转发到不同的后端服务器,实现高可用性和性能优化…

定时器的原理和应用

#include<reg51.h> unsigned char s[]{0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; unsigned char count0,num0; void inittimer() {TMOD0x01;//0000 0001TH0(65536-50000)/256; //定时50ms50000us 2562^8 初值向右边移动8位TL0(65536-50000)%256;ET01;//开启定…

让Unity的协程变得简单

作者简介: 高科,先后在 IBM PlatformComputing从事网格计算,淘米网,网易从事游戏服务器开发,拥有丰富的C++,go等语言开发经验,mysql,mongo,redis等数据库,设计模式和网络库开发经验,对战棋类,回合制,moba类页游,手游有丰富的架构设计和开发经验。 (谢谢…

多源统一视频融合可视指挥调度平台VMS/smarteye系统概述

系统功能 1. 集成了视频监控典型的常用功能&#xff0c;包括录像&#xff08;本地录像、云端录像&#xff08;录像计划、下载计划-无线导出&#xff09;、远程检索回放&#xff09;、实时预览&#xff08;PTZ云台操控、轮播、多屏操控等&#xff09;、地图-轨迹回放、语音对讲…

windows 下用使用api OCI_ConnectionCreate连接oracle报错 TNS:无法解析指定的连接标识符

背景&#xff0c;两台服务器系统一样&#xff0c;oracle版本一样&#xff0c;其中一台服务器在运行程序的时候报错 TNS:无法解析指定的连接标识符 但是PL/SQL可以正常连接&#xff0c;怀疑是oracle配置文件的原因 tnsnames.ora配置文件大概作用&#xff1a;是Oracle客户端的网…

实时数仓之实时数仓架构(Hudi)

目前比较流行的实时数仓架构有两类&#xff0c;其中一类是以FlinkDoris为核心的实时数仓架构方案&#xff1b;另一类是以湖仓一体架构为核心的实时数仓架构方案。本文针对FlinkHudi湖仓一体架构进行介绍&#xff0c;这套架构的特点是可以基于一套数据完全实现Lambda架构。实时数…

springboot整合nacos(配置中心)

使用com.alibaba.boot配置nacos,一定要在bootstrap.yml内配置nacos的相关配置,而不是application.yml sprinboot整合nacos官网,例如pom的依赖是(注意:需要用上nacos的账号密码必须需要nacos-config-spring-boot-starter版本是0.2.6以上,使用nacos-config-spring-boot-st…

基于 StarRocks 的风控实时特征探索和实践

背景 金融风控特征是在金融领域中用于评估和管理风险的关键指标。它们帮助金融机构识别潜在风险&#xff0c;降低损失&#xff0c;并采取措施规避风险。例如&#xff0c;用户最后一次授信提交时间就是一个重要的金融风控特征。 金融风控实时特征场景是一个典型的大数据实时业务…

【人工智能Ⅱ】实验4:Unet眼底血管图像分割

实验4&#xff1a;Unet眼底血管图像分割 一&#xff1a;实验目的与要求 1&#xff1a;掌握图像分割的含义。 2&#xff1a;掌握利用Unet建立训练模型。 3&#xff1a;掌握使用Unet进行眼底血管图像数据集的分割。 二&#xff1a;实验内容 1&#xff1a;用Unet网络完成眼底血…