之前的几条都不断地重复着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. php利用递归函数实现无限级分类

    相信很多学php的很多小伙伴都会尝试做一个网上商城作为提升自己技术的一种途径.各种对商品分类,商品名之类的操作应该是得心应手,那么就可以尝试下无限级分类列表的制作了. 什么是无限级分类? 无限级分类是 ...

  2. C++成员权限控制(总结)

    1) 前言 在我学习C++的过程中,类中成员的权限控制一直是比较头疼的一个点,一会public,一会又private,还有protected,再加点继承,而且又有公有继承.私有继承,保护继承,所以感觉 ...

  3. java内存优化牛刀小试

    小猿做了两年的c++,上个月竟然被调到java项目,于是第一篇随笔就想八一八java的内存优化. 首先优化这种事,肯定是应该放到最后去做的,不过在写代码的过程中养成良好的习惯也是很重要的.在这里先推荐 ...

  4. 序列化和反序列化的几种方式(DataContractSerializer)(二)

    DataContractSerializer 类 使用提供的数据协定,将类型实例序列化和反序列化为 XML 流或文档. 无法继承此类. 命名空间: System.Runtime.Serializati ...

  5. Day One

    站立式会议 站立式会议内容总结 442 今天完成:学习Android 三种常用的adapter的使用方法,实现主页的可折叠列表 遇到问题:在实现自定义Adapter时,调用出现错误.已解决. 明天计划 ...

  6. __HTML_5读取文件API

    //HTML5 __FileSystemApi <!doctype html> <html> <head> <meta charset="utf-8 ...

  7. 总结css之内联图片的优缺点

    会不会有这样一种感觉?IT技术开发知识面很广也很深,总会有你不懂得问题出现.一个接着一个新的问题,一个接着一个新的挑战. 今天,解读[内联图片],什么是内联图片,使用内联图片的优缺点是什么?这个问题是 ...

  8. (原)java中对象复制、==、equals

    对于基本数据类型而言,即如下八种基本数据类型,int,boolean,char,byte,short,float,double,long. public class test { public sta ...

  9. Java Observer 观察者

    http://www.cnblogs.com/jaward/p/3277619.html 1.API 被观察者 java.util.Observable; public class Observabl ...

  10. log4j使用教程详解(怎么使用log4j2)

    1. 去官方下载log4j 2,导入jar包,基本上你只需要导入下面两个jar包就可以了(xx是乱七八糟的版本号): log4j-core-xx.jar log4j-api-xx.jar 2. 导入到 ...