89 lines
2.2 KiB
JavaScript
89 lines
2.2 KiB
JavaScript
|
|
||
|
module.exports = ProtoList
|
||
|
|
||
|
function setProto(obj, proto) {
|
||
|
if (typeof Object.setPrototypeOf === "function")
|
||
|
return Object.setPrototypeOf(obj, proto)
|
||
|
else
|
||
|
obj.__proto__ = proto
|
||
|
}
|
||
|
|
||
|
function ProtoList () {
|
||
|
this.list = []
|
||
|
var root = null
|
||
|
Object.defineProperty(this, 'root', {
|
||
|
get: function () { return root },
|
||
|
set: function (r) {
|
||
|
root = r
|
||
|
if (this.list.length) {
|
||
|
setProto(this.list[this.list.length - 1], r)
|
||
|
}
|
||
|
},
|
||
|
enumerable: true,
|
||
|
configurable: true
|
||
|
})
|
||
|
}
|
||
|
|
||
|
ProtoList.prototype =
|
||
|
{ get length () { return this.list.length }
|
||
|
, get keys () {
|
||
|
var k = []
|
||
|
for (var i in this.list[0]) k.push(i)
|
||
|
return k
|
||
|
}
|
||
|
, get snapshot () {
|
||
|
var o = {}
|
||
|
this.keys.forEach(function (k) { o[k] = this.get(k) }, this)
|
||
|
return o
|
||
|
}
|
||
|
, get store () {
|
||
|
return this.list[0]
|
||
|
}
|
||
|
, push : function (obj) {
|
||
|
if (typeof obj !== "object") obj = {valueOf:obj}
|
||
|
if (this.list.length >= 1) {
|
||
|
setProto(this.list[this.list.length - 1], obj)
|
||
|
}
|
||
|
setProto(obj, this.root)
|
||
|
return this.list.push(obj)
|
||
|
}
|
||
|
, pop : function () {
|
||
|
if (this.list.length >= 2) {
|
||
|
setProto(this.list[this.list.length - 2], this.root)
|
||
|
}
|
||
|
return this.list.pop()
|
||
|
}
|
||
|
, unshift : function (obj) {
|
||
|
setProto(obj, this.list[0] || this.root)
|
||
|
return this.list.unshift(obj)
|
||
|
}
|
||
|
, shift : function () {
|
||
|
if (this.list.length === 1) {
|
||
|
setProto(this.list[0], this.root)
|
||
|
}
|
||
|
return this.list.shift()
|
||
|
}
|
||
|
, get : function (key) {
|
||
|
return this.list[0][key]
|
||
|
}
|
||
|
, set : function (key, val, save) {
|
||
|
if (!this.length) this.push({})
|
||
|
if (save && this.list[0].hasOwnProperty(key)) this.push({})
|
||
|
return this.list[0][key] = val
|
||
|
}
|
||
|
, forEach : function (fn, thisp) {
|
||
|
for (var key in this.list[0]) fn.call(thisp, key, this.list[0][key])
|
||
|
}
|
||
|
, slice : function () {
|
||
|
return this.list.slice.apply(this.list, arguments)
|
||
|
}
|
||
|
, splice : function () {
|
||
|
// handle injections
|
||
|
var ret = this.list.splice.apply(this.list, arguments)
|
||
|
for (var i = 0, l = this.list.length; i < l; i++) {
|
||
|
setProto(this.list[i], this.list[i + 1] || this.root)
|
||
|
}
|
||
|
return ret
|
||
|
}
|
||
|
}
|