Node Package: options

options

A very light-weight in-code option parsers for node.js.
一个非常轻量的在代码内的NodeJS选项解析器。

大致的作用就是解析、重设、合并、拷贝、读取、验证选项,源代码非常短,本文就做一个简单的解读。

这个包非常底层,没有依赖其他的第三方包(叶子包),而且被广泛地引用,在自行开发包的时候可以引用一下。

这个包是只支持Node的,不适用于浏览器,因为它主要操作配置文件,引用了NodeJS的 fs 包。


代码注释

老实说这个代码写得真不怎么样。

/*!
 * Copyright(c) 2011 Einar Otto Stangvik <einaros@gmail.com>
 * MIT Licensed
 */

var fs = require('fs');
/**
 * Options 是一个类,其构造函数的仅有一个参数:默认选项。
 * @params: defaults, 默认的参数选项
 * @note: defaults在代码中会以闭包的形式保存(老实说这不是一个好方法)
 * @note: 没有在Options中使用原型来生成方法
 * @note: 成员变量设定不清楚
 */
function Options(defaults) {
  var internalValues = {};
  var values = this.value = {}; // 老实说通读了代码我觉得这个变量就是鸡肋
  // 将defaults深拷贝到internalValues中
  Object.keys(defaults).forEach(function(key) {
    internalValues[key] = defaults[key];
    // 定义对象的属性
    Object.defineProperty(values, key, {
      get: function() { return internalValues[key]; }, // 偷梁换柱地重载了getter
      configurable: false, // 不可配置
      enumerable: true // 可枚举
    });
  });
  /**
   * reset: 重置选项
   * @return: Options对象自身
   *  */ 
  this.reset = function() {
    // 将defaults深拷贝到internalValues中
    Object.keys(defaults).forEach(function(key) {
      internalValues[key] = defaults[key];
    });
    return this;
  };
  /**
   * Merge: 合并选项
   * @params: options, 需要合并的选项
   * @params: required, options 中要包含的键的数组
   * @throw: 当 required 中某值key使得 options[key] == undefined 时
   * @return: Options对象自身
   *  */
  this.merge = function(options, required) {
    // 初始化新的options
    options = options || {};
    // 若 required 是数组
    if (Object.prototype.toString.call(required) === '[object Array]') {
      // 遍历 required, 检查options与required之间是否missing。
      var missing = []; // 注意此处的变量提升
      for (var i = 0, l = required.length; i < l; ++i) {
        var key = required[i];
        if (!(key in options)) {
          missing.push(key);
        }
      }
      // missing 报错 
      if (missing.length > 0) {
        if (missing.length > 1) {
          throw new Error('options ' +
            missing.slice(0, missing.length - 1).join(', ') + ' and ' +
            missing[missing.length - 1] + ' must be defined');
        }
        else throw new Error('option ' + missing[0] + ' must be defined');
      }
    }
    // 将options中的值深拷贝入internalValues
    Object.keys(options).forEach(function(key) {
      if (key in internalValues) {
        internalValues[key] = options[key];
      }
    });
    return this;
  };
  /**
   * copy: 拷贝选项
   * @params: keys, 需要拷贝的键的数组。
   * @return: 新的对象
   *  */ 
  this.copy = function(keys) {
    var obj = {};
    // 将defaults中所有在keys中的键找出来复制到obj中。
    // 吐槽: 照理说不是应该遍历keys比较正常吗
    Object.keys(defaults).forEach(function(key) {
      if (keys.indexOf(key) !== -1) {
        obj[key] = values[key];
      }
    });
    return obj;
  };
  /**
   * read: 从文件中以JSON格式读取选项
   * @params: filename, 文件名
   * @params: cb, 回调函数
   * @note: 当cb未定义时使用同步读取方式,否则使用异步。
   * @return: Options对象自身
   *  */ 
  this.read = function(filename, cb) {
    // 判断cb的类型
    if (typeof cb == 'function') {
      // 异步读取
      var self = this;
      fs.readFile(filename, function(error, data) {
        if (error) return cb(error); // 将error回传给回调
        var conf = JSON.parse(data); // JSON格式解析
        self.merge(conf); // 将options合并
        cb(); // 吐槽: 作者的设计是就是不给回调任何关于data的信息
      });
    }
    else {
      // 同步读取
      var conf = JSON.parse(fs.readFileSync(filename));
      this.merge(conf); // 吐槽: 你倒是嵌套地彻底一些啊
    }
    return this;
  };
  /**
   * isDefined: 谓词:某个参数是否被定义
   * @params: key, 某个参数
   * @return: boolean值, 此参数是否被定义
   *  */ 
  this.isDefined = function(key) {
    return typeof values[key] != 'undefined';
  };
  /**
   * isDefinedAndNonNull: 谓词:判断某个参数是否被定义且非空
   * @params: key, 某个参数
   * @return: boolean值, 此参数是否被定义且非空
   *  */ 
  this.isDefinedAndNonNull = function(key) {
    return typeof values[key] != 'undefined' && values[key] !== null;
  };
  // 冻结对象
  Object.freeze(values); // 冻结默认值
  Object.freeze(this); // 冻结
}
// 导出Options类
module.exports = Options;

读后感大概就是MDZZ。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值