跟着书本学JavaScript设计模式(多继承)

100 阅读2分钟

JavaScript多继承

由于JavaScript中继承是依赖于原型prototype链实现的,只有一条原型链,理论上是不能实现多继承,可以通过对传入对象的属性复制来实现多继承。


单继承

通过类式继承的方式进行属性赋值

    // 单继承 属性复制 这是一个浅拷贝的方式
    var extend = function (target, source) {
      for (var property in source) {
        target[property] = source[property];
      }
      return target;
    }

    // 测试代码
    var book = {
      name: 'JavaScript设计模式',
      alike: ['css', 'html', 'JavaScript'],
      sayName: function () {
        console.log(this.name)
      }
    }

    var anotherBook = {
      color: 'blue'
    }

    extend(anotherBook, book);
    console.log(anotherBook.name); // javascript 设计模式
    console.log(anotherBook.alike); // ["css", "html", "JavaScript"]

    anotherBook.alike.push('ajax');
    anotherBook.name = '设计模式';
    console.log(anotherBook.name); // 设计模式
    console.log(anotherBook.alike); // ["css", "html", "JavaScript", "ajax"]
    console.log(book.name); // JavaScript设计模式
    console.log(book.alike); // ["css", "html", "JavaScript", "ajax"]

但是上述的是一种浅拷贝的方式进行赋值,如果传入的被继承对象中存在引入类型的属性,将会拷贝失败,所以我们需要实现一个深拷贝方式进行继承。

    // 单继承 属性深拷贝
    var deepExtend = function (target, source) {
      for (var property in source) {
        if (typeof source[property] === 'object') {
          if (Object.prototype.toString.call(source[property]) === "[object Array]") {
            target[property] = source[property];
          } else {
            deepExtend(target, source[property])
          }
        } else {
          target[property] = source[property];
        }
      }
      return target;
    }
    
    // 测试代码
    var deepBook = {
      deep: true
    }
    deepExtend(deepBook, book);

    console.log(deepBook.name);
    console.log(deepBook.alike);
    deepBook.sayName();

多继承

通过对传入的对象进行一一复制,并将每一个被继承的属性复制到继承对象。

    // 多继承 属性复制
    var mix = function () {
      let i = 1,
        len = arguments.length,
        target = arguments[0],
        arg;
      for (; i < len; i += 1) {
        arg = arguments[i];
        for (let property in arg) {
          target[property] = arg[property]
        }
      }
      console.log(target);
      return target;
    }

    // 将多继承绑定Object
    Object.prototype.mix = mix;

    var cssBook = {
      css: true
    }

    var htmlBook = {
      html: true,
    }
    
    // 测试代码
    let webBook = {};
    console.log(webBook);
    webBook.mix(webBook, cssBook, htmlBook);
    console.log(webBook);

总结,由于JavaScript是通过prototype进行属性继承,所以只有通过将多个父类的属性通过一一复制在赋值的方式进行属性传递。