Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Module Cache導致inherits共用錯誤 #3

Open
b60413 opened this issue May 4, 2016 · 1 comment
Open

Module Cache導致inherits共用錯誤 #3

b60413 opened this issue May 4, 2016 · 1 comment

Comments

@b60413
Copy link

b60413 commented May 4, 2016

目的

最近初學node.js,
想要自己嘗試寫一個Map module讓其他module去繼承,
但是require module的cache機制導致inherits的module共用了同一個map,
請問應該如何修改才有辦法讓各module有自己的map?

使用的工具

ubuntu 12.04
node.js 4.4.3

操作流程

node server.js

遇到的問題

目的已詳述

嘗試過的解法

應該是架構問題, 完全不知道該從何處下手
(想過用不同的路徑載入Map Module, 但就捨棄了module cache的機制)

程式碼

-----server.js-----

//Load Library
var Player_list_lib = require(global.LIB_DIR + '/player_list_lib');
var Monster_list_lib = require(global.LIB_DIR + '/monster_list_lib');

//Create Monster
for (var monster_index = 1; monster_index <= 3; ++monster_index) {  
    Monster_list_lib.set(monster_index, 'a');
}

//Show Map
console.log(Monster_list_lib.keys());
console.log(Player_list_lib.keys());

-----map.js-----

/**
 * Map Library
 */
function Map_lib() {
    /**
     * Map
     */
    _map = {};

    /**
     * Map Count
     */
    this.size = 0;
}

/**
 * Get
 * @param key
 * @param default_val
 */
Map_lib.prototype.get = function(key, default_val) {
    //Initail Parameter
    default_val = default_val || undefined;

    //Check Key Exists
    if ( ! _map.hasOwnProperty(key)) {
        return default_val;
    }

    //Response Item
    return _map[key];
};

/**
 * Set
 * @param key
 * @param value
 */
Map_lib.prototype.set = function(key, value) {
    //Set Item
    _map[key] = value;

    //Increase Map Count
    ++this.size;
};

/**
 * Has
 * @param key
 * @returns {Boolean}
 */
Map_lib.prototype.has = function(key) {
    return _map.hasOwnProperty(key);
};

/**
 * Remove
 * @returns mixed
 */
Map_lib.prototype.remove = function(key) {
    //Check Map Count
    if (this.size < 1) {
        return;
    }

    //Check Key Exists
    if ( ! _map.hasOwnProperty(key)) {
        return;
    }

    //Remove
    delete _map[key];

    //Decrease Map Count
    --this.size;
};

/**
 * Get Map Size
 * @returns {Number}
 */
Map_lib.prototype.size = function() {
    return this.size;
};

/**
 * Clear Map
 */
Map_lib.prototype.clear = function() {
    //Re-initial Map
    _map = {};

    //Re-initial Map Count
    this.size = 0;
};

/**
 * Get Entries
 * @returns {Array}
 */
Map_lib.prototype.entries = function() {
    //Initial List
    var list = [];

    //Deal With Map
    this.keys().forEach(function(key) {
        list.push([key, _map[key]]);
    }, this);

    //Response List
    return list;
};

/**
 * Get Keys
 * @returns {Array}
 */
Map_lib.prototype.keys = function() {
    return Object.keys(_map);
};

/**
 * Get Values
 * @returns {Array}
 */
Map_lib.prototype.values = function() {
    //Initial List
    var list = [];

    //Deal With Map
    this.keys().forEach(function(key) {
        list.push(_map[key]);
    }, this);

    //Response List
    return list;
};

//Export
module.exports = Map_lib;

-----Player_list_lib.js / Monster_list_lib.js-----

//Load Module
var util = require('util');

//Load Library
var Map_lib = require(global.LIB_DIR + '/map_lib');

/**
 * Constructor
 */
function Player_list_lib() {
    //Parent Constructor
    Player_list_lib.super_.apply(this, arguments);
};

/**
 * Instance
 */
Player_list_lib._instance = undefined;

/**
 * Get Instance
 */
Player_list_lib.getInstance = function() {
    if (this._instance === undefined) {
        this._instance = new Player_list_lib();
    }

    return this._instance;
};

//Inherits 'List_lib'
util.inherits(Player_list_lib, Map_lib);

//Exports
module.exports = Player_list_lib.getInstance();

輸出

[ '1', '2', '3' ]
[ '1', '2', '3' ]

@chentsulin
Copy link

chentsulin commented May 10, 2016

require 進來的的東西是個 singleton,然後做了 prototype 繼承所以共用同一個物件

https://github.com/nodejs/node/blob/master/lib/util.js#L896:

exports.inherits = function(ctor, superCtor) {

  if (ctor === undefined || ctor === null)
    throw new TypeError('The constructor to "inherits" must not be ' +
                        'null or undefined');

  if (superCtor === undefined || superCtor === null)
    throw new TypeError('The super constructor to "inherits" must not ' +
                        'be null or undefined');

  if (superCtor.prototype === undefined)
    throw new TypeError('The super constructor to "inherits" must ' +
                        'have a prototype');

  ctor.super_ = superCtor;
  Object.setPrototypeOf(ctor.prototype, superCtor.prototype);
};

可以去了解一下 prototype 繼承跟一般 class 繼承差在哪

js 實作繼承的招數太多,有七八種以上,可參考
http://shichuan.github.io/javascript-patterns/#code-reuse-patterns

甚至用 plain object 都可以做到大部份繼承想要做到的事

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants