/** * 获取值的类型字符串 * @param {*} val - 任意值 * @returns {string} 类型名称,如 'String' 'Number' 'Array' 'Null' 'Undefined' * @example * Object.getTypeString('hello') // 'String' * Object.getTypeString(123) // 'Number' * Object.getTypeString(null) // 'Null' */ Object.getTypeString = function (val) { return Object.prototype.toString.call(val).replace(/\[object |]/g, ''); }; /** * 解析路径字符串为键数组 * @param {string} path - 路径字符串,支持点分隔、特殊键名、混合格式 * @returns {string[]} 键数组 * @private */ const _parsePath = (path) => { const keys = []; const keyRegex = /\[['"]([^'"]+)['"]\]|[^.\[\]]+/g; let match; while ((match = keyRegex.exec(path)) !== null) { keys.push(match[1] || match[0]); } return keys; }; /** * 安全获取对象嵌套属性 * @param {string} path - 属性路径,支持多种格式: * - 普通点分隔: 'a.b.c' * - 特殊键名: "['key.with.dot']" * - 混合: "['a.b'].c['d.e']" * @param {*=} defaultValue - 路径不存在或值为 undefined 时返回的默认值 * @returns {*} 找到的属性值或默认值 * @example * { a: { b: { c: 1 } } }.getPro('a.b.c') // 1 * { a: { b: { c: 1 } } }.getPro('a.x.y', 'default') // 'default' * { 'x.y': { z: 2 } }.getPro("['x.y'].z") // 2 */ Object.prototype.getPro = function (path, defaultValue) { let result = this; for (const key of _parsePath(path)) { if (result == null) return defaultValue; result = result[key]; } return result !== undefined ? result : defaultValue; }; /** * 设置对象嵌套路径值(自动创建中间对象) * @param {string} path - 属性路径,格式同 getPro * @param {*} value - 要设置的值 * @returns {void} * @example * const obj = {}; * obj.setPro('a.b.c', 1); // obj => { a: { b: { c: 1 } } } * obj.setPro("['x.y'].z", 2); // obj => { a: {...}, 'x.y': { z: 2 } } */ Object.prototype.setPro = function (path, value) { const keys = _parsePath(path); let target = this; for (let i = 0; i < keys.length - 1; i++) { if (target[keys[i]] == null || typeof target[keys[i]] !== 'object') { target[keys[i]] = {}; } target = target[keys[i]]; } target[keys[keys.length - 1]] = value; };