pseudomap 项目源码阅读
pseudomap 项目是一个 ES6 之前使用 Map 数据结构的一个工具库,map 的特点在于拓展了对象的键只能是字符串的短板,在 ES6 之前很容易想到使用一个构造函数来实现,同时对于每一个键值关系使用一个新的对象存储,this.key=key;this.value=value
的形式。适合 JavaScript 初学者学习构造函数的使用,同时大神的代码质量还是非常值得学习的!
var hasOwnProperty = Object.prototype.hasOwnProperty module.exports = PseudoMap function PseudoMap (set) { // 检测this的指向来判断该函数是否被当做构造函数运行,使用new实例化 // 构造函数时将改变this的指向为该对象,直接运行函数,this则是指全局对象 if (!(this instanceof PseudoMap)) // whyyyyyyy throw new TypeError("Constructor PseudoMap requires 'new'") this.clear() // 设置传递的参数 if (set) { if ((set instanceof PseudoMap) || (typeof Map === 'function' && set instanceof Map)) set.forEach(function (value, key) { this.set(key, value) }, this) else if (Array.isArray(set)) set.forEach(function (kv) { this.set(kv[0], kv[1]) }, this) else throw new TypeError('invalid argument') } } PseudoMap.prototype.forEach = function (fn, thisp) { thisp = thisp || this Object.keys(this._data).forEach(function (k) { if (k !== 'size') fn.call(thisp, this._data[k].value, this._data[k].key) }, this) } PseudoMap.prototype.has = function (k) { return !!find(this._data, k) } PseudoMap.prototype.get = function (k) { var res = find(this._data, k) // 利用逻辑与的执行特点,不存在时直接返回undefined,这样就不需要在find方法中去判断了,妙 return res && res.value } // 存储 PseudoMap.prototype.set = function (k, v) { set(this._data, k, v) } // 删除 PseudoMap.prototype.delete = function (k) { var res = find(this._data, k) if (res) { delete this._data[res._index] this._data.size-- } } PseudoMap.prototype.clear = function () { // 创建一个空对象 var data = Object.create(null) data.size = 0 // 重新设置构造函数的_data属性,不可写,不可枚举防止其被篡改 Object.defineProperty(this, '_data', { value: data, enumerable: false, configurable: true, writable: false }) } // 设置size的get方法返回this._data.size Object.defineProperty(PseudoMap.prototype, 'size', { get: function () { return this._data.size }, set: function (n) {}, enumerable: true, configurable: true }) PseudoMap.prototype.values = PseudoMap.prototype.keys = PseudoMap.prototype.entries = function () { throw new Error('iterators are not implemented in this version') } // 两者相等或者两个都是NaN时返回true,注意逻辑与的优先级大于逻辑或 // Either identical, or both NaN function same (a, b) { return a === b || a !== a && b !== b } // 用来储存键值信息的对象 function Entry (k, v, i) { this.key = k this.value = v this._index = i } function find (data, k) { for (var i = 0, s = '_' + k, key = s; hasOwnProperty.call(data, key); key = s + i++) { if (same(data[key].key, k)) return data[key] } } function set (data, k, v) { // 此时则是重新设置值 for (var i = 0, s = '_' + k, key = s; hasOwnProperty.call(data, key); key = s + i++) { if (same(data[key].key, k)) { data[key].value = v return } } // size自增 data.size++ // 将键值关系作为一个Entry对象储存,这样就避免了传统的对象键只能是字符串的短板 data[key] = new Entry(k, v, key) }
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论