课程表

前端开发规范课程

工具箱
速查手册

JavaScript 规范

当前位置:免费教程 » HTML/CSS » 前端开发规范

通用约定

注释

原则

  • As short as possible(如无必要,勿增注释):尽量提高代码本身的清晰性、可读性。
  • As long as necessary(如有必要,尽量详尽):合理的注释、空行排版等,可以让代码更易阅读、更具美感。

单行注释

必须独占一行。// 后跟一个空格,缩进与下一行被注释说明的代码一致。

多行注释

避免使用 /*...*/ 这样的多行注释。有多行注释内容时,使用多个单行注释。

函数/方法注释

  1. 函数/方法注释必须包含函数说明,有参数和返回值时必须使用注释标识。;
  2. 参数和返回值注释必须包含类型信息和说明;
  3. 当函数是内部函数,外部不可访问时,可以使用 @inner 标识;
  1. /**
  2. * 函数描述
  3. *
  4. * @param {string} p1 参数1的说明
  5. * @param {string} p2 参数2的说明,比较长
  6. * 那就换行了.
  7. * @param {number=} p3 参数3的说明(可选)
  8. * @return {Object} 返回值描述
  9. */
  10. function foo(p1, p2, p3) {
  11. var p3 = p3 || 10;
  12. return {
  13. p1: p1,
  14. p2: p2,
  15. p3: p3
  16. };
  17. }

文件注释

文件注释用于告诉不熟悉这段代码的读者这个文件中包含哪些东西。 应该提供文件的大体内容, 它的作者, 依赖关系和兼容性信息。如下:

  1. /**
  2. * @fileoverview Description of file, its uses and information
  3. * about its dependencies.
  4. * @author user@meizu.com (Firstname Lastname)
  5. * Copyright 2009 Meizu Inc. All Rights Reserved.
  6. */

命名

变量, 使用 Camel 命名法。

  1. var loadingModules = {};

私有属性、变量和方法以下划线 _ 开头。

  1. var _privateMethod = {};

常量, 使用全部字母大写,单词间下划线分隔的命名方式。

  1. var HTML_ENTITY = {};
  1. 函数, 使用 Camel 命名法。
  2. 函数的参数, 使用 Camel 命名法。
  1. function stringFormat(source) {}
  2. function hear(theBells) {}
  1. , 使用 Pascal 命名法
  2. 类的 方法 / 属性, 使用 Camel 命名法
  1. function TextNode(value, engine) {
  2. this.value = value;
  3. this.engine = engine;
  4. }
  5. TextNode.prototype.clone = function () {
  6. return this;
  7. };
  1. 枚举变量 使用 Pascal 命名法。
  2. 枚举的属性, 使用全部字母大写,单词间下划线分隔的命名方式。
  1. var TargetState = {
  2. READING: 1,
  3. READED: 2,
  4. APPLIED: 3,
  5. READY: 4
  6. };

由多个单词组成的 缩写词,在命名中,根据当前命名法和出现的位置,所有字母的大小写与首字母的大小写保持一致。

  1. function XMLParser() {}
  2. function insertHTML(element, html) {}
  3. var httpRequest = new HTTPRequest();

命名语法

类名,使用名词。

  1. function Engine(options) {}

函数名,使用动宾短语。

  1. function getStyle(element) {}

boolean 类型的变量使用 is 或 has 开头。

  1. var isReady = false;
  2. var hasMoreCommands = false;

Promise 对象用动宾短语的进行时表达。

  1. var loadingData = ajax.get('url');
  2. loadingData.then(callback);

接口命名规范

  1. 可读性强,见名晓义;
  2. 尽量不与 jQuery 社区已有的习惯冲突;
  3. 尽量写全。不用缩写,除非是下面列表中约定的;(变量以表达清楚为目标,uglify 会完成压缩体积工作)
常用词 说明
options 表示选项,与 jQuery 社区保持一致,不要用 config, opts 等
active 表示当前,不要用 current 等
index 表示索引,不要用 idx 等
trigger 触点元素
triggerType 触发类型、方式
context 表示传入的 this 对象
object 推荐写全,不推荐简写为 o, obj 等
element 推荐写全,不推荐简写为 el, elem 等
length 不要写成 len, l
prev previous 的缩写
next next 下一个
constructor 不能写成 ctor
easing 示动画平滑函数
min minimize 的缩写
max maximize 的缩写
DOM 不要写成 dom, Dom
.hbs 使用 hbs 后缀表示模版
btn button 的缩写
link 超链接
title 主要文本
img 图片路径(img标签src属性)
dataset html5 data-xxx 数据接口
theme 主题
className 类名
classNameSpace class 命名空间

True 和 False 布尔表达式

类型检测优先使用 typeof。对象类型检测使用 instanceof。null 或 undefined 的检测使用 == null。

下面的布尔表达式都返回 false:

  • null
  • undefined
  • '' 空字符串
  • 0 数字0

但小心下面的, 可都返回 true:

  • '0' 字符串0
  • [] 空数组
  • {} 空对象

不要在 Array 上使用 for-in 循环

for-in 循环只用于 object/map/hash 的遍历, 对 Array 用 for-in 循环有时会出错. 因为它并不是从 0 到 length - 1 进行遍历, 而是所有出现在对象及其原型链的键值。

  1. // Not recommended
  2. function printArray(arr) {
  3. for (var key in arr) {
  4. print(arr[key]);
  5. }
  6. }
  7. printArray([0,1,2,3]); // This works.
  8. var a = new Array(10);
  9. printArray(a); // This is wrong.
  10. a = document.getElementsByTagName('*');
  11. printArray(a); // This is wrong.
  12. a = [0,1,2,3];
  13. a.buhu = 'wine';
  14. printArray(a); // This is wrong again.
  15. a = new Array;
  16. a[3] = 3;
  17. printArray(a); // This is wrong again.
  18. // Recommended
  19. function printArray(arr) {
  20. var l = arr.length;
  21. for (var i = 0; i < l; i++) {
  22. print(arr[i]);
  23. }
  24. }

二元和三元操作符

操作符始终写在前一行, 以免分号的隐式插入产生预想不到的问题。

  1. var x = a ? b : c;
  2. var y = a ?
  3. longButSimpleOperandB : longButSimpleOperandC;
  4. var z = a ?
  5. moreComplicatedB :
  6. moreComplicatedC;

. 操作符也是如此:

  1. var x = foo.bar().
  2. doSomething().
  3. doSomethingElse();

条件(三元)操作符 (?:)

三元操作符用于替代 if 条件判断语句。

  1. // Not recommended
  2. if (val != 0) {
  3. return foo();
  4. } else {
  5. return bar();
  6. }
  7. // Recommended
  8. return val ? foo() : bar();

&& 和 ||

二元布尔操作符是可短路的, 只有在必要时才会计算到最后一项。

  1. // Not recommended
  2. function foo(opt_win) {
  3. var win;
  4. if (opt_win) {
  5. win = opt_win;
  6. } else {
  7. win = window;
  8. }
  9. // ...
  10. }
  11. if (node) {
  12. if (node.kids) {
  13. if (node.kids[index]) {
  14. foo(node.kids[index]);
  15. }
  16. }
  17. }
  18. // Recommended
  19. function foo(opt_win) {
  20. var win = opt_win || window;
  21. // ...
  22. }
  23. var kid = node && node.kids && node.kids[index];
  24. if (kid) {
  25. foo(kid);
  26. }

jQuery 规范

使用最新版本的 jQuery

最新版本的 jQuery 会改进性能和增加新功能,若不是为了兼容旧浏览器,建议使用最新版本的 jQuery。以下是三条常见的 jQuery 语句,版本越新,性能越好:

  1. $('.elem')
  2. $('.elem', context)
  3. context.find('.elem')

jQuery的加载

1、推荐使用CDN(内容分发网络)提供的jQuery,一来速度较快,二来不止你一个网站在用,有时可以利用其他网站的缓存加快速度。点击这里查看本站推荐的CDN

2、最好在本地备份一个相同版本的代码,以防万一,不能链接远程服务,详情见此

3、使用裸协议的URL(去掉http:或者https:),加载CDN可以省掉http。例如:

  1. <script src="http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js"></script>

可以简写为:

  1. <script src="//apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js"></script>

4、如果可能,尽量将你的JavaScript和jQuery代码放到页面底部。

5.该使用哪个版本?

如果你想兼容IE678请不要用2.x的版本

针对极少数不用考虑兼容性问题的,极力推荐使用最新版本的jQuery

当从CDN服务器加载jQuery时,最好把版本写全(比如1.11.0而不是1.11或者直接写个1)

不要重复加载和多次加载

不要从jquery CDN中加载 jquery-latest.js,具体请看

6、如果你同时还使用了其他JS框架诸如Prototype, MooTools, Zepto等等,这些框架中,有的也用了$符号,所以你就不要再用$来进行jQuery 编码了,而请用'jQuery'代替。并且调用$.noConflict()保证不会有冲突出现。

7、要检测浏览器对一些新特性是否支持,请用Modernizr

关于变量

1、jQuery类型的变量最好加个$前缀。

2、时常将jQuery选择器返回的内容存进变量以便重用

  1. var $myDiv = $("#myDiv");
  2. $myDiv.click(function(){...});

3、使用 camel case命名

关于选择器

1.尽量ID选择器。实际运用的是js的document.getElementById(),所以速度较其他选择器快。

2.使用类选择器时不要指定元素的类型。请看性能比较

  1. var $products = $("div.products"); // 慢
  2. var $products = $(".products"); // 快

3.ID父亲容器下面查找子元素请用.find()方法。这样做快的原因是通过id选择元素不会使用Sizzle引擎。详情看这里

  1. // BAD, a nested query for Sizzle selector engine
  2. var $productIds = $("#products div.id");
  3. // GOOD, #products is already selected by document.getElementById() so only div.id needs to go through Sizzle selector engine
  4. var $productIds = $("#products").find("div.id");

4.多级查找中,右边尽量指定得详细点而左边则尽量简单点。了解更多

  1. // 丑陋
  2. $("div.data .gonzalez");
  3. // 优化后
  4. $(".data td.gonzalez");

5.避免冗余。详情或者查看性能比较

  1. $(".data table.attendees td.gonzalez");
  2. // 好的方式:去掉了中间的冗余
  3. $(".data td.gonzalez");

6.指定选择的上下文。

  1. // 劣质的代码:因为需要遍历整个DOM来找到.class
  2. $('.class');
  3. // 高品代码:因为只需在指定容器范围内进行查找
  4. $('.class', '#class-container');

7.避免使用万能选择器。查看具体阐释

  1. $('div.container > *'); // 差
  2. $('div.container').children(); // 棒

8.警惕隐式的万能选择器。省略的情况下其实使用的就是*号通配符。更多信息

  1. $('div.someclass :radio'); // 差
  2. $('div.someclass input:radio'); // 棒

9.ID已经表示唯一了,背后使用的是document.getElementById(),所以不要和其他选择器混淆了。

  1. $('#outer #inner'); // 脏
  2. $('div#inner'); // 乱
  3. $('.outer-container #inner'); // 差
  4. $('#inner'); // 干净利落,后台只需调用document.getElementById()

DOM操作

1.操作任何元素前先将其从文档卸载,然后再贴回去。请看

  1. var $myList = $("#list-container > ul").detach();
  2. //...a lot of complicated things on $myList
  3. $myList.appendTo("#list-container");

2、使用连接字符串或数组join(),然后再append()。请看

性能比较: http://jsperf.com/jquery-append-vs-string-concat

  1. // 不好
  2. var $myList = $("#list");
  3. for(var i = 0; i < 10000; i++){
  4. $myList.append("<li>"+i+"</li>");
  5. }
  6. // GOOD
  7. var $myList = $("#list");
  8. var list = "";
  9. for(var i = 0; i < 10000; i++){
  10. list += "<li>"+i+"</li>";
  11. }
  12. $myList.html(list);
  13. // EVEN FASTER
  14. var array = [];
  15. for(var i = 0; i < 10000; i++){
  16. array[i] = "<li>"+i+"</li>";
  17. }
  18. $myList.html(array.join(''));

3、不要用缺失的元素,具体请看

  1. // BAD: This runs three functions before it realizes there's nothing in the selection
  2. $("#nosuchthing").slideUp();
  3. // GOOD
  4. var $mySelection = $("#nosuchthing");
  5. if ($mySelection.length) {
  6. $mySelection.slideUp();
  7. }

事件

1.一个页面只写一个文档ready事件的处理程序。这样代码既清晰好调试,又容易跟踪代码的进程。

2.不要用匿名函数来做事件的回调。匿名函数不易调试维护测试和复用。或许你想较真,看看这里吧

  1. $("#myLink").on("click", function(){...}); // 不要这样
  2. // 这样
  3. function myLinkClickHandler(){...}
  4. $("#myLink").on("click", myLinkClickHandler);

3.处理文档ready事件的回调也表用匿名函数,匿名函数不易调试维护测试和复用

  1. $(function(){ ... }); // 糟糕的做法:无法利用此函数也无法为其写测试用例
  2. // 好的做法
  3. $(initPage); // 抑或 $(document).ready(initPage);
  4. function initPage(){
  5. // 这里你可以进行程序的初始化了
  6. }

4.进一步,最好也将ready事件的处理程序放到外部文件中引入到页面,而页面中内嵌的代码只需调用即可。

  1. <script src="my-document-ready.js"></script>
  2. <script>
  3. // 初始化一些必要的全局变量
  4. $(document).ready(initPage); // 抑或 $(initPage);
  5. </script>

5.千万表写内联到HTML的JS代码,这是调试的噩梦!应该总是用jQuery来绑定事件自带程序,这样也方便随时动态地取消绑定。

  1. <a id="myLink" href="#" onclick="myEventHandler();">my link</a> <!--不好 -->
  2. $("#myLink").on("click", myEventHandler); // GOOD

6.如果可能尽量在绑定事件处理程序时使用一个命名空间,这样可以方便地取消绑定而不会影响其他绑定。

  1. $("#myLink").on("click.mySpecialClick", myEventHandler); // 不错
  2. // 之后,让我们优雅地解除绑定
  3. $("#myLink").unbind("click.mySpecialClick");

7.当选择某个元素的子元素的时候,尽量在后面选择,不要在前面选择其中选择。如下:

  1. $("#list a").on("click", myClickHandler); // BAD, you are attaching an event to all the links under the list.
  2. $("#list").on("click", "a", myClickHandler); // GOOD, only one event handler is attached to the parent.

Ajax异步操作

1.不要用.getJson() 或 .get(),直接用直接用$.ajax() ,因为jQuery内部还是将前者转化为$.ajax()

2.表对HTTPS站点使用HTTP去发起请求,最好干脆就表指定(将HTTP或者HTTPS从你的URL中移除)

3.表在链接里面嵌参数,请使用专门的参数设置来传递

  1. // 不易阅读的代码...
  2. $.ajax({
  3. url: "something.php?param1=test1&param2=test2",
  4. ....
  5. });
  6. // 更易阅读...
  7. $.ajax({
  8. url: "something.php",
  9. data: { param1: test1, param2: test2 }
  10. });

4.尽量指明数据类型以便你自己清楚要处理什么样的数据(见下方会提到的Ajax模板)

5.对于异步动态加载的内容,最好使用代理来绑定事件处理程序。这样的好处是对于之后动态加载的元素事件同样有效。了解更多

  1. $("#parent-container").on("click", "a", delegatedClickHandlerForAjax);

6.使用Promise模式。更多例子

  1. $.ajax({ ... }).then(successHandler, failureHandler);
  2. // 抑或
  3. var jqxhr = $.ajax({ ... });
  4. jqxhr.done(successHandler);
  5. jqxhr.fail(failureHandler);

7.标准的Ajax模板如下,查看官方案例

  1. var jqxhr = $.ajax({
  2. url: url,
  3. type: "GET", // 默认为GET,你可以根据需要更改
  4. cache: true, // 默认为true,但对于script,jsonp类型为false,可以自行设置
  5. data: {}, // 将请求参数放这里.
  6. dataType: "json", // 指定想要的数据类型
  7. jsonp: "callback", // 指定回调处理JSONP类型的请求
  8. statusCode: { // 如果你想处理各状态的错误的话
  9. 404: handler404,
  10. 500: handler500
  11. }
  12. });
  13. jqxhr.done(successHandler);
  14. jqxhr.fail(failureHandler);

动画与特效

1.保持一个始终如一风格统一的动画实现

2.紧遵用户体验,不要滥用动画特效

使用简洁的显示隐藏,状态切换,滑入滑出等效果来展示元素

使用预设值来设置动画的速度'fast','slow',或者400(中等速度)

插件相关

1.始终选择一个有良好支持,文档完善,全面测试过并且社区活跃的插件

2.注意所用插件与当前使用的jQuery版本是否兼容

3.一些常用功能应该写成jQuery插件。jQuery插件的编写模板

链式结构

1.除了用变量将jQuery选择器返回的结果保存,还可以利用好链式调用。

  1. $("#myDiv").addClass("error").show();

2.当链式调用多达3次以上或代码因绑定回调略显复杂时,使用换行和适当的缩进来提高代码的可读性。

  1. $("#myLink")
  2. .addClass("bold")
  3. .on("click", myClickHandler)
  4. .on("mouseover", myMouseOverHandler)
  5. .show();

3.对于特别长的调用最好还是用变量保存下中间结果来简化代码。

其他案例

1.使用对象来传递参数

  1. $myLink.attr("href", "#").attr("title", "my link").attr("rel", "external"); // 糟糕:调用了三次attr
  2. // 不错,只调用了一次attr
  3. $myLink.attr({
  4. href: "#",
  5. title: "my link",
  6. rel: "external"
  7. });

2.不要将CSS与jQuery杂揉

  1. $("#mydiv").css({'color':red, 'font-weight':'bold'}); // 不好
  2. .error {/* 不错 */
  3. color: red;
  4. font-weight: bold;
  5. }
  6. $("#mydiv").addClass("error");

3.时刻关注官方Changelog,不要使用摒弃了的方法。点此查看所有废弃的方法

4.适时地使用原生JavaScript。原生的性能肯定相当好一些,查看性能比较

  1. $("#myId"); // 多少还是会逊色于...
  2. document.getElementById("myId");

本小节(jQuery 规范)翻译自:http://lab.abhinayrathore.com/jquery-standards/#jQueryCND
译者博客:http://www.haorooms.com/post/jquery_dmgf_zjsj


性能优化

避免不必要的 DOM 操作

浏览器遍历 DOM 元素的代价是昂贵的。最简单优化 DOM 树查询的方案是,当一个元素出现多次时,将它保存在一个变量中,就避免多次查询 DOM 树了。

  1. // Recommended
  2. var myList = "";
  3. var myListHTML = document.getElementById("myList").innerHTML;
  4. for (var i = 0; i < 100; i++) {
  5. myList += "<span>" + i + "</span>";
  6. }
  7. myListHTML = myList;
  8. // Not recommended
  9. for (var i = 0; i < 100; i++) {
  10. document.getElementById("myList").innerHTML += "<span>" + i + "</span>";
  11. }

缓存数组长度

循环无疑是和 JavaScript 性能非常相关的一部分。通过存储数组的长度,可以有效避免每次循环重新计算。

注: 虽然现代浏览器引擎会自动优化这个过程,但是不要忘记还有旧的浏览器。

  1. var arr = new Array(1000),
  2. len, i;
  3. // Recommended - size is calculated only 1 time and then stored
  4. for (i = 0, len = arr.length; i < len; i++) {
  5. }
  6. // Not recommended - size needs to be recalculated 1000 times
  7. for (i = 0; i < arr.length; i++) {
  8. }

异步加载第三方内容

当你无法保证嵌入第三方内容比如 Youtube 视频或者一个 like/tweet 按钮可以正常工作的时候,你需要考虑用异步加载这些代码,避免阻塞整个页面加载。

  1. (function() {
  2. var script,
  3. scripts = document.getElementsByTagName('script')[0];
  4. function load(url) {
  5. script = document.createElement('script');
  6. script.async = true;
  7. script.src = url;
  8. scripts.parentNode.insertBefore(script, scripts);
  9. }
  10. load('//apis.google.com/js/plusone.js');
  11. load('//platform.twitter.com/widgets.js');
  12. load('//s.widgetsite.com/widget.js');
  13. }());

避免使用 jQuery 实现动画

  1. 禁止使用 slideUp/Down() fadeIn/fadeOut() 等方法;
  2. 尽量不使用 animate() 方法;
转载本站内容时,请务必注明来自W3xue,违者必究。
 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号