node.js 下使用 util.inherits 來實現繼承


上一篇博客說到了node.js繼承events類實現事件發射和事件綁定函數,其中我們實現了一個公用基類 _base ,然后在模型中差異化的定義了各種業務需要的模型並繼承 _base 公共基類.但是其中的繼承是一筆帶過,今天詳細的說下node.js中繼承.

 

var events=require('events');
var util=require('util');
 
function _base(){
    this.emitter=new events.EventEmitter(this);
};
 
util.inherits(_base,events.EventEmitter); //繼承
 
_base.prototype.onEvent=function(eventName,callback){
    this.emitter.on(eventName,callback);
}
 
_base.prototype.emitEvent=function(eventName,arg){
    this.emitter.emit(eventName,arg);
}
 
module.exports=_base;

 

util 包介紹:

node.js中的util核心包是node.js自帶的核心代碼,其完全用javascript代碼實現,里面實現了一些常用的工具方法.

其中,我們今天要說的繼承方法 inherites 就是util 核心包實現的一個api 

 

util.inherits :

util.inherits(constructor, superConstructor)

此方法有2個參數: 此方法參數針對的都是構造函數

constructor : 構造函數

superConstructor: 父類構造函數

 

分析最上面的代碼:

var events=require('events');
var util=require('util');

node.js 核心代碼都包含上面的2個包,直接 require 引用即可

 

接下來是構造函數:

function _base(){
    this.emitter=new events.EventEmitter(this);
};

此構造函數里定義了一個私有變量 emitter ,細心的人應該發現此私有變量在下面的方法中用到了,為什么會這樣,我們會再下一篇博客中來分析原型對象為何能共享構造函數中的私有變量.(此篇略過)

 

再下來是繼承語法:

util.inherits(_base,events.EventEmitter); //繼承

inherits 把2個構造函數傳入進去到底做了什么?

我們來看下 inherits 的源碼:

exports.inherits = function(ctor, superCtor) {
 ctor.super_ = superCtor;
 ctor.prototype = Object.create(superCtor.prototype, {
 constructor: {
  value: ctor,
  enumerable: false,
  writable: true,
  configurable: true
 }
 });
};

在上面的代碼中 ctor 想要繼承 superCtor ,我們姑且把 ctor 稱作子類, superCtor 稱作父類.

ctor.super_= superCtor;

super_屬性是子類繼承父類時構造函數要寫入的一個屬性值.

 

ctor.prototype=Object.create(superCtor,prototype,{.....});

我們可以看到源碼中子類原型指像父類原型對象.

當通過 new關鍵字創建子類對象時,子類原型對象上的屬性都將會復制一份到子類對象中.就這樣達到了繼承的效果.

 

上面子類原型被Object.create() 方法賦值,那么我們再來看下 Object,create 是何方神聖.

 

Object.create

Object.create(proto [, propertiesObject ])

作用:

通過指定的原型對象和屬性創建一個新的對象.

proto 就是原型對象,

propertiesObject 就是指定的原型對象的屬性,可選屬性(非必填),如何理解這個參數?  它有4個屬性,如下:

var myBlog = Object.create({}, {'blog':{'value':'yijiebuyi', 'writable': false, 'enumerable': false, 'configurable': false}});

我們定義了一個 myBlog 對象引用

通過 Object,create 來賦值, 原型對象為 {} 

propertiesObject 是對應的

{'blog':{'value':'yijiebuyi', 'writable': false, 'enumerable': false, 'configurable': false}}
value: 表示blog 的屬性值;
writable: 表示blog 的屬性值是否可寫;[默認為: false]
enumerable: 表示屬性blog 是否可以被枚舉;[默認為: false]
configurable: 表示屬性blog 是否可以被配置,例如 對obj.a做 delete操作是否允許;[默認為: false]

 

所以:create 函數實現原理就是 指定一個原型對象 obj ,然后把指定屬性(及屬性的配置)指到 原型對象下.

那么最后得到的 myblog 對象是這樣的 {blog: "yijiebuyi"} 

 

那我們知道了 util 中的 inherits 方法內部主要是調用了 Object.create來創建了一個新對象,新對象是基於父類原型對象 superCtor.prototype

另外一個屬性是 constructor ,構造函數new出來的對象都有此屬性,此屬性值是指向了構造函數的引用.我們一般通過此屬性可以得知這個對象是被誰new出來的. 

{
 constructor: {
  value: ctor,
  enumerable: false,
  writable: true,
  configurable: true
 }
 }

如上代碼就是定義了 contructor 屬性,它的值是 ctor ,ctor是什么? 別忘了我們的初衷, ctor正是 inherits 函數傳入的第一個參數,就是子類引用.

所以這個 create 函數創建了一個以父類原型對象為基礎的新對象,同時把 contructor 屬性指向子類構造函數.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM