JavaScript 面向对象

当我们需要创建大量的对象时,字面量创建将会导致过多的重复代码,为了解决这个问题,我们创造了一些设计模式来创建对象

创建对象

  1. 工厂模式

    function createPerson(name, age, job) {
        var o = new Object()
        o.name = name
        o.age = age
        o.job = job
        o.sayName = function () {
            alert(this.name)
        }
        return o
    }
    
    var person1 = createPerson('Nicholas', 29, 'Software Engineer')
    var person2 = createPerson('Greg', 27, 'Doctor')

    存在问题

    • 无法解决对象识别问题(爷爷当然都是 Object 啦,但他们是拥有同一个爸爸吗?)
  2. 构造函数模式

       function Person(name, age, job) {
         this.name = name
         this.age = age
         this.job = job
         this.sayName = function () {
           alert(this.name)
         }
       }
    
       var person1 = new Person('Nicholas', 29, 'Software Engineer')
       var person2 = new Person('Greg', 27, 'Doctor')

    此时,person1 和 person2 的爸爸就是 Person 啦

    person1 instanceof Person // true
    person2 instanceof Person // true

    存在问题

    • 同一个函数 sayName 被创建了两次,属于没有必要的内存消耗
  3. 构造函数模式 + 原型模式

    function Person(name, age, job) {
     this.name = name
     this.age = age
     this.job = job
    }
    Person.prototype = {
     constructor: Person, // 不写这条的话, 实例的 constructor 为 Object
     sayName: function () {
       alert(this.name)
     }
    }

    这下没毛病了吧!!有强迫症的工程师要说了,能不能把 构造函数原型 的代码整合到一起呢,分开后缺少一点点整体美……好吧,以下动态原型模式满足你

  4. 动态原型模式

    function Person(name, age, job) {
     this.name = name
     this.age = age
     this.job = job
     if (typeof this.sayName != 'function') {
       Person.prototype.sayName = function () {
         alert(this.name)
       }
     }
    }

继承

当我们的对象需要沿用其他对象的共同属性,又想要有自己的特点的时候,我们就需要继承了。

ECMAScript 只支持实现继承,而且其实现继承主要是依靠原型链来实现的。

——《JavaScript 高级程序设计》第 3 版

  1. 原型链

    function SuperType() {
     this.property = true
    }
    SuperType.prototype.getSuperValue = function () {
     return this.property
    }
    
    function SubType() {
     this.subproperty = false
    }
    SubType.prototype = new SuperType() // 继承了 SuperType
    SubType.prototype.getSubValue = function () {
     return this.subproperty
    }
    
    var instance = new SubType()
    alert(instance.getSuperValue()) // true

    存在问题

    • 由于 SubType 的原型是 SuperType 的一个实例,所以所有 SubType 的实例都会共享 SuperType 的实例属性,这里共享的属性为 property,当一个 SubType 的实例修改这个属性时,其他 SubType 的实例都会受到影响
  2. 组合继承(JavaScript 中最常用的继承模式)

    function SuperType(name) {
     this.name = name;
     this.colors = ['red', 'blue', 'green']
    }
    SuperType.prototype.sayName = function () {
     alert(this.name);
    };
    
    function SubType(name, age) {
     SuperType.call(this, name);
     this.age = age;
    }
    
    SubType.prototype = new SuperType();
    SubType.prototype.constructor = SubType;
    SubType.prototype.sayAge = function () {
     alert(this.age);
    };
    
    var instance1 = new SubType('Nicholas', 29);
    instance1.colors.push('black');
    alert(instance1.colors); // 'red,blue,green,blank'
    instance1.sayName();     // 'Nicholas'
    instance1.sayAge();      // 29
    
    var instance2 = new SubType('Greg', 27);
    alert(instance2.colors); // 'red,blue,green'
    instance2.sayName();     // 'Greg'
    instance2.sayAge();      // 27

ES6 世界的类

创建类

class Person {
  constructor(name, age, job) {
    this.name = name
    this.age = age
    this.job = job
  }
  sayName () {
    alert(this.name)
  }
}

哇,这个世界好清净!!

继承

class SuperType {
  constructor(name) {
    this.name = name;
    this.colors = ['red', 'blue', 'green'];
  }
  sayName () {
    alert(this.name);
  }
}

class SubType extends SuperType {
  constructor(name, age) {
    super(name); // 如果不调用 super 方法,子类就得不到 this 对象
    this.age = age;
  }
  sayAge() {
    alert(this.age);
  };
}

var instance1 = new SubType('Nicholas', 29);
instance1.colors.push('black');
alert(instance1.colors); // 'red,blue,green,blank'
instance1.sayName();     // 'Nicholas'
instance1.sayAge();      // 29

var instance2 = new SubType('Greg', 27);
alert(instance2.colors); // 'red,blue,green'
instance2.sayName();     // 'Greg'
instance2.sayAge();      // 27

ES6 的世界真是又清新又爽快!!


参考资料

  1. 《JavaScript 权威指南》第 6 版,David Flanagan 著,淘宝前端团队 译
  2. 《JavaScript 高级程序设计》第 3 版,Nicholas C.Zaks 著,李松峰 曹力 译
  3. 《ECMAScript 6 入门》,阮一峰,http://es6.ruanyifeng.com/,2018-2-2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值