1.使用Object的直接实例构造轻量级的字典

字典就是可变长的字符串与值得映射集合。JavaScript甚至提供了枚举一个对象属性名的利器——for...in循环。

  1. var dict = { alice : 34 , bob : 24 , chris : 62 } ;
  2. var people = [ ] ;
  3. for(var name in dict){
  4. people.push(name + ":"+ dict [name])
  5. }
  6. people ;

坚持Object的直接实例原则可以使得for...in循环摆脱原型污染的影响。

2.防止原型污染的最简单的方式之一就是一开始就不适用原型。但在ES5之前没有标准的方式创建一个空原型的新对象。你可能会尝试设置一个构造函数的原型属性为null或者undefined。

  1. function C() { }
  2. C.prototype = null ;

但实例化该构造函数仍然得到的是Object的实例。

  1. var o = new C() ;
  2. Object.getPrototypeOf(o) === null ;
  3. Object.getPrototypeOf(o) === Object.prototype ;

ES5首先提供了标准方法来创建一个没有原型的对象。Object.create函数能够使用一个用户指定的原型链和一个属性描述符动态地构造对象。通过简单的传递一个null原型参数和一个空的描述符,我们就可以建立一个真正的空对象。

  1. var x = Object.create(null) ;
  2. Object.getPrototypeOf(o) === null ;

原型污染无法影响这样的对象行为。一些不支持Object.create函数的旧的JavaScript环境可能支持另一种值得一提的方式。在许多环境中,__proto__提供了对对象内部原型链的读写访问。对象字面量语法也支持初始化一个原型链为null的新对象。

3.使用hasOwnProperty方法以避免原型污染

JavaScript的对象操作总是以继承的方式工作。即使是一个空的对象字面量也继承了Object.prototype的大量属性。但它提供的hasOwnProperty可以避免原型污染。

4.绝对不要在Object.prototype中增加可枚举的属性

到目前为止,for...in循环最常见的用法是枚举字典中的元素。如果想允许对字典对象使用for...in循环,那么不要在共享的Object.prototype中增加可枚举的属性。

如下代码:

  1. Object.prototype.allKeys = function(){
  2. var result = [ ] ;
  3. for(var key in this){
  4. result.push(key) ;
  5. }
  6. return result ;
  7. }

遗憾的是,该方法污染了自身。如果你真的想在Object.prototype中增加属性,ES5提供了一种更友好的机制。Object.defineProperty方法可以定义一个对象的属性并指定该属性的元数据。例如,我们可以用与之前完全一样的方式定义上面的属性而通过设置可枚举属性为false使其在for...in循环中不可见。

  1. Object.defineProperty(Object.prototype , allkeys”,{
  2. value : function(){
  3. var result = [ ] ;
  4. for (var key in this){
  5. result.push(key) ;
  6. }
  7. return result ;
  8. },
  9. writable : true ,
  10. enumerable : false ,
  11. configurable : true
  12. });

每当你增加一个不应该在for...in循环中出现的属性时,Object.defineProperty便是你的选择。

 

5.避免在枚举期间修改对象

事实上,ECMAScript标准规定了:

如果被枚举的对象在枚举期间添加了新的属性,那么在枚举期间并不能保证新添加的属性能够被访问。当迭代一个对象时,如果该对象的内容可能会在循环期间被改变,应该使用while循环或经典的for循环来代替for...in循环。

 

6.数组迭代要优先使用for循环而不是for...in循环。

7.迭代方法优于循环。

①JavaScript的闭包是一种为这些模式建立迭代抽象方便的、富有表现力的手法,从而使我们避免复制,粘贴循环头部。ES5为最常用的一些模式提供了便利的方法。Array.prototype.forEach是其中最简单的一个。例如:

  1. for(var i = 0 , n = players.length ; i < n ; i ++){
  2. players[ i ].score++ ;
  3. }

我们可以用下面的代码替换上面的循环:

  1. players.forEach(function(p){
  2. p.score++ ;
  3. }) ;

这段代码不仅更简单可读,而且还消除了终止条件和任何数组索引。

②另一种常见的模式是对数组的每个元素进行一些操作后建立一个新的数组。ES5引入了Array.prototype.map方法使该模式更简单、更优雅。

  1. var trimmed = input.map(function(s){
  2. return s.trim() ;
  3. }) ;

③另一种常见的模式是计算一个新的数组,该数组只包含现有数组的一些元素。Array.prototype.filter使其变得很简便。它需要一个谓词,该谓词是一个函数,如果元素应该存在于新数组中则返回真值否则返回假值。例如,我们可以从价格表中提取出符合一个特定价格区间的列表:

  1. listings.filter(function(listing){
  2. return listing.price >= min && listing.price <=max ;
  3. }) ;

循环只有一点优于迭代函数,那就是前者有控制流操作,如break和continue。

此外,ES5的数组方法some和every可以用于提前终止循环。

8.在类数组对象上复用通用的数组方法

Array.ptototype中的标准方法被设计成其他对象可复用的方法,即使这些对象并没有继承Array。事实证明,许多这样的类数组对象接踵而至地出现在JavaScript的不同地方。在Web平台,DOM的NodeList类是另一个类数组对象的实例。类似document.getElementsByTagName这样的操作会查询Web页面中的节点,并返回NodeList作为搜索的结果。

Effective JavaScript :第五章的更多相关文章

  1. [Effective Java]第五章 泛型

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  2. Effective JavaScript :第二章

    1.熟练掌握闭包 理解闭包要学会三个基本的事实: ①JavaScript允许你引用在当前函数以外定义的变量: 例如: function makeSandwich(){ var magicIngredi ...

  3. Effective JavaScript :第一章

    第一章 一.严格模式与非严格模式 1.在程序中启用严格模式的方式是在程序的最开始增加一个特定的字符串字面量: ‘use strict’ 同样可以在函数体的开始处加入这句指令以启用该函数的严格模式. f ...

  4. Javascript 第五章总结:A trip to Objectville

    前言 在以前的代码中,我们使用 primitive 类型的变量和 procedural manner 来执行脚本.但是,更好的办法是 object-oriented (面向对象)的.作者说:它能让我们 ...

  5. javascript第五章--函数表达式

    ① 递归 ② 闭包 ③ 模仿块级作用域 ④ 私有变量

  6. 读《编写可维护的JavaScript》第五章总结

    第五章 UI层的松耦合 5.1 什么是松耦合 在Web开发中,用户界面是由三个彼此隔离又相互作用的层定义的: HTML是用来定义页面的数据和语义 CSS用来给页面添加样式 JavaScript用来给页 ...

  7. Javascript权威指南——第二章词法结构,第三章类型、值和变量,第四章表达式和运算符,第五章语句

    第二章 词法结构 一.HTML并不区分大小写(尽管XHTML区分大小写),而javascript区分大小写:在HTML中,这些标签和属性名可以使用大写也可以使用小写,而在javascript中必须小写 ...

  8. [Effective JavaScript 笔记]第3章:使用函数--个人总结

    前言 这一章把平时会用到,但不会深究的知识点,分开细化地讲解了.里面很多内容在高3等基础内容里,也有很多讲到.但由于本身书籍的篇幅较大,很容易忽视对应的小知识点.这章里的许多小提示都很有帮助,特别是在 ...

  9. 【JavaScript权威指南(第五版)】笔记之第二部分 客户端JavaScript 第13章~第23章

    第十三章 Web浏览器中的javascript ①   eg:下面两行代码实际上执行的是相同的功能 var answer = 42; window.answer = 42;   ③每个window对象 ...

  10. 【JavaScript权威指南(第五版)】笔记之第一部分 核心javascript (第1章~第12章)

    第一章 javascript概述 ①.javascript是一种松散类型语言;也是一种解释型语言;         第二章 词法结构 ①.大小写敏感         第三章 数据类型和值 ①.isFi ...

随机推荐

  1. 用Canvas,画中国国旗(Canvas基本知识点)

    .getContext("2d")=======>获取绘图接口 //2d .beginPath()========>创建绘图路径开始点 .moveTo(x,y)==== ...

  2. Python_web框架解析

    这一阵正在学习廖雪峰老师的实战课程,这里对其中web.py框架进行一些分析,总结一下学到的东西. 这一部分的课程网站:http://www.liaoxuefeng.com/wiki/001374738 ...

  3. 【原】手写一个promise

    上一篇文章中,我们介绍了Promise的基本使用,在这篇文章中,我们试着自己来写一个Promise,主要是学习Promise的内部机制,学习它的编程思想. !!!备注:本文写的不好,仅供自己学习之用, ...

  4. CHM木马

    一. 弹出计算器 打开EasyCHM,工具 -> 反编译指定的CHM,选择目标文件和反编译工作目录. 进入反编译的工作目录,找到并编辑主页文件,这里是index.html 在<body&g ...

  5. trove命令翻译(上)(只做翻译,未实验效果)

    The trove client is the command-line interface (CLI) for the Database service API and its extensions ...

  6. oc底层方法调用流程

    1.对象方法保存到类对象里面,每个类对象中都有一个方法列表.类方法保存在元类中方法列表 a.通过isa指针去对应的类中查找: b.生成方法编号,根据方法编号查找对应的方法(找到只是最终实现地址,根据地 ...

  7. YARN的capacity调度器主要配置分析

    yarn中一个基本的调度单元是队列. yarn的内置调度器: 1.FIFO先进先出,一个的简单调度器,适合低负载集群.2.Capacity调度器,给不同队列(即用户或用户组)分配一个预期最小容量,在每 ...

  8. 最强DE 战斗力 (nyoj 541)

    题解链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=541 几天前百度题解后用数学知识AC的,后来大牛说这是一道动态规划题. 网上的数学解题链接 ...

  9. linux下如何查询jdk安装路径

    1:echo $JAVA_HOME 使用$JAVA_HOME的话能定位JDK的安装路径的前提是配置了环境变量$JAVA_HOME,否则如下所示,根本定位不到JDK的安装路径 [root@localho ...

  10. HDU 5904 LCIS

    $dp$. 这题的突破口在于要求数字是连续的. 可以分别记录两个串以某个数字为结尾的最长上升长度,然后枚举一下以哪个数字为结尾就可以得到答案了. 因为$case$有点多,不能每次$memset$,额外 ...