<<Javascript Patterns>>阅读笔记 -- 第2章 基本技巧(二)
关于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章 基本技巧(二)的更多相关文章
- <<Javascript Patterns>>阅读笔记 -- 第2章 基本技巧(一)
第一次写这种东西, 有些生涩和蹩脚, 也是为了自己在表达或是总结方面有所提高, 同时为看过的东西留个痕迹, 以便日后查阅. 有错误或是不妥的地方, 还望各位指正, 谢谢! 第1章 简介 本章主要介绍了 ...
- <<Javascript Patterns>>阅读笔记 – 第3章 字面量和构造函数
对象字面量 首先给出对象字面量的定义语法: 1. 将对象定义在一对括号中(左大括号“{”和右大括号”}”) 2. 对象中以逗号分隔属性和方法. 每个属性或方法以key-value的形式出现, key和 ...
- 《图解HTTP》阅读笔记--第十一章针对web的攻击技术
第十一章.针对WEB的攻击技术 ----<图解HTTP>阅读笔记攻击目标---Web简单的HTTP协议本身并不存在安全性 问题,协议本身并不会成为被攻击的对象,应用HTTP的服务器和客户端 ...
- 深入理解 C 指针阅读笔记 -- 第六章
Chapter6.h #ifndef __CHAPTER_6_ #define __CHAPTER_6_ /*<深入理解C指针>学习笔记 -- 第六章*/ typedef struct _ ...
- 深入理解 C 指针阅读笔记 -- 第五章
Chapter5.h #ifndef __CHAPTER_5_ #define __CHAPTER_5_ /*<深入理解C指针>学习笔记 -- 第五章*/ /*不应该改动的字符串就应该用 ...
- Javascript权威指南阅读笔记--第3章类型、值和变量(1)
之前一直有个想法,好好读完JS权威指南,便于自己对于JS有个较为全面的了解.毕竟本人非计算机专业出生,虽然做着相关行业的工作,但总觉得对于基础的掌握并没有相关专业学者扎实,正好因为辞职待业等原因,还是 ...
- JavaScript模式读书笔记 第4章 函数
2014年11月10日 1.JavaScript函数具有两个特点: 函数是第一类对象 函数能够提供作用域 函数即对象,表现为: -1,函数能够在执行时动态创建,也 ...
- 【javascript dom读书笔记】 第九章 CSS-DOM
用dom设置样式 element.style.property = value 何时用dom脚本设置样式 作者写到:绝大多数的现代浏览器,虽然对css伪类的支持不是很完整,但是对dom都有良好的支持, ...
- JavaScript模式读书笔记 文章3章 文字和构造
1.对象字面量 -1.Javascript中所创建的自己定义对象在任务时候都是可变的.能够从一个空对象開始,依据须要添加函数.对象字面量模式能够使我们在创建对象的时候向其加入函数. ...
随机推荐
- [JLOI2014] 松鼠的新家 (lca/树上差分)
[JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在 ...
- ASP.NET 使用ajaxupload.js插件出现上传较大文件失败的解决方法
在网上下载了一个ajaxupload.js插件,用于无刷新上传图片使的,然后就按照demo的例子去运行了一下,上传啊什么的都OK,但是正好上传的示例图片有一个比较大的,4M,5M的样子,然后上传就会报 ...
- Spring.Net 入门学习(一)实现控制器翻转与依赖注入
Spring.net IOC:Invasion of Control,控制器翻转,名字由英文翻译过来就是这个意思了,其实用通俗的话来说就是:将创建对象的职责交给控制器来做,这个控制器就是spring了 ...
- IIS7.5 HTTP 错误500.19-Internal Server Error 无法访问请求的页面,因为该页的相关配置数据无效
IIS7.5 HTTP 错误500.19-Internal Server Error 无法访问请求的页面,因为该页的相关配置数据无效 --------------------------------- ...
- Scrapy的安装--------Windows、linux、mac等操作平台
Scrapy安装 Scrapy的安装有多种方式,它支持Python2.7版本及以上或者是Python3.3版本及以上.下面来说py3环境下,scrapy的安装过程. Scrapy依赖的库比较多,至少需 ...
- 贪心+离散化+线段树上二分。。。 Samara University ACM ICPC 2016-2017 Quarterfinal Qualification Contest G. Of Zorcs and Axes
题目链接:http://codeforces.com/gym/101149/problem/G 题目大意:给你n对数字,为(a[i], b[i]),给你m对数字,为(w[i], c[i]).给n对数字 ...
- MongoDB-3.4集群搭建:分片
概念 集群拥有三个节点: 分片(sharding),分发路由(query routers)和配置服务器 (config server) Shard 分片是存储了一个集合部分数据的MongoDB实例,每 ...
- CSS浏览器兼容问题集-第三部分
FF与IE 1. Div居中问题 div设置 margin-left, margin-right 为 auto 时已经居中,IE 不行,IE需要设定body居中,首先在父级元素定义text-algin ...
- 【Foreign】减法 [二分][贪心]
减法 Time Limit: 10 Sec Memory Limit: 256 MB Description 给你一个n个数的序列A,并且给出m次操作B. 操作的含义是:每次从A中选出不同的B_i个 ...
- 【BZOJ】1023: [SHOI2008]cactus仙人掌图 静态仙人掌(DFS树)
[题意]给定仙人掌图(每条边至多在一个简单环上),求直径(最长的点对最短路径).n<=50000,m<=10^7. [算法]DFS树处理仙人掌 [题解]参考:仙人掌相关问题的处理方法(未完 ...