《JavaScript模式》第2章 基本技巧
@by Ruth92(转载请注明出处)
第2章 基本技巧
一、编写可维护的代码
阅读性好
具有一致性
预见性好
看起来如同一个人编写
有文档
编写注释
编写 API 文档
@namespace:用于命名包含以上对象的全局引用的名称。@class:有些命名不当,实际上是指对象或者构造函数。@method:定义对象中的方法和方法名。@param:列举函数使用的参数。其中将参数类型用大括号括起来,并在其后注释参数名及描述。@return:类似于@param,用于描述返回值的,并且该方法没有名称。/**
* 翻转一个字符串
* @param {String} input 输入需要翻转的字符串
* @return {String} 翻转后的字符串
*/
var reverse = function(input) {
// ...
return output;
};
编写可读性强的代码
在编写代码,甚至是编写某个 API 时,心里都要想着该代码可能是要提供给其他人阅读的。
同行互查
二、 尽量少用全局变量
☛ 【全局变量的问题】:
它们在整个 JavaScript 应用或 Web 页面内共享;它们生存于同一个全局命名空间内,总有可能发生命名冲突。
☛ 【创建全局变量的反模式】:
JavaScript 总是出人意料的创建全局变量的原因:
特性1,JavaScript 可直接使用变量,甚至无需声明;
特性2,JavaScript 有暗示全局变量的概念,即任何变量,如果未经声明,就为全局对象所有。
暗示全局变量
function sum(x, y) {
// 反模式:暗示全局变量
result = x + y;
return result;
}
隐式创建全局变量——>带有
var声明的链式赋值// 反模式,不要使用
function foo() {
/**
* 相当于 var a = (b = 0);
* 原因:缘于从右至左的操作符优先级。
*/
var a = b = 0; // a 是局部变量,b 是全局变量
// ...
} // 对链式赋值的所有变量都进行声明
function foo() {
var a, b;
// ...
a = b = 0; // 均为局部变量
}
☛ 【变量释放时的副作用】:
隐含全局变量与明确定义的全局变量有细微的不同之处:在于能否使用 delete 操作符撤销变量。
- 全局变量(这类变量在函数外部创建):使用
var创建,不能删除; - 隐含全局变量(尽管它是在函数内部创建):不使用
var创建,可以删除。
这表明:隐含全局变量严格来讲不是真正的变量,而是全局对象的属性。属性可以通过 delete 操作符删除,但变量不可以。
// 定义三个全局变量
var global_var = 1;
global_novar = 2; // 反模式
(function() {
global_fromfunc = 3; // 反模式
})();
// 企图删除
delete global_var; // false
delete global_novar; // true
delete global_fromfunc; // true
// 测试删除情况
typeof global_var; // 'number'类型
typeof global_novar; // 'undefined' 类型
typeof global_fromfunc; // 'undefined' 类型
☛ 【*访问全局变量】:
如果需要访问不带硬编码处理的标识
window,可以按如下方式,从内嵌函数的作用域访问:var global = (function() {
// this 在函数内部作为一个函数调用时,总是指向该全局对象
return this;
})();
代码运行在严格模式下时,如果你正在开发一个库,可以将库里的代码打包在一个直接函数中,然后在全局作用域中,传递一个引用给
this,把this看成传递到直接函数的一个参数。
三、变量相关的最佳实践
单一
var模式;在声明变量的时候同时初始化,为变量赋初值也是一种好的做法;
为了避免由于变量提升造成的混乱,最好在开始就声明要用的所有变量。
四、循环最佳实践
for循环:缓存数组(或容器)的长度。/**
* for 循环
* 单变量模式,缺陷:创建代码时复制黏贴整个循环容易出错
*/
function looper() {
var i,
max,
myarray = []; // ...
for (i = 0, max = myarray.length; i < max; i++) {
// 处理 myarray[i];
}
} /**
* 改进1:
* 逐步减至 0,通常更快
*/
function looper() {
var i,
max,
myarray = []; // ...
for (i = myarray.length; i--) {
// 处理 myarray[i];
}
} /**
* 改进2:
* 使用 while 循环
*/
function looper() {
var myarray = [],
i = myarray.length; while (i--) {
// 处理 myarray[i]
}
}
for-in循环(枚举,用来遍历非数组对象):使用hasOwnProperty过滤原型链属性// 对象
var man = {
hands: 2,
legs: 2,
heads: 1
}; if (typeof Object.prototype.clone === 'undefined') {
Object.prototype.clone = function() {};
} /**
* for-in 循环
*/
for (var i in man) {
if (man.hasOwnProperty(i)) { // filter
console.log(i, ":", man[i]);
}
} // 在 Object.prototype 中调用该函数
for (var i in man) {
if (Object.prototype.hasOwnProperty.call(man, i)) { // filter
console.log(i, ":", man[i]);
}
} // 缓存较长的属性名
var i,
hasOwn = Object.prototype.hasOwnProperty; for (i in man) {
if (hasOwn.call(man, i)) {
console.log(i, ":", man[i]);
}
} // 格式化的变种:使得循环语句变得可读性更强,且缩进更少
var i,
hasOwn = Object.prototype.hasOwnProperty; for (i in man) if (hasOwn.call(man, i)) {
console.log(i, ":", man[i]);
}
五、编码约定
缩进
应该一直使用大括号并直到将开放的大括号放置在前面语句的同一行
使用分号
空格
六、命名约定
构造函数的首字母大写
构造函数:大骆驼峰式命名法 →
MyConstructor()函数和方法名:小骆驼峰式命名法 →
myFunction()、calculateArea()、getFirstName()分隔单词
基本变量和对象:下划线分隔开各个单词 →
first_name、favorite_band、sold_company_name其他命名模式
常量:全部大写 →
var PI = 3.14私有方法或私有属性:使用一个下划线前缀
var person = {
getName: function() {
return this._getFirst() + ' ' + this._getLast();
},
_getFirst: function() {
// ...
},
_getLast: function() {
// ...
}
};
七、其他
不要增加内置的原型
如果有例外的情形,采用如下模式为原型增加自定义的方法:
if (typeof Object.prototype.myMethod !== 'function') {
Object.prototype.myMethod = function() {
// implementation...
};
}
switch模式可以使用以下模式来提高
switch语句的可读性和健壮性var inspect_me = 0,
result = ''; switch (inspect_me) {
case 0:
result = 'zero';
break;
case 1:
result = 'one';
break;
default:
result = 'unkown';
}
避免使用隐式类型转换,使用
===和!==JavaScript 在使用比较语句时会执行隐式类型转换,这也是为什么执行
false == 0或"" == 0这类比较语句时会返回true避免使用
eval()// 反模式
var property = 'name';
alert(eval('obj.' + property)); // 推荐的方法
alert(obj[property]);
通过
setInterval()、setTimeout()和function()等构造函数来传递参数,在大部分情况下,也会导致类似eval()的隐患,应该尽量避免使用这些函数。// 反模式
setTimeout('myFunc()', 1000);
setTimeout('myFunc(1, 2, 3)', 1000); // 推荐的模式
setTimeout(myFunc, 1000);
setTimeout(function() {
myFunc(1, 2, 3);
}, 1000);
使用
new Function()构造函数与eval()比较类似,因此该函数的使用也需要十分小心。如果一定需要使用
eval(),可以考虑使用new Function()来代替,好处:由于在new Function()中的代码将在局部函数空间中运行,因此代码中任何采用var定义的变量不会自动成为全局变量。另一个避免自动成为全局变量的方法是将
eval()调用封装到一个即时函数中。
使用
parseInt()的数值约定不要忽略第二个进制参数。
parseInt('08 hello', 10) // 8
另一个将字符串转换为数值的方法:
+ "08" // 8
Number('08') // 8
在正式发布时精简代码
在正式发布之前精简脚本是非常重要的,因为这样可以大大缩小 JavaScript 文件,通常可以减少一半左右。
使用代码检查器检查代码,如 JSLint
《JavaScript模式》第2章 基本技巧的更多相关文章
- Javascript模式(第二章基本技巧)------读书笔记
本章主要帮助大家写出高质量的JS代码的方法,模式和习惯,例如:避免使用全局变量,使用单个的var变量声明,缓存for循环的长度变量length等 一.尽量避免使用全局变量 1 每一个js环境都有一个全 ...
- 【javascript模式】Chapter2: 基本 技巧
1 尽量少用全局变量,最好一个应用程式只有一个全局变量 隐含全局变量(不使用var声明)与明确定义的全局变量区别: (1)使用var创建的全局变量(在函数外部声明)不能用delete删除 (2) ...
- Javascript模式(第一章简介)------读书笔记
一:模式 模式是一个通用问题的解决方案,可以提供一个更好的实践经验.有用的抽象化表示和解决一类问题的模板. 本书主要讨论如下三种类型的模式 1 设计模式:可复用面向对象软件的基础,包括singleto ...
- <<Javascript Patterns>>阅读笔记 -- 第2章 基本技巧(一)
第一次写这种东西, 有些生涩和蹩脚, 也是为了自己在表达或是总结方面有所提高, 同时为看过的东西留个痕迹, 以便日后查阅. 有错误或是不妥的地方, 还望各位指正, 谢谢! 第1章 简介 本章主要介绍了 ...
- 【读书笔记】读《JavaScript模式》 - 函数复用模式之现代继承模式
现代继承模式可表述为:其他任何不需要以类的方式考虑得模式. 现代继承方式#1 —— 原型继承之无类继承模式 function object(o) { function F() {}; F.protot ...
- 初涉JavaScript模式系列 阶段总结及规划
总结 不知不觉写初涉JavaScript模式系列已经半个月了,没想到把一个个小点进行放大,竟然可以发现这么多东西. 期间生怕对JS的理解不到位而误导各位,读了很多书(个人感觉JS是最难的oo语言),也 ...
- 《javascript模式--by Stoyan Stefanov》书摘--汇总
<javascript模式--by Stoyan Stefanov>书摘--基本技巧 http://www.cnblogs.com/liubei/p/JavascriptModeLog1. ...
- javascript进阶课程--第一章--函数
javascript进阶课程--第一章--函数 学习要点 了解内存管理 掌握全局函数的使用 知识点 基本类型和引用类型 基本类型值有:undefined,NUll,Boolean,Number和Str ...
- javascript进阶教程第一章案例实战
javascript进阶教程第一章案例实战 一.学习任务 通过几个案例练习回顾学过的知识 通过练习积累JS的使用技巧 二.实例 练习1:删除确认提示框 实例描述: 防止用户小心单击了“删除”按钮,在用 ...
随机推荐
- windows系统下Tomcat与Apache服务器集成
说明:此文是看书真实试验成功的,书中提到了不同版本不兼容的问题,但是很荣幸我没碰到,此例可供参考. 本文假设你已经有了java环境和tomcat,你已经熟悉tomcat的应用. Jdk 1.7.0_5 ...
- ajax分页2:jquery.pagination +JSON 动态无刷新分页
静态页面: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w ...
- Expression<Func<T, bool>>
public static Expression<Func<T, bool>> True<T>() { return f => true; } public ...
- 判断一个字符串是否为有效ip地址
bool f (const char *s) { int s1,s2,s3,s4; ) { return false; } if ((s1 & 0xffffff00) || (s2 & ...
- linux内核启动笔记
一. 1.解压 tar xjf linux-2.6.22.6.tar.bz2 2.打补丁 patch -p1 < ../linux-2.6.22.6_jz2440.patch 3.配置 ...
- 隐藏与显示:display/visibility/visible区别
说到标签的隐藏,你们会用到什么呢?display?visibility?还是服务器控件的visible? 显然,这三者都能起到隐藏与显示的效果,但是用途确完全不一样,请看用法与区别: <div ...
- 手机app常见bug积累
经过一年的测试工作,以下是手机APP比较容易出现的错误.之后如果发现了还会继续添加,修改.1.翻页手机客户端,内容超过一页时,上拉加载更多内容,加载错误(容易出现数据重复,图片和文章不匹配,图片重复加 ...
- OpenCV之响应鼠标(四):在图像上绘制出矩形并标出起点的坐标
涉及到两方面的内容:1. 用鼠标画出矩形.2.在图像上绘制出点的坐标 用鼠标绘制矩形,涉及到鼠标的操作,opencv中有鼠标事件的介绍.需要用到两个函数:回调函数CvMouseCallback和注册回 ...
- Hadoop 重启各个节点
对于datanode可以在master中配置,然后在maste启动的时候,一并去启动这些节点 .对于死掉的节点,也可以通过以下命令启动 .重启挂掉的节点进入到 挂掉的机器 bin/hadoop-dae ...
- Python的平凡之路(1)
2016-07-26 一.Python简介 Python是一种解释型.面向对象.动态数据类型的高级程序设计语言.它的特点如下: 面向对象.解释语言.交互性.模块化.动态性.高级语言.可移植.可 ...