美文网首页
07-JavaScript面向对象

07-JavaScript面向对象

作者: 七分之二十四 | 来源:发表于2019-05-21 11:19 被阅读0次

    JavaScript面向对象

    • 面向过程强调的是功能行为,关注的是解决问题需要哪些步骤
    • 面向对象是将功能封装进对象,强调具备了功能的对象,关注的是解决问题需要哪些对象

    面向对象的特点

    • 是一种符合人们思考习惯的思想
    • 可以将复杂的事情简单化
    • 将程序员从执行者转换成了指挥者

    创建默认对象

    • JavaScript中提供了一个默认的类Object,我们可以通过这个类来创建对象

    • 由于我们是使用系统默认的类创建的对象,所以系统不知道我们想要什么属性和行为,我们必须手动的添加我们想要的属性和行为

      • 如何给一个对象添加属性: 对象名称.属性名称 = 值;
      • 如果给一个对象添加行为: 对象名称.行为名称 = 函数;
    • 创建对象第一种方式

      let 对象名称 = new    Object();
      对象名称.属性名称 = 值;
      对象名称.行为名称 = 方法;
      
    • 创建对象第二种方式

      let 对象名称 = {};
      对象名称.属性名称 = 值;
      对象名称.行为名称 = 方法;
      
    • 创建对象第三种方式

      let 对象名称 = {
          属性名称:值,
          行为名称:方法;
      }
      

    方法和函数区别

    • 函数就是没有和其他的类显示的绑定在一起的,就称之为函数,可以直接调用
    • 方法就是显示的和其他的类显示的绑定在一起的,就称之为方法,只能通过对象来调用
    • 无论是函数还是方法,内部都有一个叫this的东西,谁调用了当前的函数或者方法,那么当前的this就是谁,函数内部的this输出的是window,方法内部的this输出的是当前调用的那个对象

    工厂函数不专业

    • 工厂函数就是专门用于创建对象的函数

      function 函数名称(形参列表){
          let 对象名称 = new Object();
          对象名称.属性名称 = 形参;
          对象名称.行为名称 = 方法;
          return 对象名称;
      }
      

    构造函数

    • 构造函数和工厂函数一样,都是专门用于创建对象的,本质上是工厂函数的简写

    • 构造函数和工厂函数的区别

      • 构造函数的函数名称首字母必须大写
      • 构造函数只能通过new来调用
      function 构造函数名称(形参列表){
          let 对象名称 = new Object(); //系统自动添加
          let this = 对象名称; //系统自动添加
          this.属性名称 = 形参;
          return this; //系统自动添加
      }
      构造函数名称.prototype = {
          行为名称:方法
      }
      当我们通过new来调用函数时
      1.会在构造函数中自动创建一个对象
      2.会自动将刚才创建的对象赋值给this
      3.会在构造函数最后自动添加return this;
      
      
    • prototype的特点

      • 储存在prototype中的方法可以被对应构造函数创建出来的所有对象共享
      • prototype中除了可以存储方法以外,还可以存储属性
      • prototype中如果出现了和构造函数中同名的属性或者方法,对象在访问的时候,访问到的是构造函数中的数据
    • prototype应用场景

      • prototype中一般情况下用于存储所有对象都相同的一些属性以及方法
      • 如果是对象特有的属性或者方法,我们会存储到构造函数中

    对象三角恋关系

    • 每个构造函数中都有一个默认的属性,叫做prototype,prototype属性保存着一个对象,这个对象我们称之为原型对象
    • 每个原型对象都有一个默认的属性,叫做constructor,constructor指向当前原型对象对应的那个构造函数
    • 通过构造函数创建出来的对象称之为实例对象,每个实例对象中都有一个默认的属性,叫做__proto__,__proto__指向创建它的那个构造函数的原型对象

    Function函数

    • JavaScript中函数是引用类型(对象类型),既然是对象,所以也是通过构造函数创建出来的,所有函数都是通过Function构造函数创建出来的对象
    • JavaScript中只要是函数就由prototype属性,Function函数的prototype属性指向Function原型对象
    • JavaScript中只要是原型对象就有constructor属性,Function原型对象的constructor指向它对应的构造函数
    • Function构造函数也是一个对象, 所以也有__proto__属性,Function构造函数__proto__属性指向Function原型对象

    Object函数

    • JavaScript中还有一个系统提供的构造函数叫做Object,只要是函数都是"Function构造函数"的实例对象
    • 只要是对象就有__proto__属性,所以Object构造函数也有__proto__属性,Object构造函数的__proto__属性指向创建它那个构造函数的原型对象
    • Object原型对象的__proto__属性指向NULL

    函数对象完整关系

    • 所有的构造函数都有一个prototype属性, 所有prototype属性都指向自己的原型对象
    • 所有的原型对象都有一个constructor属性, 所有constructor属性都指向自己的构造函数
    • 所有函数都是Function构造函数的实例对象
    • 所有函数都是对象, 包括Function构造函数
    • 所有对象都有__proto__属性
    • 普通对象的__proto__属性指向创建它的那个构造函数对应的"原型对象"
    • 所有对象的__proto__属性最终都会指向"Object原型对象"
    • "Object原型对象"的__proto__属性指向NULL
    • "Function构造函数"的__proto__属性指向自己的"原型对象"

    原型链

    • 对象中__proto__组成的链条我们称之为原型链
    • 对象在查找属性和方法的时候,会先在当前对象查找
    • 当前对象找不到想要的,会一次去上一级原型对象中查找
    • 找到Object原型对象都没有找到,就会报错
    • 为了不破坏原型链的关系,在给原型对象赋值时,需要手动添加constructor指向对象的构造函数
    • 属性注意点:在给一个对象不存在的属性设置值的时候,不会去原型对象中查找,如果当前对象没有就会给当前对象新增一个不存在的属性

    Js三大特性

    封装性

    • 对象的私有变量和函数
      • 默认情况下对象中的属性和方法都是公有的,只要拿到对象就能操作对象的属性和方法
      • 外界不能直接访问的变量和函数就是私有变量和私有函数
      • 构造函数的本质也是一个函数,所以也会开启一个新的作用域,所以在构造函数中定义的变量和函数就是私有变量和函数
    • 封装性就是隐藏实现细节,仅对外公开结构
    • 封装就是将数据隐藏起来,只能用此类的方法才可以读取或者设置数据,不可被外部任意修改,封装是面向对象设计本质将变化隔离,这样降低了数据被误用的可能提高安全性和灵活性

    属性方法分类

    • 实例属性/实例方法
      • 在企业开发中通过实例对象访问的属性,就称之为实例属性
      • 在企业开发中通过实例对象调用的方法,就称之为实例方法
    • 静态属性/静态方法
      • 在企业开发中通过构造函数访问的属性,就称之为静态属性
      • 在企业开发中通过构造函数调用的方法,就称之为静态方法

    继承性

    • 在企业开发中如果构造函数和构造函数之间的关系是is a关系,那么就可以使用继承来优化代码,来减少代码的冗余度
    • bind-call-apply
      • bind方法作用: 修改函数或者方法中的this为指定的对象, 并且会返回一个修改之后的新函数给我们,bind方法除了可以修改this以外, 还可以传递参数, 只不过参数必须写在this对象的后面
      • call方法作用:修改函数或者方法中的this为指定的对象, 并且会立即调用修改之后的函数,call方法除了可以修改this以外, 还可以传递参数, 只不过参数必须写在this对象的后面
      • apply方法作用:修改函数或者方法中的this为指定的对象,并且会立即调用修改之后的函数,apply方法除了可以修改this以外,还可以传递参数,只不过参数必须通过数组的方式传递
    • js中继承的中级方法
      • 在子类的构造函数中通过call借助父类的构造函数
      • 将子类的原型对象修改为父类的实例对象

    多态性

    • 强类型语言与弱类型语言
      • 一般编译型语言都是强类型语言,要求变量的使用要严格符合规定
      • 一般解释型语言都是弱类型语言,不会要求变量的使用要严格符合定义
      • 由于js语言是弱类型语言,所有我们不用过多关注多态
    • 多态是指事物的多种状态
    • 父类型变量保存子类型对象, 父类型变量当前保存的对象不同, 产生的结果也不同,这是多态在编程语言中的体现

    ES6类和对象

    • 在ES6之前通过构造函数来定义一个类

    • 从ES6开始系统提供了一个名称叫做class的关键字,这个关键字就是专门用于定义类的

      class 名称{
        //当我们通过new创建对象的时候,系统会自动调用constructor
          constructor(myName,myAge){
              this.name = myName;
              this.age = myAge;
          }
          //下面一行代码默认会添加到原型对象中
          方法名称(){}
          //静态方法
          static 方法名称(){}
      }
      
    • ES6中如何继承

      • 在子类后面添加extends并指定父类的名称
      • 在子类的constructor构造函数中通过super方法借助父类的构造函数
    • 注意点

      • 在ES6标准中添加实例属性都需要在
      • constructor中添加
      • 在ES6中static只支持定义静态方法不支持定义静态属性

    获取对象类型:根据对象名称.constructor.name输出来判断

    instanceof关键字:用于判断对象是否是指定构造函数的实例,只要构造函数的原型对象出现在实例对象的原型链中都会返回true

    isPrototypeOf属性:用于判断一个对象是否是另一个对象的原型,只要调用者在传入对象的原型链上都会返回true

    判断对象属性(会查找原型中):通过"属性名称" in 对象返回的值来判断

    判断自身是否拥有某个属性:通过对象.hasOwnProperty("属性名称")返回的值来判断


    对象遍历

    • 对象遍历就是依次取出对象中所有的属性和方法
    • 在js中可以通过高级for循环来遍历对象
    • for(let key in 对象)将指定对象中所有的属性和方法的名称取出来依次赋值给key这个变量

    对象解构赋值

    • 对象的解构赋值和数组的解构赋值除了符号不一样,其他的一模一样
    • 数组解构使用[],对象解构使用{}
    • 在对象解构赋值中,左边的变量名称必须和对象的属性名称一致,才能解构出数据

    深拷贝和浅拷贝

    • 深拷贝:修改新变量的值不会影响原有变量的值,默认情况下基本数据类型都是深拷贝
    • 浅拷贝:修改新变量的值会影响原有的变量的值,默认情况下引用类型都是浅拷贝

    数组高级API

    • forEach(遍历数组)

      //创建一个自己的forEach
      Array.prototype.myForEach = function(fn){
        for(let i = 0;i < this.length;i++){
            fn(this[i],i,this)
        }
      }
      //使用自己创建的forEach
      arr.myForEach(function(value,index,array){
        console.log(value)
      })
      
    • findIndex/find(数组查找)

      //创建一个自己的findIndex
      Array.prototype.myFindIndex = function(fn){
        for(let i = 0;i < this.length;i++){
              //找到了就返回索引
            if(fn(this[i],i,this)){
                return i;
            }
        }
          //没找到就返回-1
        return -1;
      }
      //使用自己创建的findIndex
      arr.myFindIndex(function(value,index,array)
      {
        if(value === xxx){
            return true;
        }
      })
      
      //创建一个自己的find
      Array.prototype.myFind = function(fn){
          for(let i = 0;i < this.length;i++){
              //找到了就返回元素
              if(fn(this[i],i,this)){
                  return this[i];
              }
          }
          //没找到就返回undefined
          return undefined;
      }
      
    • filter/map

      //创建自己的filter
      Array.prototype.myFilter = function(fn){
          //创建一个新数组+
          let newArr = [];
          for(let i = 0;i < this.length;i++){
              //把符合条件的添加到一个新数组中
              if(fn(this[i],i,this)){
                  newArr.push(this[i])
              }
          }
          //返回新数组
          return newArr;
      }
      //使用自己创建的filter
      arr.myFilter(function(value,index,array){
          if(value === xxx){
              return true;
          }
      })
      
      //创建自己的map
      Array.prototype.myMap = function(fn){
          //创建一个同样长度的数组
          let newArr = new Array(this.length);
          //把数组中的元素全部设置为undefined
          newArr.fill(undefined);
          for(let i = 0;i < this.length;i++){
              //把符合条件的替换掉原来的undefined
              if(fn(this[i],i,this)){
                  newArr[i] = this[i];
              }
          }
          //返回新数组
          return newArr;
      }
      

    • 数组排序:sort
    • 获取字符串长度: .length
    • 获取某个字符串: [索引]/charAt
    • 字符串查找: indexOf/lastIndexOf/includes
    • 拼接字符串: concat(不推荐)/ +
    • 截取子串: slice/substring/substr
    • 字符串切割: split
    • 是否以指定字符串开头: startsWith
    • 是否以指定字符串结尾: endsWith
    • 字符串模板: ``

    基本数据类型和基本包装类型

    • 基本数据类型
      • 字符串类型/数值类型/布尔类型/空类型/未定义类型
      • 通过字面量创建的基本数据类型的数据都是常量
      • 常量是不能被修改的,每次修改或者拼接都是生成一个新的
    • 对象类型的特点
      • 有属性和方法
    • 以前之所以能够访问基本数据类型的属性和方法,是因为在运行时系统自动将基本数据类型包装成了对象类型

    三大对象

    • JavaScript中提供三种自带的对象,分别是"本地对象"/"内置对象"/"宿主对象",宿主是指JavaScript运行环境,js可以再浏览器中运行,也可以在服务器上运行(nodejs)
    • 本地对象
      • 与宿主无关,无论在浏览器还是服务器中都有的对象
      • 就是ECMAScript标准中定义的类(构造函数)
      • 在使用过程中需要手动new创建
      • 例如:Boolean,Number,String,Array,Function,Object,Data,RegExp等
    • 内置对象
      • 与宿主无关,无论在浏览器还是服务器中都有的对象
      • ECMAScript已经帮我们创建好的对象
      • 在使用过程中无需手动new创建
      • 例如:Global,Math,JSON
    • 宿主对象
      • 对于嵌入到网页的js来说,其宿主对象就是浏览器,所以宿主对象就是浏览器提供的对象
      • 包含:Window和Document等
      • 所有的DOM和BOM对象都属于宿主对象
    • 自定义对象:我们自己编写的类创建的对象
    • Math内置对象
      • Math.floor() 向下取整
      • Math.ceil() 向上取整
      • Math.round() 四舍五入
      • Math.abs() 绝对值
      • Math.random() 生成随机数

    相关文章

      网友评论

          本文标题:07-JavaScript面向对象

          本文链接:https://www.haomeiwen.com/subject/jppdzqtx.html