为了账号安全,请及时绑定邮箱和手机立即绑定

聊聊 JavaScript 的继承

最近在看 NodeES6,感觉就是 JavaScipt 越来越像 PHP 了。好了,不扯了,直奔主题。这篇文章不是去讲 JS 原型链,而是简单聊聊 ES6 中的 Class,Node 中的 util.inherits(),ES5 中的 Object.create() 方法,及 ES6 中的 Object.setPrototypeOf() 方法。

  • ES6 中引入了 Class 的概念来模拟类。

    JavaScript classes introduced in ECMAScript 6 are syntactical sugar over JavaScript's existing prototype-based inheritance. The class syntax is not introducing a new object-oriented inheritance model to JavaScript. JavaScript classes provide a much simpler and clearer syntax to create objects and deal with inheritance.

以上概念直接引用自 MDN,简单讲就是 ES6 中的 Class 只不过是基于 JS 原型继承层面上的语法糖。下面是 MDN 中的一个示例:

class  Rectangle { 
  constructor(height, width) { 
    this.height = height;
    this.width = width; 
  } 
  get area() { 
    return this.calcArea(); 
  } 
  calcArea() { 
    return this.height * this.width; 
    }
 }
const newRec = new Rectangle (10, 10);
console.log(newRec.area);

其中 class 里面的 constructor 方法会在该 class 每次实例化的时候自动执行。//和 PHP class 里面的 constructor 一样一样的。
在 class 中定义的 函数 可以省略 function 关键字。//我就稍微科普下 ES6 吧。
下面我用传统的 构造函数 来重写一下这个 Retangle 类:

function Rectangle(height, width){
  this.height = height;
  this.width = width;
}
Rectangle.prototype = {
  get area() {
    return this.calcArea();
  },
  calcArea: function(){
    return this.height * this.width;
  }
}
var newRec = new Rectangle(10,10);
console.log(newRec.area);

所以 ES6 中的 class 只不过是一种特殊的函数,如同 函数的定义有两种方式,函数声明 和 函数表达式,同样 class 的定义也有两种方式,类声明 // class foo{...} 和 类表达式 // var foo = class{...} // 继续科普 ES6,其中 函数声明和类声明的区别是,函数声明会致使声明提升, 而 类声明中则不会导致声明提升。
咦?这篇文章的题目不是 JS 继承吗?文章到现在好想一直TM在科普 ES6 的 class 啊!哈哈哈哈哈
class 之间实现继承的方式是通过使用 extends 关键字。//和 PHP一样一样的,包括 静态方法 static 的用法呀balabala...
e.g.

class Square extends Rectangle {
  constructor(length){
    super();
    this.height = length;
    this.width = length;
  }
}
console.log(Square.area);

Class 之间可以通过 extends 关键字实现继承,这比ES5的通过修改原型链实现继承,要清晰和方便很多。
ECMAScript 6 入门

下面是接着之前用构造函数方法写的 Rectangle 继续写传统构造函数实现的继承:

function Square(length){
  Rectangle.apply(this, [arguments[0], arguments[0]])
}
--------
*Method1//不推荐:
Square = new Rectangle(); 
var square = new Square(10);
console.log(Square.area);
--------
*Method2:
Square.prototype = Object.create(Rectangle.prototype)
var square = new Square(10);
console.log(Square.area);

So,

class Super {}
class Sub extends Super {}
//辣么,我们是不是可以把 ES6 中 class 的 extends 简单理解成?:
function Super(){};
function Sub(){};
Sub.prototype = Object.create(Super.prototype);
//答案是不是的
//因为 extends 实现的 class 继承 中:
console.log(Super.prototype.isPrototypeOf(Sub.prototype)) // true;
console.log(Super.isPrototypeOf(Sub)) //true;
//而 通过 Object.create() 方法实现的继承仅仅是
console.log(Super.prototype.isPrototypeOf(Sub.prototype)) //true
// class 继承的实现是://示例引用自阮老师的 《ECMAScript 6 入门》
class A {}
class B {} 
//B的实例继承A的实例
Object.setPrototypeOf(B.prototype, A.prototype);
//B继承A的静态属性
Object.setPrototypeOf(B, A);
// "Object.setPrototypeOf 方法的作用与 __proto__ 相同,用来设置一个对象的 prototype对象。它是ES6正式推荐的设置原型对象的方法。"
// Object.setPrototypeOf 改方法的等同于:
function (obj, proto) { 
  obj.__proto__ = proto; 
  return obj;
}
//MDN 中的 polyfill:
Object.setPrototypeOf = Object.setPrototypeOf || function(obj, proto) { obj.__proto__ = proto; return obj; }
  • Node 中使用的是 utili 这个模块里面的 inherits() 这个方法。

    util.inherits(constructor, superConstructor)
    Inherit the prototype methods from one constructor into another. The prototype of constructor will be set to a new object created from super Constructor.
    As an additional convenience, superConstructor will be accessible through the constructor.super_ property.

上 代码:

"use strict";
const util = require('util');
function Super(){};
function Sub(){};
util.inherits(Sub, Super);
console.log(Super.prototype.isPrototypeOf(Sub.prototype)); // true;
//Buuuuuuuuuuuuut:
console.log(Super.isPrototypeOf(Sub)); // false;

Soooooooooooooo, node 文档中介绍该 util.inherits() 方法的第一句便是:

Note: usage of util.inherits() is discouraged. Please use the ES6 class and extends keywords to get language level inheritance support.


这几个概念到这里就算是草草介绍完了,总体来讲 ES6 中引入的 class ,虽然只是一种语法糖,但是它提供了一种更加简洁、清晰的语法来创建对象以及处理继承关系。

点击查看更多内容
16人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消