为何自定义Array.prototype.top方法会被非Array对象继承?
问题描述
我为Array类型添加了如下扩展方法:
Array.prototype.top = function() { return (this.length > 0) ? this[this.length-1] : null; }
但该方法却被应用到了非Array对象上。例如执行以下代码时:
for (key in myrecordset) { alert(key); // 会遍历并弹出"top" }
在调试控制台得到如下结果:
> myrecordset.length < undefined > typeof myrecordset < 'object' > myrecordset instanceof Array < false > myrecordset['top'] < f() { return (this.length ... }
该对象并非JavaScript数组(无length属性、不是Array实例),却能访问到Array.prototype.top方法?另外查看其原型链时得到:
> myrecordset.constructor() < {} [[ Prototype ]]: Object
原因与解决方案
问题根源
所有JavaScript对象的原型链最终都会指向Object.prototype,而Array.prototype的原型正是Object.prototype。你直接给Array.prototype添加的top方法默认是可枚举属性,当使用for...in循环遍历普通对象时,会遍历对象原型链上所有可枚举的属性,因此会把top方法当成当前对象的属性遍历出来。
解决办法
使用Object.defineProperty给Array.prototype添加方法,并将其设置为不可枚举:
Object.defineProperty(Array.prototype, 'top', { value: function() { return (this.length > 0) ? this[this.length-1] : null; }, enumerable: false, // 核心:禁止枚举 writable: true, configurable: true });
这样for...in循环就不会遍历到top方法,同时数组实例仍然可以正常调用该方法。
注意:尽量避免直接给原生对象原型添加可枚举属性,这种操作很容易引发遍历冲突,尤其是在处理第三方对象时。
内容的提问来源于stack exchange,提问作者Chrys G
相关产品推荐
相关产品推荐

