proto-list.js 2.2 KB

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