@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 有暗示全局变量的概念,即任何变量,如果未经声明,就为全局对象所有。

  1. 暗示全局变量

    function sum(x, y) {
    // 反模式:暗示全局变量
    result = x + y;
    return result;
    }
  2. 隐式创建全局变量——>带有 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' 类型

☛ 【*访问全局变量】:

  1. 如果需要访问不带硬编码处理的标识 window,可以按如下方式,从内嵌函数的作用域访问:

     var global = (function() {
    // this 在函数内部作为一个函数调用时,总是指向该全局对象
    return this;
    })();
  2. 代码运行在严格模式下时,如果你正在开发一个库,可以将库里的代码打包在一个直接函数中,然后在全局作用域中,传递一个引用给 this,把 this 看成传递到直接函数的一个参数。

三、变量相关的最佳实践

  1. 单一 var 模式;

  2. 在声明变量的时候同时初始化,为变量赋初值也是一种好的做法;

  3. 为了避免由于变量提升造成的混乱,最好在开始就声明要用的所有变量。

四、循环最佳实践

  1. 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]
    }
    }
  2. 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]);
    }

五、编码约定

  1. 缩进

  2. 应该一直使用大括号并直到将开放的大括号放置在前面语句的同一行

  3. 使用分号

  4. 空格

六、命名约定

  1. 构造函数的首字母大写

    构造函数:大骆驼峰式命名法 → MyConstructor()

    函数和方法名:小骆驼峰式命名法 → myFunction()calculateArea()getFirstName()

  2. 分隔单词

    基本变量和对象:下划线分隔开各个单词 → first_namefavorite_bandsold_company_name

  3. 其他命名模式

    常量:全部大写 → var PI = 3.14

    私有方法或私有属性:使用一个下划线前缀

     var person = {
    getName: function() {
    return this._getFirst() + ' ' + this._getLast();
    },
    _getFirst: function() {
    // ...
    },
    _getLast: function() {
    // ...
    }
    };

七、其他

  1. 不要增加内置的原型

    如果有例外的情形,采用如下模式为原型增加自定义的方法:

     if (typeof Object.prototype.myMethod !== 'function') {
    Object.prototype.myMethod = function() {
    // implementation...
    };
    }
  2. switch 模式

    可以使用以下模式来提高 switch 语句的可读性和健壮性

     var inspect_me = 0,
    result = ''; switch (inspect_me) {
    case 0:
    result = 'zero';
    break;
    case 1:
    result = 'one';
    break;
    default:
    result = 'unkown';
    }
  3. 避免使用隐式类型转换,使用 ===!==

    JavaScript 在使用比较语句时会执行隐式类型转换,这也是为什么执行 false == 0"" == 0 这类比较语句时会返回 true

  4. 避免使用 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() 调用封装到一个即时函数中。

  5. 使用 parseInt() 的数值约定

    不要忽略第二个进制参数。

     parseInt('08 hello', 10)	// 8

    另一个将字符串转换为数值的方法:

     + "08" // 8
    Number('08') // 8
  6. 在正式发布时精简代码

    在正式发布之前精简脚本是非常重要的,因为这样可以大大缩小 JavaScript 文件,通常可以减少一半左右。

  7. 使用代码检查器检查代码,如 JSLint

《JavaScript模式》第2章 基本技巧的更多相关文章

  1. Javascript模式(第二章基本技巧)------读书笔记

    本章主要帮助大家写出高质量的JS代码的方法,模式和习惯,例如:避免使用全局变量,使用单个的var变量声明,缓存for循环的长度变量length等 一.尽量避免使用全局变量 1 每一个js环境都有一个全 ...

  2. 【javascript模式】Chapter2: 基本 技巧

    1 尽量少用全局变量,最好一个应用程式只有一个全局变量  隐含全局变量(不使用var声明)与明确定义的全局变量区别:  (1)使用var创建的全局变量(在函数外部声明)不能用delete删除  (2) ...

  3. Javascript模式(第一章简介)------读书笔记

    一:模式 模式是一个通用问题的解决方案,可以提供一个更好的实践经验.有用的抽象化表示和解决一类问题的模板. 本书主要讨论如下三种类型的模式 1 设计模式:可复用面向对象软件的基础,包括singleto ...

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

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

  5. 【读书笔记】读《JavaScript模式》 - 函数复用模式之现代继承模式

    现代继承模式可表述为:其他任何不需要以类的方式考虑得模式. 现代继承方式#1 —— 原型继承之无类继承模式 function object(o) { function F() {}; F.protot ...

  6. 初涉JavaScript模式系列 阶段总结及规划

    总结 不知不觉写初涉JavaScript模式系列已经半个月了,没想到把一个个小点进行放大,竟然可以发现这么多东西. 期间生怕对JS的理解不到位而误导各位,读了很多书(个人感觉JS是最难的oo语言),也 ...

  7. 《javascript模式--by Stoyan Stefanov》书摘--汇总

    <javascript模式--by Stoyan Stefanov>书摘--基本技巧 http://www.cnblogs.com/liubei/p/JavascriptModeLog1. ...

  8. javascript进阶课程--第一章--函数

    javascript进阶课程--第一章--函数 学习要点 了解内存管理 掌握全局函数的使用 知识点 基本类型和引用类型 基本类型值有:undefined,NUll,Boolean,Number和Str ...

  9. javascript进阶教程第一章案例实战

    javascript进阶教程第一章案例实战 一.学习任务 通过几个案例练习回顾学过的知识 通过练习积累JS的使用技巧 二.实例 练习1:删除确认提示框 实例描述: 防止用户小心单击了“删除”按钮,在用 ...

随机推荐

  1. Android selector选择器的使用

    通常按钮在点击前和后有两种状态,比如点击前为蓝色,点击后为灰色,且不再响应点击事件. 如果不使用selector选择器,点击后,就需要在程序中进行以下的类似操作 button1.setBackgrou ...

  2. CI框架 数据库批量插入 insert_batch()

    使用CI框架的AR操作:insert_batch()可以减少访问数据库的次数.一次访问即可. 示例1: $data = array( array( 'title' => 'My title' , ...

  3. RedHat 安装MySQL数据库【转】

      朋友购买了阿里云的服务器,服务器上自带有CentOS操作系统,但是开发软件需要自己安装,接下来将介绍本地RedHat Linux 5.10虚拟机上搭建Mysql数据库. 一.软件准备 (1)jdk ...

  4. css样式书写的问题

    经常遇到前端的朋友问及css样式书写的问题,结合自己实际的工作,自己总结了整理了一下,给大家分享: 一.顺序问题:显示属性-位置属性-元素自身属性-文本属性-其他属性 1.显示属性:z-index.d ...

  5. 如何删除 Ubuntu 上不再使用的旧内核

    提问:过去我已经在我的Ubuntu上升级了几次内核.现在我想要删除这些旧的内核镜像来节省我的磁盘空间.如何用最简单的方法删除Ubuntu上先前版本的内核? 在Ubuntu上,有几个方法来升级内核.在U ...

  6. mysql 远程连接

    4.现在如果用你电脑上的终端进行MySQL连接时,有可能出现如下错误: MySQL远程连接ERROR 2003 (HY000):Can't connect to MySQL server on'XXX ...

  7. 戴文的Linux内核专题:06配置内核(2)

    转自Linux中国 这一部分我们讲配置内核IRQ子系统.中断请求(IRQ)是硬件发给处理器的一个信号,它暂时停止一个正在运行的程序并允许一个特殊的程序占用CPU运行. 这个目录中的第一个问题属于内核特 ...

  8. “人少也能办大事”---K2 BPM老客户交流会

    主题:固铂轮胎工作流项目分享-K2 SmartForm下的工作流快速开发 嘉宾:王彦(固铂轮胎IT资深经理) 国内业务规模越来越大,流程越来越复杂,跨部门跨组织的流程纸质审批非常复杂,内控的要求越来越 ...

  9. VS2013项目配置directx11

    假定你已经安装好了direct11 SDK(官方下的既是最新版本)和VS2013,并在VS2013中建立了一个新工程. 用VS2013打开工程后,点击右键属性,选择VC++目录: 其中在包含目录中添加 ...

  10. OpenCV之响应鼠标(四):在图像上绘制出矩形并标出起点的坐标

    涉及到两方面的内容:1. 用鼠标画出矩形.2.在图像上绘制出点的坐标 用鼠标绘制矩形,涉及到鼠标的操作,opencv中有鼠标事件的介绍.需要用到两个函数:回调函数CvMouseCallback和注册回 ...