1 2module.exports = ProtoList 3 4function setProto(obj, proto) { 5 if (typeof Object.setPrototypeOf === "function") 6 return Object.setPrototypeOf(obj, proto) 7 else 8 obj.__proto__ = proto 9} 10 11function ProtoList () { 12 this.list = [] 13 var root = null 14 Object.defineProperty(this, 'root', { 15 get: function () { return root }, 16 set: function (r) { 17 root = r 18 if (this.list.length) { 19 setProto(this.list[this.list.length - 1], r) 20 } 21 }, 22 enumerable: true, 23 configurable: true 24 }) 25} 26 27ProtoList.prototype = 28 { get length () { return this.list.length } 29 , get keys () { 30 var k = [] 31 for (var i in this.list[0]) k.push(i) 32 return k 33 } 34 , get snapshot () { 35 var o = {} 36 this.keys.forEach(function (k) { o[k] = this.get(k) }, this) 37 return o 38 } 39 , get store () { 40 return this.list[0] 41 } 42 , push : function (obj) { 43 if (typeof obj !== "object") obj = {valueOf:obj} 44 if (this.list.length >= 1) { 45 setProto(this.list[this.list.length - 1], obj) 46 } 47 setProto(obj, this.root) 48 return this.list.push(obj) 49 } 50 , pop : function () { 51 if (this.list.length >= 2) { 52 setProto(this.list[this.list.length - 2], this.root) 53 } 54 return this.list.pop() 55 } 56 , unshift : function (obj) { 57 setProto(obj, this.list[0] || this.root) 58 return this.list.unshift(obj) 59 } 60 , shift : function () { 61 if (this.list.length === 1) { 62 setProto(this.list[0], this.root) 63 } 64 return this.list.shift() 65 } 66 , get : function (key) { 67 return this.list[0][key] 68 } 69 , set : function (key, val, save) { 70 if (!this.length) this.push({}) 71 if (save && this.list[0].hasOwnProperty(key)) this.push({}) 72 return this.list[0][key] = val 73 } 74 , forEach : function (fn, thisp) { 75 for (var key in this.list[0]) fn.call(thisp, key, this.list[0][key]) 76 } 77 , slice : function () { 78 return this.list.slice.apply(this.list, arguments) 79 } 80 , splice : function () { 81 // handle injections 82 var ret = this.list.splice.apply(this.list, arguments) 83 for (var i = 0, l = this.list.length; i < l; i++) { 84 setProto(this.list[i], this.list[i + 1] || this.root) 85 } 86 return ret 87 } 88 } 89