set.js 2.4 KB

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