JavaScript

JS面向对象

字数:3295    阅读时间:17min
阅读量:1532

一、面向过程和面向对象

什么是面向过程:
  解决一个问题的时候会分析该怎么一步步的解决这个问题,遇到什么问题执行什么方法解决什么问题,最终达到向要的结果;注重的过程,在过程中一步步解决问题

什么是面向对象:
  解决一个问题的时候会把事务抽象成一个个对象,分析每个对象拥有的属性和方法,最后让对象执行自己的方法进而解决问题;注重的是结果不在乎过程怎样,创建需要的对象,为对象添加各自的属性和方法

  • 以是洗衣机为例:
    • 面向过程:执行放衣服方法--->执行洗衣液方法--->执行加水方法--->执行洗衣服方法--->执行漂洗方法--->执行甩干方法
    • 面向对象:创建一个人类对象,和洗衣机对象--->为人类添加剂放衣服方法,放洗衣液方法,加水方法;为洗衣机添加洗衣服方法,漂洗方法,甩干方法--->人执行放衣服加水加洗衣液方法;洗衣机执行洗衣服漂洗甩干方法

我们知道JS其实算是一门面向过程的编程语言,但是JS里为什么还有面向对象呢,因为在设计之初是参考Java的,所以就引入了对象这个概念,JS的对象都是基于这个全局的Object对象创造出来的,所以JS的面向对象更准确的说应该是基于对象

二、对象的创建方式

2.1:基础方式

这两种基础方式创建的对象 ,只适合在创建单个对象,不量产的时候使用

2.2:工厂模式

可以创建多个相似对象,可以量产对象;缺点:无法识别对现象的类型,返回的都是Object对象

2.3:构造函数模式

构造函数解决了工厂模式无法识别对象类型的问题;缺点:每次实例一个对象的时候总是会重新创建构造器上的所有函数,这就造成了不必要的内存浪费

JS在使用new的时候内部所作的事情

  1. 创建一个空对象
  2. 将空对象的原型指向构造函数的原型(空对象的__proto__=构造函数的prototype)
  3. 执行构造函数并将this指向当前空对象
  4. 检查构造函数执行结果,如果返回值是一个引用类型则输出该返回值,如果返回值不是一个引用类型,则输出新创建的这个空对象
2.4:原型模式

它解决了构造函数内存消耗的缺点;缺点:因为所有的属性和方法都是共享的,当一个实例改变了(不是重写)引用值类型(例如数组)的数据,其他实例上的这个属性都会跟着发生变化

2.5:组合模式

组合模式结合了构造函数模式和模式的优点,是创建对象中最常用的方法;它可以让实例拥有自己的属性值副表,同时也可以使用原型上的共享方法;非要说有什么缺点的话,那就是构造函数和原型分开了,没有很好的形成一个整体

2.6:动态原型模式

动态原型创建对象就是为了解决组合式创建对象的缺陷,将所有的信息封装在构造函数中;这种方法就称的上是完美了;注意if判断一个在执行之后应该存在的方法或属性就好;不能用对象字面量修改原型对象

2.7:寄生构造函数模式

很少用到可做了解,基本上就是为扩展原生构造函数的,比如为Array扩展额外的方法

2.8:稳妥构造函数模式

基本上用不到,可做了解;最大的特点就是安全。。。。

三、继承的方式

我们知道面向对象的三大特性就是封装,继承,多态;封装不用多说了,就是能将够事物的属性和方法抽离出来封装在一个对象中,方便使用;多态就是同一个操作作用于不同的对象上,可以产生不同的解释和不同的执行结果 ,在js中对象的多态用到的不多;我们着重讲解继承

3.0:原型和原型链
  • 什么是原型
    • 原型就是可以提供公共属性的一个对象
    • 每个对象都有一个原型prototype,这里面存储的是可以共享出去的属性。prototype称之为显式原型。
    • 每个对象都有一个__proto__,它相当于是一个指针,指向的是构造当前对象的prototype,js的原型链就是通过__proto__串联起来的。__proto__称之为隐式原型。
    • 对象的prototype都有一个constructor属性,它相当于是一个指针,指向的是构造函数本身(因为每次new的时候空对象的__proto__都指向了构造函数的prototype)
  • 什么是原型链
    • 实例对象的__proto__指向的是构造函数中的prototype原型对象;构造函数中的__proto__指向的是系统Object的prototype原型对象;系统对象Object的__proto__指向的是null(所有对象的原型链最终都指向null)
    • 实例对象的__proto__,跟构造函数prototype原型对象之间的指向关系就是原型链
  • 原型的作用
    1. 共享数据,减少空间占用
    2. 继承
3.1:原型链式继承
  • 优点:
    1. 简单,一行代码搞定
    2. 父类的方法得到复用
  • 缺点:
    1. 为子类添加原型上的属性和方法的时候,必须写在指针指向实例化父类之后
    2. 无法实现多继承
    3. 所有的属性都是共享的(尤其是对数组进行操作的时候原型数组就会被改变)
    4. 不能传参(属性在初始化的时候就已经确定,不能修改)
3.2:借用构造函数式继承
  • 优点
    • 可以传递参数
    • 解决了原型方式数据共享不能随意修改数组的缺陷
    • 可以实现多继承
  • 缺点
    • 每次实例化Cat的时候都会运行一次Animation构造函数
    • 方法无法复用, 不能使用原型上的共享方法
3.3:组合式继承
  • 优点
    • 组合式继承综合了原型链继承和借用构造函数继承的优点,同时又避免了他们各自的缺点,可以说是完美的继承方法了,我们称之为伪经典模式,开发中基本都用这种模式
  • 缺点(影响不大可忽略)
    • 构造函数运行了两次
    • 构造函数里的属性存了两份
3.4:原型式继承
  • 优点
    • 可以实现普通对象的继承(例如没有构造函数的字面量方式对象)
  • 缺点
    • 无法传递参数
    • 属性共享会带来属性被篡改风险,比如数组的修改
    • 看起来不像是一个继承
3.5:寄生式继承

将原型式继承和自己的方法写在一个函数中,使之成为一个整体看起来更像是一个继承

3.6:组合寄生式继承

组合寄生式继承结合了借用构造函数式继承的优点和寄生式继承的优点,完美的解决了伪经典模式运行两次构造函数的缺点,我们称之为完美继承;如果非要说有什么缺点,那就是写起来比较麻烦

3.7:ES6类的继承(extends)

ES6继承在语言层面上提供了面向对象的部分支持,在模式上使用的是组合寄生式继承,用起来更直观更方便更标准化,也支持原生对象的继承;但是也有一些缺点,比如不能设置静态属性(可以设置静态方法);class中不能定义私有属性和方法,所有的属性和方法都会被子类继承,可以写在class外,但是又破坏了对象的整体性

四、封装和多态

面向对象的封装

在ES5中没有类的概念,我们用function来模拟类,类就是保存了一个函数的变量,这个函数又自己的属性和方法;把客观事物封装成抽象的类,隐藏属性和方法的实现细节,仅对外公开接口就是封装;个人理解,创建对象的过程就是在封装对象

面向对象的多态

所谓多态,就是指一个引用类型在不同情况下可以有多种状态。多态在js中用的比较少

野生小园猿
励志做一只遨游在知识海洋里的小白鲨
查看“野生小园猿”的所有文章 →

相关推荐