之前的几条都不断地重复着for...in循环,它便利好用,但又容易被原型污染。for...in循环最常见的用法是枚举字典中的元素。这里就是从侧面提出不要在共享的Object.prototype中增加可枚举的属性。
这就导致,我们在开发的时候,不能在Object.prototype中添加有用的方法。如,我们想增加一个产生对象属性名数组的allKeys方法将会怎么样?

Object.prototype.allKeys=function(){
var res=[];
for(var key in this){
res.push(key);
}
return res;
}

上面的方法污染了它自身。

({a:1,b:2,c:3}).allKeys();//['allKeys','a','b','c']

可以用之前说的方法改进allKeys方法忽略掉Object.prototype中的属性。

独立为函数

把要添加的方法独立为一个函数。

function allKeys(obj){
var res=[];
for(var key in this){
res.push(key);
}
return res;
}

这样就可以使用,而又可以不污染到原型。for...in循环也不会出错。

设置为不可枚举

如果想在Object.prototype中增加属性,ES5提供了Object.defineProperty方法,可以定义一个对象的属性并指定该属性的元数据。通过设置其可枚举性为false使其在for...in循环中不可见。

Object.defineProperty(Object.prototype,'allKeys',{
value:function(){
var res=[];
for(var key in this){
res.push(key);
}
return res;
},
writable:true,
enumerable:false,
configurable:true
});

调用一下可得

({a:1,b:2,c:3}).allKeys();//['a','b','c']

上面的代码不会污染其他所有Object实例的所有for...in循环。事实上,当你需要增加一个不应该在for...in循环中出现的属性时,Object.defineProperty方法可以用来定义属性。

提示

  • 避免在Object.prototype中增加属性

  • 考虑编写一个函数代替Object.prototype方法

  • 如果你确定需要在Object.prototype中增加属性,使用ES5中的Object.defineProperty方法将它们定义为不可枚举的属性

[Effective JavaScript 笔记]第47条:绝不要在Object.prototype中增加可枚举的属性的更多相关文章

  1. [Effective JavaScript 笔记]第38条:在子类的构造函数中调用父类的构造函数

    示例 场景类 场景图(scene)是在可视化的过程中(如游戏或图形仿真场景)描述一个场景的对象集合.一个简单的场景包含了在该场景中的所有对象(称角色),以及所有角色的预加载图像数据集,还包含一个底层图 ...

  2. [Effective JavaScript 笔记] 第4条:原始类型优于封闭对象

    js有5种原始值类型:布尔值.数字.字符串.null和undefined. 用typeof检测一下: typeof true; //"boolean" typeof 2; //&q ...

  3. [Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符

    “1.0e0”=={valueOf:function(){return true;}} 是值是多少? 这两个完全不同的值使用==运算符是相等的.为什么呢?请看<[Effective JavaSc ...

  4. [Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码

    函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式 ...

  5. [Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法

    js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+ ...

  6. [Effective JavaScript 笔记]第45条:使用hasOwnProperty方法以避免原型污染

    之前的43条,44条讨论了属性的枚举,但都没有彻底地解决属性查找中原型污染的问题.看下面关于字典的一些操作 'zhangsan' in dict; dict.zhangsan; dict.zhangs ...

  7. [Effective JavaScript 笔记]第46条:使用数组而不要使用字典来存储有序集合

    对象属性无序性 js对象是一个无序属性集合. var obj={}; obj.a=10; obj.b=30; 属性a和属性b并没有谁前谁后之说.for...in循环,先输出哪个属性都有可能.获取和设置 ...

  8. [Effective JavaScript 笔记]第66条:使用计数器来执行并行操作

    第63条建议使用工具函数downloadAllAsync接收一个URL数组并下载所有文件,结果返回一个存储了文件内容的数组,每个URL对应一个字符串.downloadAllAsync并不只有清理嵌套回 ...

  9. [Effective JavaScript 笔记]第20条:使用call方法自定义接收者来调用方法

    不好的实践 函数或方法的接收者(即绑定到特殊关键字this的值)是由调用者的语法决定的.方法调用语法将方法被查找的对象绑定到this变量,(可参阅之前文章<理解函数调用.方法调用及构造函数调用之 ...

随机推荐

  1. cocos2d-x 3.0以上版本字体设置问题

    cocos2d-x中的万年大坑,字体总算是有比较好的结局办法了.之前都是CCLabelTTF,CCLabelBMFont,CCLabelAtlas什么的,我只想说一句:好难用!毕竟是做游戏,那么难看的 ...

  2. Object C学习笔记25-文件管理(一)

    在此篇文章中简单记录一下文件管理,在Object C中NSFileManager用于管理文件已经路径.在Object C中的文件路径可以是相对路径也可以是绝对路径.斜线“/”开头,斜线实际上就是一个目 ...

  3. How to set China Azure Storage Connection String

    Configure Visual Studio to access China Azure Storage Open Visual Studio 2012, Server Explorer Add n ...

  4. 获取Web.config配置节

    static string GetAppSetting(string key) { var appSetting = ConfigurationManager.AppSettings[key]; if ...

  5. redis学习笔记——(3)

    7.Redis中的set类型       sadd set value:向set中添加元素value. srem set value:删除set中的元素value. spop set:随机返回并删除s ...

  6. Spring security 和 AOP 学习

    1.Spring security 登录验证拦截器 资源管理拦截器 认证和授权:      认证:登录时候确实存在此用户. 登录要认证!      授权:登录后判断权限级别,然后赋予相应的操作权限. ...

  7. nginx 的中文配置详细解释

    文章转自:http://www.ha97.com/5194.html 更详细的模块参数请参考:http://wiki.nginx.org/Main #定义Nginx运行的用户和用户组 user www ...

  8. Linux 进程管理器 supervixor

    使用 supervisor 管理进程 http://www.cnblogs.com/smail-bao/p/5673434.html http://ju.outofmemory.cn/entry/20 ...

  9. Java String是不可变对象

    基本数据类型和String类型都是值传递,数组,对象等是引用传递 经多方面查找,String很奇特,虽然是引用数据类型,但是采用的却是值传递!!!基本数据类型采用的都是值传递,数组和对象都是引用传递( ...

  10. 【Gym 100733D】Little thief Shi

    题 Shi realized that he was almost out of money, even renting Shitalian lands. Shi was walking on a s ...