美文网首页
js面向对象编程

js面向对象编程

作者: lemonzoey | 来源:发表于2022-03-22 15:30 被阅读0次

    从面向过程开发到面向对象开发,是个思维的重大转变,当真正理解了面向对象编程后,对于日常的开发就会有一个质的飞跃。

    一. 面向过程与面向对象的区别

    1.概念

    1.面向过程
    是一种以过程为中心的编程思想,面对问题,罗列出解决问题的步骤,然后按步骤一步步去实现
    比如:蛋炒饭的制作,蛋和饭都混在一起,省事省力就能做出一盘美味可口的炒饭

    2.面向对象
    是以对象为核心,不需要关心程序内部的实现。解决问题时候,把问题抽象成对象,分析解决问题需要哪些对象,然后给对象里赋值一些方法和属性,让对象执行自己的方法,解决问题。
    比如:盖浇饭的制作,把一份完整的饭拆分成米饭和菜,通过组合不同的米粉和菜能满足不同客户定制化的需求

    2.区别

    1.面向过程:
    优点:性能较高
    缺点:耦合性强,不易维护,扩展和复用

    2.面向对象
    优点:程序间低耦合,易于维护,扩展和复用,灵活配置
    缺点:性能低于对象过程,因为面对对象需要实力化,比较消耗性能

    二. 面向对象的特性

    1.三大原则:封装,继承,多态

    1.封装

    1.概念:也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
    封装可以给用户提供一个函数,函数里的方法属性不对外暴漏,而能实现用户想要实现的功能
    好处:将变化隔离,程序便于使用,易于复用,安全性较高,
    原则:隐藏不需要对外暴漏的属性,仅提供公共访问方式

    2.继承

    1.概念:让一个类拥有另一个类的属性和方法
    2.创建对象的方式
    1.对象字面量
    const obj = {}
    
    2.构造函数
    const = new Object()
    
    3.Object.create()

    用这种方式创建一个空对象 Object.create(Object.prototype),类似 {},注意,Object.create(null)可以创建对象,但是这个对象没有原型,不会继承任何东西,连toString()方法都没有哦。

    const obj1 = {name:'111'}
    const obj2 = Object.create(obj1) 
    console.log(obj2.name) // 111
    
    
    2.继承的方式
    1.原型链

    1.1 基本思想:利用原型,让一个引用类型继承另一个引用类型的属性和方法

    // 父函数
    function Parent(){
      this.value1 = true
    }
    Parent.prototype.getParentValue = function(){
     return this.value1
    }
    
    // 子类函数
    function Child(){
      this.value2 = false
    }
    // 这句话是最关键的。child 继承了parent的原型
    Child.prototype = new Parent()
    
    Child.prototype.getChildvalue = function(){
     return this.value2
    }
    const cc = new Child()
    console.log(cc.getParentValue()) // true 这个是继承的父类的方法
    console.log(cc.getChildvalue()) // false 自己的方法
    
    

    1.2 缺点:
    缺点1.实例共享引用类型,
    原型链继承主要的问题是包含引用类型值的原型, 因为包含引用类型值的原型属性会被所有的实例共享, 而在通过原型来实现继承的时候, 原型实际变成了另外一个函数的实例(这里边就有可能存在引用类型)

    缺点2.在创建 Child 的子类的时候,无法像继承元素传递参数

    所以综上,这种继承方式少用

    2.构造函数
    3.组合继承
    4.原型式继承
    5.寄生式模式
    6.寄生组合试继承

    3.多态

    三. 对象的特性

    1.对象的方法

    1.1 属性的简洁方

    const name='zy'
    const obj = {name:name}
    // 简写
    const obj1 ={name} 
    console.log('obj1',obj1) // obj1: {name:'zy'}
    
    

    1.2 属性名表达式

    const obj = {name:'zy'}
    obj.name // 'zy'
    obj['name'] // zy
    

    1.3 属性的可枚举和遍历 ***

    1.可枚举性
    1. Object.getOwnPropertyDescriptor

    每个属性都有一个Descriptor,方法是 Object.getOwnPropertyDescriptor(对象,属性名)

    const obj = {name:'zy'}
    console.log(Object.getOwnPropertyDescriptor(obj,'name'))
    //  {
    //    configurable: true, // 是否可以删除
    //    enumerable: true, // 是否可以枚举
    //    value: zy,
    //    writable: true, // 是否可以编辑
    //  }
    
    getOwnPropertydescriptor
    2.Object.getOwnPropertyDescriptors

    若要看整个对象的描述,可以用Object.getOwnPropertyDescriptors(obj)

    const obj = {name:'zy',age:'1'}
    Object.getOwnPropertyDescriptors(obj)
    // {
    // age: {
    //  configurable: true,
    //  enumerable: true,
    //  value: "1",
    //  writable: true,
    //}
    //name: {
    //  configurable: true,
    //  enumerable: true,
    //  value: "zy",
    //  writable: true,
    //}
    //}
    
    Object.getOwnPropertyDescriptors
    3.Object.defineProperty

    这里可以看到通过对象字面量直接创建的属性默认是可以遍历,可以更改和可以删除的,下面我们通过另一种方法创建对象的属性,Object.defineProperty

    const obj = {}
    Object.defineProperty(obj,'name',{
      value:'zy'
    })
    console.log(obj) // {name:'zy}
    console.log(Object.getOwnPropertyDescriptor(obj,'name'))
    // {
    // configurable: false
    // enumerable: false
    // value: 12
    // writable: false,
    // }
    
    Object.defineProtery

    通过对比可以发现,直接字面量创建的对象属性默认都是可以编辑遍历和删除的,而通过Object.definePorperty创建的对象属性则默认是不可编辑遍历和删除的。

    扩展下 defineProperty的相关知识
    configurable 是配置属性是否可以删除,默认true
    enumerable 是配置属性是否可以枚举,默认true
    writable 是配置属性是否可以编辑,默认true

    4.Object.preventExtensions

    Object.preventExtensions()方法让一个对象变的不可扩展,也就是永远不能再添加新的属性。
    1.通过对象字面量新增属性,静默的失败

    const obj = {name:'zy'}
    Object.preventExtensions(obj)
    obj.age = '1' //通过对象这种方式添加属性已经添加不上去了
    console.log(obj) // {name:'zy'}
    

    2.通过defineProperty给对象添加属性则直接报错

    const obj = {name:'zy'}
    Object.preventExtensions(obj)
    Object.defineProperty(obj,'age',{value:'1'})
    console.log(obj) 
    // Uncaught TypeError: Cannot define property age, object is not extensible
    
    5.Object.isExtensible()

    Object.isExtensible() 方法判断一个对象是否是可扩展的(是否可以在它上面添加新的属性)。

    const obj = {name:'zy'}
    Object.isExtensible(obj) // true
    Object.preventExtensions(obj)
    Object.isExtensible(obj) //false
    
    6.Object.seal()

    Object.seal()方法封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置。当前属性的值只要原来是可写的就可以改变。

    7.Object.freeze()

    方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改。freeze() 返回和传入的参数相同的对象。

    2.遍历

    对象的遍历总共有5种方式

    1.for...in

    for in可以遍历对象自身和继承的属性,不含不可枚举和Symbol

    补充个知识点:in 操作符 和 hasOwnProperty
    in和hasOwnProperty的区别
    in 可以检查出自身和原型上的所有属性
    hasOwnProperty 判断的自身的属性
    通过这两个属性可以区分是哪些属性是自身的,哪些属性是原型上的

    const obj = {
     name:'zy',
     age:'1',
    }
    // in 操作符
    console.log('name' in obj) // true 自身的属性
    console.log('age' in obj) // true 自身的属性
    console.log('wdith' in obj) // false 不存在这个属性
    console.log('toString' in obj) // true 原型上的方法
    
    // hasOwnProperty
    console.log(Object.hasOwnProperty('name')) // true 自身的属性
    console.log(Object.hasOwnProperty('toString')) // false 不是自身的属性和方法
    
    // 通过in 和 hasOwnProperty组合区分出原型的方法属性
    in 返回true hasOwnProperty 返回false的就是原型上的方法
    function isPropertyItem(item,obj){
      return item in obj  && !Object.hasOwnProperty(item)  
    }
    
    2.Object.keys(obj)

    Object.keys,返回一个数组,可遍历对象自身属性,不含不可枚举和Symbol

    3.Object.getOwnpropertyNames(obj)

    getOwnpropertyNames ,返回数组,获取自身所有属性,包含不可枚举,不含Symbol

    4.Object.getOwnPropertySymbols(obj)

    Object.getOwnPropertySymbols 返回数组,获取自身所有Symbol属性

    5.Reflect.ownKeys(obj)

    Reflect.ownKeys返回一个数组,获取自身所有属性,包含 不可枚举和Symbol

    相关文章

      网友评论

          本文标题:js面向对象编程

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