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

news/2024/11/22 19:33:34/

目录

  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 = 21obj3.show = function () {console.log('i am obj3---show')}// 3. 通过工厂函数的方式// (1) 创建一个工厂函数function factory(name, age) {// 手动创建对象var obj4 = {}obj4.name = nameobj4.age = ageobj4.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 = namethis.age = agethis.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 = namethis.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指向obj9return 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 = namethis.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); //falseconsole.log(cat1.print === cat2.print); //trueconsole.log(Cat.prototype); //{print: ƒ, constructor: ƒ}// 问题1: cat.__proto__ 指向 Cat.prototypeconsole.log(cat1.__proto__ ) //{print: ƒ, constructor: ƒ}console.log(cat1.__proto__ === Cat.prototype);  //true// 问题2: Cat.prototype.__proto__指向 Object.prototypeconsole.log(Cat.prototype.__proto__ );  //  {constructor: ƒ, __defineGetter__: ƒ, …}console.log(Cat.prototype.__proto__ === Object.prototype);  //true// 问题3: Cat.__ptoto__ 指向 Function.prototypeconsole.log(Cat.__proto__);  //ƒ () { [native code] }console.log(Cat.__proto__ === Function.prototype);  //true// 问题4: Object.prototype.__proto__ 指向 nullconsole.log(Object.prototype.__proto__);  // null// 问题5: Object.__proto__指向 Function.prototypeconsole.log(Object.__proto__ );  // ƒ () { [native code] }console.log(Object.__proto__ === Function.prototype);  // true// 问题6: Function.prototype.__proto__ 指向 Object.prototypeconsole.log(Function.prototype.__proto__);  //{constructor: ƒ, __defineGetter__: ƒ, …}console.log(Function.prototype.__proto__ === Object.prototype);  //true// 问题7: Function.__proto__ 指向 Object.prototypeconsole.log(Function.__proto__ );  //  ƒ () { [native code] }console.log(Function.__proto__ === Function.prototype);  //trueconsole.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());  //100console.log(obj1.getA.apply(obj2)); //300 使得obj1.getA中的this指向obj2 // 添加原型上的属性Object.prototype.c = 600  // hasOwnProperty() 检测是否属于自身属性console.log(obj1.hasOwnProperty('a'));  // trueconsole.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.ppmy.cn/news/9638.html

相关文章

JavaWeb项目 -- 博客系统

JavaWeb项目 -- 博客系统前言:页面展示一、创建 Maven 项目二、设计数据库三、封装数据库的操作3.1 创建 DBUtil 类3.2 创建 Blog 类3.3 创建 User 类3.4 创建类 BlogDao3.5 创建类 UserDao四、导入准备好的前端代码五、实现博客列表界面5.1 约定好前后端交互接口5.…

简单又好用的财务分析工具有哪些?

什么样的财务分析工具才能算是简单又好用?是能够快速完成组合多变的财务指标运算分析;能够充分发挥企业经营健康晴雨表作用,反映企业财务健康状态;还是能够支持多维度动态分析、自助分析;或者是轻松合并账套&#xff0…

Java集合类ArrayList应用 | 如何在字符串s1中删除有在字符串s2出现的字符?

目录 一、题干 二、题解 1. 思路 ArrayList实现 2. 代码 ArrayList实现 StringBuilder实现-1 StringBuilder实现-2 三、总结 一、题干 面试的编程题: s1: "welcome to Zhejiang" s2: "come" 要求输出从字符串s1删除s2中存在的字符之后…

【Java寒假打卡】Java基础-BigDecimal

【Java寒假打卡】Java基础-BigDecimal构造方法四则运算BigDecimal的特殊方法基本数据类型包装类自动装箱与自动拆箱Integer的类型转换将数字字符串进行拆分成整数数组构造方法 package com.hfut.edu.test1;import java.math.BigDecimal;public class test3 {public static void…

Spring AOP 面向切面编程

1.AOP是什么我们之前学过 OOP 面向对象编程, 那么 AOP 是否就比 OOP 更牛逼呢? 是否也是面向过程到面向对象这种质的跨越呢? 其实不是, 它和 OOP 思想是一种互补的关系, 是对 OOP 思想的一种补充.AOP (Aspect Oriented Programming) : 面向切面编程, 它是一种思想, 它是对某一…

3台机器配置hadoop集群_Hadoop+Hbase 分布式集群架构

安装搭建Hadoop1、 配置说明本次集群搭建共三台机器,具体说明下:主机名IP说明nn01192.168.1.51DataNode、NodeManager、ResourceManager、NameNodedn01192.168.1.52DataNode、NodeManager、SecondaryNameNodedn02192.168.1.53DataNode、NodeManager2 、安…

【二分查找】有界数组中指定下标处的最大值

题目描述 给你三个正整数 n、index 和 maxSum 。你需要构造一个同时满足下述所有条件的数组 nums&#xff08;下标 从 0 开始 计数&#xff09;&#xff1a; nums.length nnums[i] 是 正整数 &#xff0c;其中 0 < i < nabs(nums[i] - nums[i1]) < 1 &#xff0c;其…

论文投稿指南——中文核心期刊推荐(生物科学)

【前言】 &#x1f680; 想发论文怎么办&#xff1f;手把手教你论文如何投稿&#xff01;那么&#xff0c;首先要搞懂投稿目标——论文期刊 &#x1f384; 在期刊论文的分布中&#xff0c;存在一种普遍现象&#xff1a;即对于某一特定的学科或专业来说&#xff0c;少数期刊所含…