JavaScript篇.day10-面向对象,对象,构造函数,this关键字,原型

news2024/9/20 18:43:00

目录

  1. 面向对象

  1. 对象

  1. 构造函数

  1. this关键字

  1. 原型

    • 面向对象

  • 面向过程: 在开发过程中,关注过程的开发方式. 在开发时关注每一个细节,步骤和顺序.

  • 面向对象: 在开发过程中,只需要找一个对象来完成事情的开发思想

  • 对象: 在生活中,万物皆对象

  • 封装: 将完成步骤封装在对象内部

  • 属性: 对象的特征

  • 核心: ①制造一个对象, 批量生产对象; ②每个对象都有自己的属性(特征)和方法(函数,行为); ③每个对象都类似,但不相同(构造函数)

e.g:
(1)想吃饭
面向过程:
-> 所有事情自己亲力亲为
-> 考虑顺序: 烧水, 洗菜, 切菜, 炒菜...
-> 考虑细节: 切菜时,菜切的花样
面向对象:
-> 只需要到饭店去点菜 (不关注菜如何做, 找一个做饭的对象)
(2)开发选项卡
面向过程:
-> 考虑获取哪些元素? tab标签, 每一个tab标签对应的内容区域
-> 考虑给哪些元素绑定点击事件? tab标签绑定点击事件
-> 考虑点击的功能? 进行内容的切换
面向对象:
-> 找到一个能完成选项卡功能的对象, 让这个对象来完成
-> 注意: 这个对象是否存在? 存在则直接使用, 不存在则制造对象(创建对象)
制造对象:
-> 我们需要一个制造对象的机器(抽象的概念)
-> 机器的作用是: 生产一个对象(具体的概念)
-> 生产出来的对象要能够完成选项卡的功能
-> 因此, 我们只需要准备这个机器
-> 开发过程中, 只需要造机器, 由机器生产出来的一个对象来完成选项卡功能, 当开发另一个选项卡时, 不需再次制造机器, 只需要该机器再生产一个对象来完成另一个选项卡功能即可
    • 对象

对象的创建方式
  • 字面量方式,可动态添加属性和方法, 但无法批量生产对象

  • Object 内置构造函数的方式 可动态添加属性和方法, 但添加属性和方法时无法批量添加

  • 通过工厂函数的方式

  • 自定义构造函数的方式

      // 创建对象方式
      // 1. 通过字面量的方式   可动态添加属性和方法, 但无法批量生产对象
      var obj1 = {
        name: 'mm',
        age: 18,
        show: function () {
          console.log('i am obj1---show')
        },
      }
      var obj2 = {
        name: 'tt',
        age: 20,
        show: function () {
          console.log('i am obj2---show')
        },
      }
      // 可动态添加属性和方法
      obj1.sex = '女'
      obj2.sex = '男'
      obj1.run = function () {
        console.log('i can run!!!!!---obj1')
      }
      obj2.run = function () {
        console.log('i can run!!!!!---obj2')
      }

      // 2. Object 内置构造函数的方式  可动态添加属性和方法, 但添加属性和方法时无法批量添加
      var obj3 = new Object()
      obj3.name = 'qq'
      obj3.age = 21
      obj3.show = function () {
        console.log('i am obj3---show')
      }

      // 3. 通过工厂函数的方式
      // (1) 创建一个工厂函数
      function factory(name, age) {
        // 手动创建对象
        var obj4 = {}
        obj4.name = name
        obj4.age = age
        obj4.show = function () {
          console.log('i am obj4---show')
        }
        // 手动返回对象
        return obj4
      }
      // (2) 使用工厂函数创建对象
      var obj5 = factory("aa", 18)
      var obj6 = factory("zz", 19)
      var obj7 = new Factory()
      console.log('5---',obj5);
      console.log('6---',obj6);
      console.log(obj5 == obj6);  //false  两个对象类似但不相同

      // 4. 自定义构造函数的方式
      // (1) 自定义函数就是在造机器
      // (2) 构造函数会自动的创建并返回对象,无需return(创建对象时,需要与new关键字配合使用)
      // (3) 手动添加属性和方法
      function Factory(name,age){
        // 手动向对象中添加属性和方法
        // this指当前对象, 动态变化, 指向调用者
        this.name = name
        this.age = age
        this.show = function(){
          console.log('i am' +  obj + '---show');
        }
      }
      // 创建对象   new 构造函数名()   首字母大写,为了区分构造函数
      var obj7 = new Factory("ww",17)
      var obj8 = new Factory("ss",16)
      console.log('7---',obj7);
      console.log('8---',obj8);
      // 访问属性
      console.log(obj7.name); // ww
创建对象方法比较

将方法写在构造函数内部:

将方法写在构造函数的原型上:

    • 构造函数

构造函数
  • 能批量生产对象

  • 可像函数一样传递参数, 可以为每一个对象添加不同的内容

  • 当需要完成一个功能时, 造一个构造函数, 利用构造函数来创建完成功能的对象

  • '机器'即为构造函数, 属性就直接写在构造函数内部,方法写在构造函数的原型上(避免每创建一次对象就创建一次相同的函数,造成空间的浪费)开发过程,即为造'机器'的过程, 就是面向对象的封装过程

      // 创建对象 Date是一个制造机器, new Date()创建一个对象, 使用对象来获取年份,月份等
      var time1 = new Date()
      var time2 = new Date()
      console.log(time1 == time2);  //false    每个对象类似,但不相同
      var point = { 
        x:10,
        y: 20,
        function(){
          console.log('point---function');
        }
      }
      console.log(point.x);
普通函数和自定义构造函数的比较
  • 普通函数: 使用时函数调用[函数名()], 函数名小驼峰式命名规则

  • 自定义构造函数: 用来创建对象[new 函数名()],使用时必须与new连用,否则不能自动创建对象,函数名大驼峰式命名规则(所有单词首字母大写, 与普通函数做区分)

使用构造函数的问题
  • 问题: 如果将方法写在构造函数的内部, 在每次创建对象时,都会创建函数,造成空间浪费

  • 解决: 方法只创建一次, 供所有对象使用, 使用原型

      // 自定义Dog的构造函数
      function Dog(name, type) {
        // 定义属性
        this.name = name
        this.type = type
        // 定义方法
        this.print = function () {
            console.log('dogName: ', this.name, ', type:', this.type)
        }
      }
      // 创建对象(生产实例)
      var dog1 = new Dog('小白', '萨摩耶')
      var dog2 = new Dog('小黑', '二哈')
      console.log('dog1: ',dog1, 'dog2: ', dog2);
      // 调用print方法
      dog1.print()
      dog2.print()
      // dog1和dog2不是相同的对象
      console.log(dog1 === dog2); //false
      // dog1和dog2的print方法不同, 是两个函数
      console.log(dog1.print === dog2.print); //false
      /*   dog1 第一次使用new Dog创建的对象 会将this指向dog1, 将构造函数中的代码全部执行一遍(在dog1上添加name和type属性, 同时也在dog1上添加print方法,创建一个函数)
            dog2 第二次使用new Dog创建的对象 会将this指向dog2, 将构造函数中的代码全部执行一遍(在dog2上添加name和type属性, 同时也在dog1上添加print方法,创建一个函数)     */ 
    • this关键字

this指向问题

  • 普通函数函数中,this指向函数调用者

  • this指向window对象(全局)

  • 箭头函数中,this指向函数定义时this的指向(通常函数定义时指向的是window)

      // this指向问题
      // 1. this指向当前调用者
      var obj9 = {
        a: 10,
        b: 20,
        show: function(){
          console.log(this);   // this指向obj9
          return this.a   
        }
      }
      console.log(obj9.show());  //10

      // 2. this指向 Window 对象 (当前调用者为window)
      var a = 30  //全局变量
      var show1 = obj9.show  //不加() 获取到show函数
      console.log(show1);   
      show1()   //等价于window.show(), show中的this指向全局的Window对象, 返回的是全局变量a=30的值
改变this指向
  • call() 方法 fun.call(thisArg, arg1, arg2, ...) 调用一个对象(可调用函数)

  • apply()方法 fun.apply(thisArg, [argsArray]) 可调用函数, 可改变函数的 this 指向, 参数必须为数组形式 [argsArray]

  • bind()方法 fun.bind(thisArg, arg1, arg2, ...)不会调用函数, 可以改变函数内部this指向

    • 原型

原型
  • 在js中的每一个函数都有一个属性 prototype(原型对象),是一个对象

  • 每个对象上都有一个 __proto__(对象原型)属性, 指向所属构造函数的prototype

  • 当访问对象的属性或方法时, 首先在自身查找, 若没有,则会在 __proto__上查找

  • 在原型上添加方法, 在内存中只会创建一个方法, 专门供对象使用

  • 构造函数constructor: 本身也是函数,故也有prototype属性

/*        在js内部,所有的object对象数据类型都属于内置构造函数Object
          在js内部,所有函数都属于内置构造函数Function对象    */
 /*  问题1: cat对象上的__proto__指向谁?
             -> cat 所属的构造函数是 Cat
             -> cat.__proto__ 指向 Cat.prototype

      问题2: Cat.prototype上的__proto__指向谁?
             -> Cat.prototype 是一个对象, 也有__proto__属性
             -> Cat.prototype所属的构造函数是Object
             -> Cat.prototype.__proto__指向 Object.prototype

      问题3: Cat的__proto__指向谁? 
             -> Cat是一个自定义构造函数, 本事也是一个对象, 故也有__proto__属性
             -> Cat 的所属构造函数是 Function  (在js内部,所有函数都属于内置构造函数Function对象)
             -> Cat.__ptoto__ 指向 Function.prototype

      问题4: Object.prototype上的__proto__指向谁?
             -> Object.prototype 是一个对象, 也有__proto__属性
             -> Object.prototype在js中是顶级原型对象,不存在__proto__对象原型
             -> Object.prototype.__proto__ 指向 null

      问题5: Object上的__proto__指向谁?
             -> Object对象有__proto__属性
             -> Object是一个内置构造函数, 故所属构造函数是 Function
             -> Object.__proto__指向 Function.prototype


      问题6: Function.prototype上的__proto__指向谁?
             -> Function.prototype 是一个对象, 也有__proto__属性
             -> Function.prototype 所属构造函数是 Object
             -> Function.prototype.__proto__ 指向 Object.prototype

      问题7: Function上的__proto__指向谁?
             -> Function 是一个对象, 也有__proto__属性
             -> Function 是一个内置构造函数, 所属的构造函数就是Function 
             -> Function.__proto__ 指向 Function.prototype
  */
     function Cat(name, type) {
        // 定义属性
        this.name = name
        this.type = type
      }
      // Cat.prototype会得到一个对象, 是Cat构造函数的原型
      Cat.prototype.print = function(){
        console.log('CatName: ', this.name, ', Cattype:', this.type)
      }
      var cat1 = new Cat('小白', '小橘猫')
      var cat2 = new Cat('小黑', '英短')
      console.log(cat1, cat2);
      console.log(cat1 === cat2); //false
      console.log(cat1.print === cat2.print); //true

      console.log(Cat.prototype); //{print: ƒ, constructor: ƒ}
      // 问题1: cat.__proto__ 指向 Cat.prototype
      console.log(cat1.__proto__ ) //{print: ƒ, constructor: ƒ}
      console.log(cat1.__proto__ === Cat.prototype);  //true
      // 问题2: Cat.prototype.__proto__指向 Object.prototype
      console.log(Cat.prototype.__proto__ );  //  {constructor: ƒ, __defineGetter__: ƒ, …}
      console.log(Cat.prototype.__proto__ === Object.prototype);  //true
      // 问题3: Cat.__ptoto__ 指向 Function.prototype
      console.log(Cat.__proto__);  //ƒ () { [native code] }
      console.log(Cat.__proto__ === Function.prototype);  //true
      // 问题4: Object.prototype.__proto__ 指向 null
      console.log(Object.prototype.__proto__);  // null
      // 问题5: Object.__proto__指向 Function.prototype
      console.log(Object.__proto__ );  // ƒ () { [native code] }
      console.log(Object.__proto__ === Function.prototype);  // true
      // 问题6: Function.prototype.__proto__ 指向 Object.prototype
      console.log(Function.prototype.__proto__);  //{constructor: ƒ, __defineGetter__: ƒ, …}
      console.log(Function.prototype.__proto__ === Object.prototype);  //true
      // 问题7: Function.__proto__ 指向 Object.prototype
      console.log(Function.__proto__ );  //  ƒ () { [native code] }
      console.log(Function.__proto__ === Function.prototype);  //true

      console.log( function(){} instanceof Object);  //true  函数也是一个对象
      console.log(Object instanceof Object);  //true  函数也是一个对象
原型链

原型链是用__proto__属性穿起来的链状结构

原型上的属性
      var obj1 = {
        a: 100,
        b: 200,
        getA :function() {
          return this.a
        },
      }
      var obj2 = {
        a: 300,
        b: 400,
        getA :function() {
          return this.a
        },
      }
      console.log(obj1.getA());  //100
      console.log(obj1.getA.apply(obj2)); //300 使得obj1.getA中的this指向obj2 

      // 添加原型上的属性
      Object.prototype.c = 600  

      // hasOwnProperty() 检测是否属于自身属性
      console.log(obj1.hasOwnProperty('a'));  // true
      console.log(obj1.hasOwnProperty('c'));  // false   c属性在原型上,不属于自身属性

      // 遍历对象  
      // 可获取到原型上的属性值
      for(var key in obj1){
        console.log(obj1[key]);   // 100 200  ƒ(){return this.a } 600 
      }
      // Object.keys() 无法获取到原型上的属性
      console.log(Object.keys(obj1));  //['a', 'b', 'getA']

PreviousNotes:

https://blog.csdn.net/qq_54379580/article/details/126464151

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

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

相关文章

Java泛型上界与泛型方法的应用 | 如何通过泛型类获取任意类型的三个数的最大值?

目录 一、引言 二、泛型上界 1、什么是泛型的上界 2、泛型上界的语法 三、泛型方法 1、泛型方法的语法 2、泛型方法的类型推导 三、编程分析 1、MyCompare泛型类 2、泛型方法实现 四、总结 一、引言 初学Java时,同学们基本都会遇到这样一个基础编程题&am…

平面设计师去哪里找素材?

5个平面设计素材网站,赶紧收藏! 1、菜鸟图库 https://www.sucai999.com/?vNTYwNDUx ​ 站内平面海报、UI设计、电商淘宝、免抠、高清图片、样机模板等素材非常齐全。还有在线抠图、CDR版本转换功能,能有效的为设计师节省找素材时间&#x…

MySQL查询训练题1

表信息: dept表和emp表 bonus表和salgrade表 练习题: 1、选择部门30中的所有员工; select * from Emp where DEPTNO30;2、列出所有办事员(CLERK)的姓名,编号和部门编号; select ENAME 姓名,EMPNO 编号,DEPTNO 部门…

【vue2中使用axios和插槽】一.组件的生命周期;二.vue2中使用axios;三.插槽

目录 一.组件的生命周期 1.组件的生命周期经历的阶段: (1)创建阶段:beforeCreate、created、beforeMount、mounted (2)运行阶段:beforeUpdate、update (3)销毁阶段&a…

C++ 学习 Day.10(标准模板库简介)

标准模板库: 简单地说,标准模板库(STL)是一组模板类和函数,向程序员提供了: • 用于存储信息的容器; • 用于访问容器存储的信息的迭代器; • 用于操作容器内容的算法。 关于STL可见…

Git学习和使用

目录:Git概念和知识Git的四个工作区域和工作流程Git 的四个工作区域Git 的工作流程git文件状态常用操作进阶操作单个本地库绑定多远程仓库方案Git概念和知识 Git的四个工作区域和工作流程 Git 的四个工作区域 Remote:远程仓库 位于托管代码的服务器&a…

【语义分割】语义分割综述文章

目录:语义分割一、什么是语义分割二、什么是图像中的语义信息?三、语义分割中的上下文信息四、语义分割方法五、语义分割神经网络六、目前比较经典的网络七、评价指标一、什么是语义分割 语义分割,也称为像素级分类问题,其输出和…

如何远程访问别人的MySQL数据库

1、 如何远程访问别人的MySQL数据库 - curryzwy - 博客园 (cnblogs.com)https://www.cnblogs.com/curryzwy/p/15730485.html 2、 mysql——同一局域网如何共同访问一台电脑的数据库(胎教级教学)_七月星辰的博客-CSDN博客_两台电脑共用一个mysql数据库…

1803. 统计异或值在范围内的数对有多少

解法一:字典树 前置知识:字典树 字典树是一种实现字符串快速检索的多叉树结构。 例如:给定字符串集合[cab, cos, car, cat], 我们现在需要判断cat是否存在于字符串集合中。 字典树代码: static int[][] trie new int[N][26]; …

AcWing 1221. 四平方和(二分或哈希)

一、题目描述 二、思路分析 先从时间复杂度的角度入手,这道题的数据范围是106,因此我们的时间复杂度要控制在O(n)O(n)O(n)或者O(nlogn)O(nlogn)O(nlogn)。 对于abcd中的任何一个元素,必定是小于n\sqrt nn​的。 我们的一个思路就是去枚举&…

如何选择用 .net Framework 或 .net core

小米问: 给你一个项目,如何选择用 netframework 或 netcore?如何选择服务器? 怎么去考虑? 咋回答呢 答: 不要考虑.net framework 除非极其特殊的情况 比如目标主机系统版本较低 服务器自然是linux好&a…

2023年考证时间一览表

2022年已经成为历史,在疫情背景全面开放下给大家整理了2023年全年的考试时间以及报名时间新鲜出炉,了解清楚,为2023年提前做好规划! 1月份 2022年下半年中小学教师资格考试面试 报名时间:2022年12月9日-12日 考试时间…

大数据:Hive视图和索引

一、视图 1.1 简介 Hive 中的视图和 RDBMS 中视图的概念一致,都是一组数据的逻辑表示,本质上就是一条 SELECT 语句的结果集。视图是纯粹的逻辑对象,没有关联的存储 (Hive 3.0.0 引入的物化视图除外),当查询引用视图时&#xff0…

【自学C++】Windows安装C++语言开发环境

Windows安装C语言开发环境 Windows安装C语言开发环境教程 C 的开发环境可以直接使用 C 语言 的开发环境, 同时,Windows 本身就自带 C 语言的运行环境,因此,为了开发 C 语言,我们只需要安装一个 C 语言的开发工具即可…

第03讲:HTTP操作之ElasticSearch文档操作

3.1.2、文档操作 实验1:创建文档 索引已经创建好了,接下来我们来创建文档,并添加数据。这里的文档可以类比为关系型数据库中的表数据,添加的数据格式为 JSON 格式 在 Postman 中,向 ES 服务器发 POST 请求 :http://1…

【Kafka】Java实现数据的生产和消费

【Kafka】Java实现数据的生产和消费 Kafka介绍 Kafka 是由 Linkedin 公司开发的,它是一个分布式的,支持多分区、多副本,基于 Zookeeper 的分布式消息流平台,它同时也是一款开源的基于发布订阅模式的消息引擎系统。 Kafka 有如下…

【LeetCode】1803. 统计异或值在范围内的数对有多少

1803. 统计异或值在范围内的数对有多少 题目描述 给你一个整数数组 nums &#xff08;下标 从 0 开始 计数&#xff09;以及两个整数&#xff1a;low 和 high &#xff0c;请返回 漂亮数对 的数目。 漂亮数对 是一个形如 (i, j) 的数对&#xff0c;其中 0 < i < j <…

阻塞式队列

文章目录一、阻塞队列阻塞队列的概念阻塞队列相关类和方法生产者消费者模型二、自定义实现阻塞队列自定义实现循环队列自定义实现阻塞队列生产者消费者模型体验一、阻塞队列 阻塞队列的概念 队列我们并不默认&#xff0c;一提起队列&#xff0c;我们立马就能想到 "先进先…

一条 update 语句的执行过程

1.一条 update 语句的执行流程 一条更新语句&#xff0c;其实是增&#xff0c;删&#xff0c;查的综合体&#xff0c;查询语句需要经过的流程&#xff0c;更新语句全部需要执行一次&#xff0c;因为更新之前必须要先拿到&#xff08;查询&#xff09;需要更新的数据。 Buffer…

低代码平台组件间通信方案复盘

背景介绍3年前我开发了一款零代码搭建平台 H5-Dooring, 主要目的是想用更低的成本, 更快的效率, 上线 web 页面(其实是不想写重复的代码了,写麻了). 好在陆陆续续折腾了3年, 目前已经可以满足基本的页面设计和搭建能力, 并能快速上线页面.之前也在社区分享了很多低代码和零代码…