JS如何实现obj["a"].toNumber()将对应对象键值转为数字
核心认知澄清
- 你最初写的
obj.prototype.toNumber代码本身无法生效:普通对象obj只是某个类的实例,不是构造函数,只有构造函数才自带prototype属性,普通实例访问prototype会得到undefined,根本没法通过这个路径挂载方法。 - 针对你期望的
obj["a"].toNumber()调用形式,方法确实需要挂载在String.prototype,而非普通对象的原型上:因为obj["a"]取出来的是字符串类型的原始值,JS在调用原始值的方法时,会临时将它包装为String类型的实例,只有挂在String原型上的方法,才能被这个临时实例访问到。 - 这种挂载方式有无法规避的硬伤:哪怕成功在String原型上定义了
toNumber方法,也没法实现“直接修改obj中对应键值”的预期。原因很简单:执行到obj["a"]时,就已经把字符串"33"读出来了,JS为了让这个原始字符串能调用方法,会临时生成一个存着"33"的String包装对象——这个临时对象和原来的obj没有任何引用关联,既没有任何办法知道自己是从obj的a键读出来的,等方法执行完这个临时对象就会被垃圾回收,对它做的任何修改,都完全不会影响obj上存的a键值。
可落地的实现方案
- 若要严格贴合
xxx.toNumber()的调用形式:在String原型上定义仅负责返回转换结果的方法,调用时手动将返回值赋值回原对象的对应键
示例代码:
注意:直接修改内置对象的原型属于全局“猴子补丁”,如果项目内其他代码或第三方库存在同名方法,极易引发命名冲突,不推荐在大型生产项目中使用。String.prototype.toNumber = function() { // this 指向临时生成的字符串包装实例 return Number(this.valueOf()) } // 实际调用逻辑 obj["a"] = obj["a"].toNumber() - 更稳妥的实现思路:不要在原始值上定义修改方法,直接在普通对象上挂载通用转换逻辑,传入需要修改的键名完成值类型转换
示例代码:
这种方式可以直接修改原对象的键值,也不会因为修改全局原型带来遍历污染、命名冲突的问题。// 给需要做转换的对象定义独立方法,避免全局原型污染 obj.convertKeyToNumber = function(targetKey) { if (typeof this[targetKey] === 'string') { this[targetKey] = Number(this[targetKey]) } } // 调用逻辑 obj.convertKeyToNumber("a")
内容的提问来源于stack exchange,提问作者gANDALF
相关产品推荐
相关产品推荐

