JavaScript 新旧替换四:继承
2021-01-15 16:15
标签:常用 dex des 子类 书籍 online github self 直接 在一些书籍中花费了不少的篇幅进行讲述,新的语法中也出现了相关的关键字,实现的方式中也涉及到 JavaScript 中很重要的知识点。 注意:JavaScript 中并没有类似 Java 中的类和继承,以下用“类”和“继承”是为了方便描述。 上一篇 JavaScript 新旧替换三:参数转换。 实现继承功能的方式有多种,JavaScript 中常用的继承模式是组合继承,这里以此为例。 在组合继承中,主要的思路是: 用新的语法实现上面的继承: 在书写形式上有很大的变化,但实际上也是通过原型链实现,通过 Babel 转译为 ES5 看下是怎样的实现思路。 首先说明一下 Babel 中转译有两种模式:normal 和 loose。 选择 normal 模式的转译更加合适,先来看下 在上面转译的代码中,处理的主要思路有: 这种方式跟组合使用构造函数模式和原型模式创建对象很相似,不过表达的语义不太一样。 再来看下继承转译后的代码: 在上面转译的代码中,处理的主要思路是: ES2015 引入了类的概念,通过 子类中如果没有显式的写出构造方法,会默认的添加。 JavaScript 新旧替换四:继承 标签:常用 dex des 子类 书籍 online github self 直接 原文地址:https://www.cnblogs.com/thyshare/p/12935154.html 目录
引子
ES5 方式
function Fruit(name) {
this.name = name;
}
Fruit.prototype.showName = function() {
console.info("Fruit Name:", this.name);
};
function Apple(name, color) {
Fruit.call(this, name);
this.color = color;
}
Apple.prototype = new Fruit();
// 矫正语义指向,并不是必需
Apple.prototype.constructor = Apple;
Apple.prototype.showColor = function() {
console.info("Apple Color:", this.color);
};
var apple = new Apple("apple", "green");
console.info("apple:", apple);
apple.showName();
apple.showColor();
Fruit.call(this, name)
绑定子类的 this
,达到继承父类属性效果。prototype
属性,子类的实例会沿着原型链查找,达到了继承父类方法的效果。 ES2015+ 方式
class Fruit {
constructor(name) {
this.name = name;
}
showName() {
console.info("Fruit Name:", this.name);
}
}
class Apple extends Fruit {
constructor(name, color) {
super(name);
this.color = color;
}
showColor() {
console.info("Apple Color:", this.color);
}
}
let apple = new Apple("apple", "green");
console.info("apple:", apple);
apple.showName();
apple.showColor();
Fruit
类转译后的实现:"use strict";
/**
* Symbol.hasInstance 属性,指向一个内部方法。
* 当其它对象使用 instanceof 运算符,判断是否为该对象的实例时,会调用这个方法。
* 比如,foo instanceof Foo 在语言内部,实际调用的是Foo[Symbol.hasInstance](foo)。
*/
function _instanceof(left, right) {
if (
right != null &&
typeof Symbol !== "undefined" &&
right[Symbol.hasInstance]
) {
return !!right[Symbol.hasInstance](left);
} else {
return left instanceof right;
}
}
// 防止直接当方法调用
function _classCallCheck(instance, Constructor) {
// 判断 instance 是否为 Constructor 的实例
if (!_instanceof(instance, Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
/**
*
* Object.defineProperty 直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象。
*
*/
function _defineProperties(target, props) {
for (var i = 0; i
_classCallCheck
方法判断调用的方式,防止 Fruit()
这样直接调用。_createClass
方法在 prototype
上添加公用方法,在 Fruit
上添加静态方法。"use strict";
function _typeof(obj) {
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof = function _typeof(obj) {
return typeof obj;
};
} else {
_typeof = function _typeof(obj) {
return obj &&
typeof Symbol === "function" &&
obj.constructor === Symbol &&
obj !== Symbol.prototype
? "symbol"
: typeof obj;
};
}
return _typeof(obj);
}
function _possibleConstructorReturn(self, call) {
if (call && (_typeof(call) === "object" || typeof call === "function")) {
return call;
}
return _assertThisInitialized(self);
}
function _assertThisInitialized(self) {
if (self === void 0) {
throw new ReferenceError(
"this hasn‘t been initialised - super() hasn‘t been called"
);
}
return self;
}
// 获取对象原型
function _getPrototypeOf(o) {
_getPrototypeOf = Object.setPrototypeOf
? Object.getPrototypeOf
: function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf(o);
}
/**
*
* Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。
* @param {*} superClass
*/
function _inherits(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: { value: subClass, writable: true, configurable: true }
});
// 没有这一步的话,就拿不到父类的属性
if (superClass) _setPrototypeOf(subClass, superClass);
}
// 设置对象原型
function _setPrototypeOf(o, p) {
_setPrototypeOf =
Object.setPrototypeOf ||
function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf(o, p);
}
function _instanceof(left, right) {
if (
right != null &&
typeof Symbol !== "undefined" &&
right[Symbol.hasInstance]
) {
return !!right[Symbol.hasInstance](left);
} else {
return left instanceof right;
}
}
function _classCallCheck(instance, Constructor) {
if (!_instanceof(instance, Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties(target, props) {
for (var i = 0; i
_inherits
方法基于父类的 prototype
创建了一个新的对象,赋给了子类的 prototype
。还将子类的 __proto__
指向了父类,为的是继承父类的属性。prototype
上定义子类自己的方法。this
的值。 ES2015+ 方式语法点
class
class
关键字可以定义类。类有下面一些特点:
new
调用,否则会报错。static
关键字。this
指向类的实例。constructor
constructor
是构造方法,通过 new
命令生成对象实例时,自动调用该方法。一个类必须有 constructor
方法,如果没有显式定义,一个空的 constructor
方法会被默认添加。class A {}
let obj = new A();
console.info(obj.constructor === A.prototype.constructor);
extends
class
继承通过 extends
实现。继承时,类中构造函数必须要执行 super
方法,否则创建实例的时候会报错。class A {}
class B extends A {
constructor() {
}
}
let obj = new B();
// VM55958:3 Uncaught ReferenceError: Must call super constructor in derived class before accessing ‘this‘ or returning from derived constructor
class A {}
class B extends A {}
// 等同于
class B extends A {
constructor(...args) {
super(...args)
}
}
super
super
关键字可以当做函数或对象使用。使用 super
的时候,必须显式指定是作为函数、还是作为对象使用,否则会报错。函数使用
对象使用
参考资料
上一篇:python中的解包
文章标题:JavaScript 新旧替换四:继承
文章链接:http://soscw.com/index.php/essay/42317.html