关于for-in循环

循环数据时, 强烈不推荐使用for-in循环.因为当Array对象被扩展后, 再用for-in循环遍历数据会导致逻辑上的错误, 举例说明:

var arr = ['a', 'b', 'c'];
// 下标遍历
for(var i=0, len=arr.length; i<len; i++) {
console.info(typeof i); // number
console.info(i);
}
// for-in遍历
for(var i in arr) {
console.info(typeof i); // string
console.info(i);
}
console.log(arr.length); //

此时, for-in遍历数组时, i的类型为string, 已不再是数组的下标, 而是作为数组对象的key出现的(Javascript中数组也是对象).

若在遍历前加上以下代码, 则for-in循环将出现逻辑上的错误

if(typeof Array.prototype.len === 'undefined') {
Array.prototype.len = function() {
return this.length;
};
}

即给数组添加原型方法len()

console.log(arr.length); // 输出仍为3

但for-in循环却同时将len输出出来了, 这说明for-in确实是将Array当成一个Object来遍历的, len作为对象的一个属性自然也会被遍历出来.

总之, 我们可以不乱在原型上添加方法, 不能保证别人不会, 所以最好是不要使用for-in循环数组.

当使用for-in遍历一个对象时, 一般与hasOwnProperty()一起使用, hasOwnProperty()用于过滤原型属性或原型方法, 举例说明:

// 定义一个person对象, 包含两个属性和一个方法
var person = {
name: '张三',
age: 28,
say: function() {
// ...
}
}
// 在Object上扩展一个方法sleep()
if(typeof Object.prototype.sleep === 'undefined') {
Object.prototype.sleep = function() {
// ...
}
}
// 使用hasOwnProperty()的for-in循环
for(var i in person) {
if(person.hasOwnProperty(i)) {
console.info(i);
}
}
/*
控制台打印结果:
name
age
say
*/
// 不使用hasOwnProperty()的for-in循环
for(var i in person) {
console.info(i);
}
/*
控制台打印结果:
name
age
say
sleep
*/

需要说明的是, 不使用hasOwnProperty()并没有错, 只是可能会对循环结果带来一些混乱, 如果自己的代码有足够信心, 可以不hawOwnProperty(), 还可以稍微提高循环速度.

不要增加内置的原型

给内置原型增加方法或属性是很强大的一个功能, 但正是由于它的强大, 往往会给维护带来巨大的成本. 此外, 如上面所述, 如果给扩展了内置原型, 在没有使用hasOwnProperty()的循环中会导致一些混乱.

如果, 一定要扩展原型, 那么要先检查自定义的属性或方法是否已经存在, 若不存在再进行扩展, 此外一定要用文档记录下来, 以便团队交流. 以下模式可以用来扩展原型:

if(typeof Object.prototype.myMethod === 'undefined') {
Object.prototype.myMethod = function() {
// ...
}
}

避免使用隐匿的类型转换

Javascript存在隐匿的类型转换, 比如fasle == 0, “” == 0这类的比较语句都回返回true, 在一定程度上会引起混淆, 类型不清.

所以建议在比较比较语句中使用===和!==比较数值和类型

避免使用eval()

第一句话”eval()是魔鬼”

一般提前编写好的代码是不需要使用eval()的, 如果代码是在运行过程中动态生成的, 可能需要使用eval()让其转换为Javascript代码, 但有更好的方法来代替eval(), 此类情况多数出现在处理ajax返回值时, 例如:

// ajax请求返回一个字符串"name", 要给一个对象obj添加一个属性, 并以name作为属性名, '张三'作为属性值
var property = "name";
var obj = {
age: 22
};
// 反模式, 不要使用
// eval('obj.' + property + '= "z3"');
// 推荐
obj[property] = '张三';
for(var i in obj) {
console.info(i);
}

使用eval()也包含一些隐患, 有可能会执行一些被篡改过的代码.

同时, setInterval()和setTimeout()的调用与eval()有类似的问题

// 反模式
setTimeout(“myFunc()”, 1000);
setTimeout(“myFunc(2, 5, 7)”, 1000);
// 推荐
setTimeout(myFunc, 1000);
setTimeout(function(){
myFunc(2, 5, 7);
}, 1000);

如果一定要使用eval(), 那么可以考虑是否可以用new Function()来代替eval().

因为使用new Function()代码将在一个局部函数空间中运行, 任何使用var定义的变量不会自动成为全局变量, 例如:

new Function("var p = 3; console.info(p);")(); //
console.info(p); // ReferenceError: p is not defined
eval("var p1 = 4; console.info(p1);"); //
console.info(p1); //

另一个防止自动成为全局变量的方法是将eval()封闭到一个立即执行函数中, 如:

(function(){
eval('var num = 11; console.info(num);'); //
})();
console.info(num); // ReferenceError: p is not defined

new Function()和eval()的另一个区别是, eval()会影响到作用域链, 而new Function()对局部变量的影响比较小.

eval()可以访问和修改它外部作用域的变量, 而new Function()不能. 例子:

(function(){
var num = 13;
eval('var num = 20; console.info(num);'); //
console.info(num); //20, 改变了num的值
})();
(function(){
var num = 12;
new Function('var num = 17; console.info(num);')(); //
console.info(num); //
})();

使用parseInt()的数值约定

这个约定主要是为了解决ECMAScript新旧版本不一致的问题,

在ECMAScript早期的版本中, 0开头的字符串会被当成一个八进制数, 在ECMAScript5中发生了改变, 所以在使用parseInt()方法时, 最好不要忽略第二个参数(进制参数),

例如在处理日期字符串时:

var month = '07',
date = '02';
month = parseInt(month, 10);
date = parseInt(date, 10);

另外, 如果是转换纯数字字符串, 例如'09', 那么使用Number('09')会更效率一些,

如果是非纯数字字符串, 例如'02 hello', 那么只有使用parseInt('02 hello')了, Number('02 hello')会返回NaN

编码约定

书中提到的编码约定, 都为了提高代码的可读性, 降低代码的维护成本,

包括缩进, 空间, 大括号, 命名规则, 空格的使用等.

其中, 要注意的一点是大括号的位置, 由于分号的插入机制, 会导致某些代码执行结果出人意料, 例如:

// 出人意料的返回结果
function func() {
return
{
name: '鸣人'
};
}
console.info(func()); // undefined;
// 以上写法相当于
function func1() {
return undefined;
{
name: '鸣人'
};
}
// 总之, 推荐将大括号放在前面语句的的同一行:
function func3() {
return {
name: '鸣人'
};
}

<<Javascript Patterns>>阅读笔记 -- 第2章 基本技巧(二)的更多相关文章

  1. <<Javascript Patterns>>阅读笔记 -- 第2章 基本技巧(一)

    第一次写这种东西, 有些生涩和蹩脚, 也是为了自己在表达或是总结方面有所提高, 同时为看过的东西留个痕迹, 以便日后查阅. 有错误或是不妥的地方, 还望各位指正, 谢谢! 第1章 简介 本章主要介绍了 ...

  2. <<Javascript Patterns>>阅读笔记 – 第3章 字面量和构造函数

    对象字面量 首先给出对象字面量的定义语法: 1. 将对象定义在一对括号中(左大括号“{”和右大括号”}”) 2. 对象中以逗号分隔属性和方法. 每个属性或方法以key-value的形式出现, key和 ...

  3. 《图解HTTP》阅读笔记--第十一章针对web的攻击技术

    第十一章.针对WEB的攻击技术 ----<图解HTTP>阅读笔记攻击目标---Web简单的HTTP协议本身并不存在安全性 问题,协议本身并不会成为被攻击的对象,应用HTTP的服务器和客户端 ...

  4. 深入理解 C 指针阅读笔记 -- 第六章

    Chapter6.h #ifndef __CHAPTER_6_ #define __CHAPTER_6_ /*<深入理解C指针>学习笔记 -- 第六章*/ typedef struct _ ...

  5. 深入理解 C 指针阅读笔记 -- 第五章

    Chapter5.h #ifndef __CHAPTER_5_ #define __CHAPTER_5_ /*<深入理解C指针>学习笔记 -- 第五章*/ /*不应该改动的字符串就应该用 ...

  6. Javascript权威指南阅读笔记--第3章类型、值和变量(1)

    之前一直有个想法,好好读完JS权威指南,便于自己对于JS有个较为全面的了解.毕竟本人非计算机专业出生,虽然做着相关行业的工作,但总觉得对于基础的掌握并没有相关专业学者扎实,正好因为辞职待业等原因,还是 ...

  7. JavaScript模式读书笔记 第4章 函数

    2014年11月10日 1.JavaScript函数具有两个特点: 函数是第一类对象    函数能够提供作用域         函数即对象,表现为:         -1,函数能够在执行时动态创建,也 ...

  8. 【javascript dom读书笔记】 第九章 CSS-DOM

    用dom设置样式 element.style.property = value 何时用dom脚本设置样式 作者写到:绝大多数的现代浏览器,虽然对css伪类的支持不是很完整,但是对dom都有良好的支持, ...

  9. JavaScript模式读书笔记 文章3章 文字和构造

    1.对象字面量     -1.Javascript中所创建的自己定义对象在任务时候都是可变的.能够从一个空对象開始,依据须要添加函数.对象字面量模式能够使我们在创建对象的时候向其加入函数.       ...

随机推荐

  1. react native 热更新

    一.安装codepush服务 npm install code-push-cli -gcode-push -v 二.创建codepush账号 code-push registercode-push l ...

  2. 驱动学习3.1:获取zynqled的物理地址

    自己想要打印EMIO管脚的物理地址,在SDK提供的头文件中加入printf是无法打印的,基于此 我将需要打印地址的几个函数提取出来,放在main函数中,然后在里面加入printf打印这些用户管脚的地址 ...

  3. 前端PHP入门-019-内置函数之数学函数-很重要

    查看帮助文档为主 函数名 描述 实例 输入 输出 abs() 求绝对值 $abs = abs(-4.2); //4.2 数字 绝对值数字 ceil() 进一法取整 echo ceil(9.999); ...

  4. 前端PHP入门-017-系统内置函数-会查阅API

    大家要知道未来这就是你的工具 如果代码能赚钱,帮你赚钱最多的是基本语法 如果你还在当程序员,你最好的伙伴就是手册 问问你自己:你有CSS2.0/3.0手册,JavaScript手册,Jquery手册, ...

  5. OpenCV---直方图的应用(均衡化和图像比较)

    一:全局直方图均衡化(对比度增强)equalizeHist def equalHist_demo(image): #OpenCV直方图均衡化都是基于灰度图像 gray = cv.cvtColor(im ...

  6. PHP提取链接批量下载

    2014年年初的时候,曾经受委托完成一个视频网站,那时最大的技术障碍是一个大视频比如500MB,在一个带宽环境不怎么快的服务器(比如1Mbps)上提供播放的问题. 这里会遇到两种情况,第一种情况是客户 ...

  7. Configure Always On Availability Group for SQL Server on Ubuntu——Ubuntu上配置SQL Server Always On Availability Group

    下面简单介绍一下如何在Ubuntu上一步一步创建一个SQL Server AG(Always On Availability Group),以及配置过程中遇到的坑的填充方法. 目前在Linux上可以搭 ...

  8. 【CodeForces】576 D. Flights for Regular Customers

    [题目]D. Flights for Regular Customers [题意]给定n个点m条边的有向图,每条边有di表示在经过该边前必须先经过di条边,边可重复经过,求1到n的最小经过边数.n,m ...

  9. 基本控件文档-UITextField属性---iOS-Apple苹果官方文档翻译

    本系列所有开发文档翻译链接地址:iOS7开发-Apple苹果iPhone开发Xcode官方文档翻译PDF下载地址 //转载请注明出处--本文永久链接:http://www.cnblogs.com/Ch ...

  10. Django之原生Ajax操作

    Ajax主要就是使用 [XmlHttpRequest]对象来完成请求的操作,该对象在主流浏览器中均存在(除早起的IE),Ajax首次出现IE5.5中存在(ActiveX控件). 先通过代码来看看Aja ...