set.js 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. var staticParseInt = require('./staticParseInt')
  2. var helperGetHGSKeys = require('./helperGetHGSKeys')
  3. var helperCheckCopyKey = require('./helperCheckCopyKey')
  4. var hasOwnProp = require('./hasOwnProp')
  5. var sKeyRE = /(.+)?\[(\d+)\]$/
  6. function setDeepProps (obj, key, isEnd, nextKey, value) {
  7. if (obj[key]) {
  8. if (isEnd) {
  9. obj[key] = value
  10. }
  11. } else {
  12. var index
  13. var rest
  14. var currMatchs = key ? key.match(sKeyRE) : null
  15. if (isEnd) {
  16. rest = value
  17. } else {
  18. var nextMatchs = nextKey ? nextKey.match(sKeyRE) : null
  19. if (nextMatchs && !nextMatchs[1]) {
  20. // 如果下一个属性为数组类型
  21. rest = new Array(staticParseInt(nextMatchs[2]) + 1)
  22. } else {
  23. rest = {}
  24. }
  25. }
  26. if (currMatchs) {
  27. if (currMatchs[1]) {
  28. // 如果为对象中数组
  29. index = staticParseInt(currMatchs[2])
  30. if (obj[currMatchs[1]]) {
  31. if (isEnd) {
  32. obj[currMatchs[1]][index] = rest
  33. } else {
  34. if (obj[currMatchs[1]][index]) {
  35. rest = obj[currMatchs[1]][index]
  36. } else {
  37. obj[currMatchs[1]][index] = rest
  38. }
  39. }
  40. } else {
  41. obj[currMatchs[1]] = new Array(index + 1)
  42. obj[currMatchs[1]][index] = rest
  43. }
  44. } else {
  45. // 如果为数组
  46. obj[currMatchs[2]] = rest
  47. }
  48. } else {
  49. // 如果为对象
  50. obj[key] = rest
  51. }
  52. return rest
  53. }
  54. return obj[key]
  55. }
  56. /**
  57. * 设置对象属性上的值。如果属性不存在则创建它
  58. * @param {Object/Array} obj 对象
  59. * @param {String/Function} property 键、路径
  60. * @param {Object} value 值
  61. */
  62. function set (obj, property, value) {
  63. if (obj && helperCheckCopyKey(property)) {
  64. if ((obj[property] || hasOwnProp(obj, property)) && !isPrototypePolluted(property)) {
  65. obj[property] = value
  66. } else {
  67. var rest = obj
  68. var props = helperGetHGSKeys(property)
  69. var len = props.length
  70. for (var index = 0; index < len; index++) {
  71. if (isPrototypePolluted(props[index])) {
  72. continue
  73. }
  74. var isEnd = index === len - 1
  75. rest = setDeepProps(rest, props[index], isEnd, isEnd ? null : props[index + 1], value)
  76. }
  77. }
  78. }
  79. return obj
  80. }
  81. /**
  82. * Blacklist certain keys to prevent Prototype Pollution
  83. * @param {string} key
  84. */
  85. function isPrototypePolluted(key) {
  86. return key === '__proto__' || key === 'constructor' || key === 'prototype'
  87. }
  88. module.exports = set