JavaScript基础强化笔记-继承

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zjiang1994/article/details/79151418

JavaScript基础强化笔记-继承

出于安全考虑,本地类和宿主类不能继承,其他都可以继承。

ECMAScript并没有严格的定义抽象类,但是存在一些不允许使用的类。

子类将继承超类的所有属性和方法,包括构造函数及方法的实现。记住,所有属性和方法都是公用的,因此子类可直接访问这些方法。子类还可 添加 超类中没有的新属性和方法,也可以 覆盖 超类的属性和方法。

JavaScript 中的继承机制并不是明确规定的,而是通过 模仿 实现的。这意味着所有的继承细节并非完全由解释程序处理。


对象冒充

  • 说白了就是先写一个超类A的构造方法。再写一个类B的构造方法;
  • 然后在B的方法中引用A的构造方法;
  • 使用之后再删除ClassA的引用。
  • 定义子类属性(所有的子类新属性在删除引用后定义)
// 超类ClassA的构造方法
function ClassA(sColor) {
    this.color = sColor;
    this.sayColor = function () {、
        alert(this.color);
    };
}

// 子类ClassB的构造方法
function ClassB(sColor, sName) {
    // 引用ClassA的构造方法
    this.newMethod = ClassA;
    // 使用ClassA的构造方法够照ClassB
    this.newMethod(sColor);
    // 删除对ClassA的引用
    delete this.newMethod;

    /* 所有的子类新属性在删除引用后定义 */

    // 子类属性
    this.name = sName;
    this.sayName = function () {
        alert(this.name);
    };
}

对象冒充可以实现多重继承

一个类可以继承多个超类。
ClassX 和 ClassY,ClassZ 想继承这两个类。

如果存在两个类 ClassX 和 ClassY 具有同名的属性或方法,ClassY 具有高优先级。
因为它从后面的类继承。

function ClassZ() {
  // 继承ClassX
  this.newMethod = ClassX;
  this.newMethod();
  delete this.newMethod;
  //继承ClassY
  this.newMethod = ClassY;
  this.newMethod();
  delete this.newMethod;
}

call()方法

call() 方法是与经典的对象冒充方法最相似。
一个参数用作 this 的对象。其他参数都直接传递给函数自身。

function ClassB(sColor, sName) {
  /*
  将classB付给ClassA中的this
  这时classA中的this实际指向是ClassB
  */
  ClassA.call(this, sColor);
  this.name = sName;
  this.sayName = function () {
    alert(this.name);
  };
}

apply() 方法

两个参数,用作 this 的对象和要传递给函数的参数的数组。
apply第二个参数只能是数组

function ClassB(sColor, sName) {
  // 引用ClassA构造方法
  ClassA.apply(this, new Array(sColor));
  // 也可以使用arguments
  // 只有超类中的参数顺序与子类中的参数顺序完全一致时才可以传递参数对象
  // ClassA.apply(this, arguments);
  // ClassB 自己的属性
  this.name = sName;
  this.sayName = function () {
    alert(this.name);
  };
}

原型链(prototype chaining)

继承这种形式在 ECMAScript 中原本是用于 原型链 的。

// ClassA的构造方法
function ClassA() {
  //要求为空,全部写在prototype上
}
// ClassA的属性
ClassA.prototype.color = "blue";
ClassA.prototype.sayColor = function () {
  alert(this.color);
};

// ClassB的构造方法
function ClassB() {
}

// 继承ClassA的属性
ClassB.prototype = new ClassA();

// ClassB自己的属性,需要出现在继承之后
ClassB.prototype.name = "";
ClassB.prototype.sayName = function () {
  alert(this.name);
};

关于 instanceof 运算

在原型链中,instanceof 运算符的运行方式也很独特。对 ClassB 的所有实例,instanceof 为 ClassA 和 ClassB 都返回 true。

var objB = new ClassB();
alert(objB instanceof ClassA);  //输出 "true"
alert(objB instanceof ClassB);  //输出 "true"

混合方式

// ClassA的构造方法,只写属性,不写函数
function ClassA(sColor) {
  this.color = sColor;
}

// 使用原型给ClassA赋予函数
ClassA.prototype.sayColor = function () {
  alert(this.color);
};

// ClassB的构造方法
function ClassB(sColor, sName) {
  // 先调用ClassA,继承ClassA的属性
  ClassA.call(this, sColor);
  this.name = sName;
}

// 再通过原型链继承ClassA的函数
ClassB.prototype = new ClassA();

// 通过原型链定义自己的函数
ClassB.prototype.sayName = function () {
    alert(this.name);
};
  • ClassB 构造函数中,用对象冒充继承 ClassA 类的 sColor 属性。
  • 在第二行突出显示的代码中,用原型链继承 ClassA 类的方法。

猜你喜欢

转载自blog.csdn.net/zjiang1994/article/details/79151418