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
 | |
|     }
 | |
|   }
 |