这边主要的是ES5及之前版本的js面向对象设计。由于工作的原因,我这边上手就是ES6,正因为这样在看面试题的时候才发现原来对于之前的js封装这一块的缺失。不管怎么说,缺什么,补什么,记不牢,先笔记。

首先需要注意的是,之后的js或者JavaScript都特指ES5及之前版本。

其实js算不上严格的面向对象(Object-Oriented,OO)语言,因为它有对象但并没有严格意义上的class,同样的没有class也就谈不上extends,所以下面的其实更应该说是”伪类”,”伪继承”。下面具体看看这方面的梳理吧。

创建对象

对于js而言{}就是一个对象,当然new Object()也是一个对象。《JavaScript高级编程》中提到了多种创建对象的模式,个人习惯使用其中3种——构造函数模型原型模式混合模型

从下文也可以看出来,js中将这些【创建对象的模式】当成了class,不过就实际情况来说,【混合模式】已经很像java中的class了

  • 构造函数模型

    定义方式:

    1
    2
    3
    4
    5
    function Person (name,..){
    this.name = name;
    ..
    this.call = function (){};
    }

    注意点:

    1. 本质上是个函数。
    2. 使用new创建对象,函数名首字母大写,直接将属性赋给this,没有return。
    3. 缺点:每个实例都将重新创建所有的属性。
  • 原型模型

    prototype中的属性,定义方式:

    1
    2
    3
    function Person (){}
    Person.prototype.name = "name";
    Person.prototype.call = function (){};

    注意点:
    1.【原型模型】其实是包含【构造函数模型】;

    1. 而且prototype的属性对立于对象实例,也就是不能通过实例改变的值。
    2. 调用对象属性时,会先查看是否有【实例属性】,没有时再查看【原型属性】。
    3. 当通过实例”改变”某个【模型属性】时,实际上是创建了一个同名【实例属性】覆盖了。但在改变对象属性中的属性时,就会因为共享而导致错误。
  • 混合模型(构造函数模型-原型模式)

    由于【构造函数模型】-【原型模式】优缺互补,一般实际使用都是【混合模式】——使用【构造函数模型】创建实例私有属性,使用【原型模式】创建共享属性

  • other

    1. 使用实例的hasOwnProperty(key:string)判断属性是否是实例属性。
    2. [key:string] in objectobject实例是否包含属性key。
    3. for-in遍历对象属性。

继承

如同上面所说的,js没有严格意义上的继承。

  • 普通继承

    与其说是继承,还不如说是合并两个对象生产新对象。而且继承是class的事,因为是”伪”的,所以这就当是吧。

    1
    var p = Object.create({..},{..});
  • 构建函数继承

    具体的原理其实就是用call调用被继承函数,因为传入的this指向当前函数,也就是说所有的属性都绑定在了当前构造函数上。但这样也就只能继承【实例属性】

    1
    2
    3
    4
    function Son (..){
    Person.call(this,..);
    ...
    }
  • 原型继承

    只能继承【原型属性】

    1
    2
    Son.prototype = Object.create(Person.protptype); //或者 Son.prototype = new Person();
    ...
  • 组合继承

    组合【构建函数继承】和【原型继承】,如此技能继承【实例属性】,又能使用【原型属性】。