引爆你的Javascript代码进化 (转)

转自 海玉的博客

方才在程序里看到一段JS代码,写法极为高明,私心想着若是其按照规范来写,定可培养对这门语言的理解,对JS编程能力提高必是极好的。说人话:丫代码写的太乱,看的窝火!

最近闲暇无事,准备对自己JS学习做一个总结。众所周知,JS是一种语法极其灵活的语言,一千个人会有一千种JS书写方式。这造成的结果往往就是给项目日后的开发及维护留下一个不小的隐患,也对你和团队再次开发及阅读代码造成一定困难,个人认为良好的书写规范是应该首当其冲的。所以参考一些优秀前端开发团队的代码规范后,总结了几点,希望能让你的Javascript代码上升一个台阶。

变量命名:

变量名包括全局变量,局部变量,类变量,函数参数等等,他们都属于这一类。

变量命名都以类型前缀+有意义的单词组成,用驼峰式命名法增加变量和函式的可读性。例如:sUserName,nCount。

前缀规范:

每个局部变量都需要有一个类型前缀,按照类型可以分为:

s:表示字符串。例如:sName,sHtml;
n:表示数字。例如:nPage,nTotal;
b:表示逻辑。例如:bChecked,bHasLogin;
a:表示数组。例如:aList,aGroup;
r:表示正则表达式。例如:rDomain,rEmail;
f:表示函数。例如:fGetHtml,fInit;
o:表示以上未涉及到的其他对象,例如:oButton,oDate;
g:表示全局变量,例如:gUserName,gLoginTime;

当然,也可以根据团队及项目需要增加前缀规范,例如我们团队会用到:

$:表示Jquery对象。例如:$Content,$Module;
一种比较广泛的Jquery对象变量命名规范。
j:表示Jquery对象。例如:jContent, jModule;
另一种Jquery对象变量命名方式。
fn:表示函数。例如:fnGetName,fnSetAge;
和上面函数的前缀略有不同,改用fn来代替,个人认为fn能够更好的区分普通变量和函数变量。
dom:表示Dom对象,例如:domForm,domInput;
项目中很多地方会用到原生的Dom方法及属性,可以根据团队需要适当修改。

这里可以根据项目及团队需要,设计出针对项目需要的前缀规范,从而达到团队开发协作便利的目的。

例外情况:

1:作用域不大临时变量可以简写,比如:str,num,bol,obj,fun,arr。
2:循环变量可以简写,比如:i,j,k等。
3:某些作为不允许修改值的变量认为是常量,全部字母都大写。例如:COPYRIGHT,PI。常量可以存在于函数中,也可以存在于全局。

为什么需要这样强制定义变量前缀?正式因为javascript是弱语言造成的。在定义大量变量的时候,我们需要很明确的知道当前变量是什么属性,如果只通过普通单词,是很难区分的。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

//普通代码

var checked = false;

var check = function() {

    return true;

}

/**

some code

**/

if(check) {//已经无法很确切知道这里是要用checked还是check()从而导致逻辑错误

    //do some thing

}

//规范后代码

var bChecked = false;

var fnCheck = function() {

    return true;

}

/**

some code

**/

if(bChecked) {

    // do some thing

}

if(fnCheck()) {

    // do other thing

}

函数命名:

统一使用动词或者动词+名词形式,例如:fnGetVersion(),fnSubmitForm(),fnInit();涉及返回逻辑值的函数可以使用is,has,contains等表示逻辑的词语代替动词,例如:fnIsObject(),fnHasClass(),fnContainsElment()。

如果有内部函数,使用_fn+动词+名词形式,内部函数必需在函数最后定义。例如:


1

2

3

4

5

6

7

8

9

10

11

12

function fnGetNumber(nTotal) {

    if (nTotal < 100) {

        nTotal = 100;

    }

    return _fnAdd(nTotal);

    function _fnAdd(nNumber) {

        nNumber++;

        return nNumber;

    }

}

alert(fGetNumber(10)); //alert 101

对象方法与事件响应函数:

对象方法命名使用fn+对象类名+动词+名词形式;例如 fnAddressGetEmail(),主观觉得加上对象类名略有些鸡肋,个人认为一个对象公开的属性与方法应该做到简洁易读。多增加一个对象类名单词,看着统一了,但有点为了规范而规范的味道,这里根据自身喜好仁者见仁智者见智吧。

某事件响应函数命名方式为fn+触发事件对象名+事件名或者模块名,例如:fnDivClick(),fnAddressSubmitButtonClick()

补充一些函数方法常用的动词:

get 获取/set 设置, add 增加/remove 删除
create 创建/destory 移除 start 启动/stop 停止
open 打开/close 关闭, read 读取/write 写入
load 载入/save 保存, create 创建/destroy 销毁
begin 开始/end 结束, backup 备份/restore 恢复
import 导入/export 导出, split 分割/merge 合并
inject 注入/extract 提取, attach 附着/detach 脱离
bind 绑定/separate 分离, view 查看/browse 浏览
edit 编辑/modify 修改, select 选取/mark 标记
copy 复制/paste 粘贴, undo 撤销/redo 重做
insert 插入/delete 移除, add 加入/append 添加
clean 清理/clear 清除, index 索引/sort 排序
find 查找/search 搜索, increase 增加/decrease 减少
play 播放/pause 暂停, launch 启动/run 运行
compile 编译/execute 执行, debug 调试/trace 跟踪
observe 观察/listen 监听, build 构建/publish 发布
input 输入/output 输出, encode 编码/decode 解码
encrypt 加密/decrypt 解密, compress 压缩/decompress 解压缩
pack 打包/unpack 解包, parse 解析/emit 生成
connect 连接/disconnect 断开, send 发送/receive 接收
download 下载/upload 上传, refresh 刷新/synchronize 同步
update 更新/revert 复原, lock 锁定/unlock 解锁
check out 签出/check in 签入, submit 提交/commit 交付
push 推/pull 拉, expand 展开/collapse 折叠
begin 起始/end 结束, start 开始/finish 完成
enter 进入/exit 退出, abort 放弃/quit 离开
obsolete 废弃/depreciate 废旧, collect 收集/aggregate 聚集

上面讨论了基本的JS书写命名规范,按我个人看法,只要能够按照上面的规范写出来的代码,一般不会太糟糕,最不济没人会说你代码乱的难以阅读。代码规范对于大团队的维护建设是毋庸置疑的,当然对于个人的代码素养也是很有帮助的,希望你能够通过上文能够加强你的代码规范,写出易读易维护的代码。

代码的规范属于战术上的进化,下面我们再来看看如何让你的Javascript在战略上进化。

面向对象书写Javascript

面向对象书写Javascript想必你一定不会陌生,但我敢说,大多数前端一般不会通过面向对象来书写JS代码。第一是Javascript本身的语言机制原因造成面向对象的书写困难,由于Javascript是原型式继承又是一个类C的语言,他的面向对象的东西相对于C++/Java比较奇怪。第二是Javascript作为一种语法极其灵活的语言,直接导致了面向对象书写JS又有多种写法,让许多初学者分不清到底哪个才是正确的写法。基于上述和个人的经验推荐如下俩种书写方式:

第一类:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

(function(){

    function Circle(nRadius){

        this.nR = nRadius;

    }

    Circle.prototype = {

        PI : 3.14,

        fnGetArea : function(){

            return this.PI * this.nR * this.nR;

        }

    }

    var c1 = new Circle(5);

    alert(c1.fnGetArea()); //78.5

})();

上面这种可以说是很标准的面向对象JS书写方式了我们又称之为工厂模式,优点就是简单容易上手,新手常常喜欢这么写。以上代码略微做些改动,会有如下这个变种:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

(function(){

    function Circle(nRadius, sMessage){

        this.init.apply(this, arguments);

    }

    Circle.prototype = {

        init : function(nRadius, sMessage){

            this.nR = nRadius;

            this.sMessage = sMessage;

        },

        PI : 3.14,

        fnGetArea : function(){

            return this.sMessage + ": " + this.PI * this.nR * this.nR;

        }

    }

    var c = new Circle(5, "构造初始化 面积");

    alert(c.fnGetArea()); //构造初始化 面积: 78.5

})();

上面这个变种,就比较有意思了,this.init.apply(this, arguments);这行代码把初始化的任务交接给了init()方法,这么做的好处就是可以把所有初始化的东西都放在一个地方进行,增加可阅读性,需要理解一定的Javascript运行机制原理。

第二类:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

(function(){

    function Circle(){

    }

    Circle.prototype = {

        init : function(nRadius, sMessage){

            this.nR = nRadius;

            this.sMessage = sMessage;

        },

        PI : 3.14,

        fnGetArea : function(){

            return this.sMessage + ": " + this.PI * this.nR * this.nR;

        }

    }

    var c = new Circle();

    c.init(5, "手动构造初始化 面积");

    alert(c.fnGetArea()); //手动构造初始化 面积: 78.5

})();

这类写法是我现在比较喜欢的写法,简洁高效。从书写角度来看省去了构造函数初始化属性,改用其init()中初始化。另一个好处在于不在new Circle()构造之初传入参数,个人认为当new构造对象的时候,最好不要掺杂参数,这样做很“危险”,改为“手动型”初始化更易于代码排查修改。当然这种写法还有一个原因就是他可以很好的转换成一般前端接受的“封装型”代码,我们把上面的代码也略微改动一下:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

(function(){

    var Circle = {

        init : function(nRadius, sMessage){

            this.nR = nRadius;

            this.sMessage = sMessage;

        },

        PI : 3.14,

        fnGetArea : function(){

            return this.sMessage + ": " + this.PI * this.nR * this.nR;

        }

    }

    Circle.init(5, "封装型 面积");

    alert(Circle.fnGetArea()); //封装型 面积: 78.5

})();

是不是对上面这类代码很熟悉,很多网站上的例子都是使用这类封装型代码书写的,优点是代码的封装性良好,可以有效的重用,多用于页面功能性效果实现,封装一个Tab控件、封装一个跑马灯效果等等。缺点就是不能很好的用作继承,这是和上面三种格式最大区别。可话又说回来一般JS代码很少会用到继承的地方,除非是写一个大型库(类似YUI)会用到继承外,一般写一个功能模块用到封装型代码就够用了,所以大多数前端喜欢使用这类封装型的书写风格。

上面介绍了2类4种面向对象的写法,一般面向对象书写格式基本都在上面了,熟悉面向对象书写可以有效的增加你对JS的理解。熟练使用上面4中写法也能够很好的在工作中给代码维护修改带来便利。最后我们再来谈一个技巧,让你的Javascript代码在技巧上进化。

用对象字面量构造对象

一个对象字面量就是包含在一对花括号中的0个或多个“名/值”对。上文在面向对象书写格式的时候我们就大量的使用了对象字面量的书写格式。

对象字面量书写Javascript可以很好的简化代码,又能极大的增加代码可读性,尤其作为参数使用可以有化腐朽为神奇的表现。我们看下面代码:


1

2

3

4

5

6

7

8

9

10

11

12

13

(function(){

    function Person(sName, nAge, nWeight, bSingle){

        this.sName = sName;

        this.nAge = nAge;

        this.nWeight = nWeight;

        this.bSingle = bSingle;

    }

    Person.prototype.showInfo = function(){

        return this.sName + " " + this.nAge + " " + this.nWeight + " " + this.bSingle;

    }

    var p = new Person("海玉", 25, 75, true);

    alert(p.showInfo()); //海玉 25 75 true

})();

上面是一个很标准的工厂模式,一般而言这类写法属于那种规规矩矩没有大错也没有亮点的代码,而且参数不少,一个不小心还会传入错误的参数,而应用对象字面量技巧可以很好的规避此类问题,我们来看改动过后的代码:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

(function(){

    function Person(){

    }

    Person.prototype = {

        init : function(option){

            if(typeof option == "undefined"){

                option = {};

            }

            this.sName = option.sName || "海玉";

            this.nAge = option.nAge || 25;

            this.nWeight = option.nWeight || 75;

            this.bSingle = (typeof option.bSingle != "undefined") ? option.bSingle : true;

        },

        showInfo : function(){

            return this.sName + " " + this.nAge + " " + this.nWeight + " " + this.bSingle;

        }

    }

    var p = new Person();

    p.init({

        nWeight : 80,

        sName : "Hank"

    })

    alert(p.showInfo()); //Hank 25 80 true

})();

这里使用第三种面向对象写法,有兴趣的朋友可以自行尝试改成封装型写法。上面的改写看出哪里改动最大吗?对的,传入参数改成了一个对象字面量,而且传入参数可以是随意设置,位置颠倒也不会有任何问题。这里充分利用对象字面量优点,利用键值对代替原始的传参方式大大提升了可读性和容错性。还有一个改进就是默认值的处理,如果没有传入任何参数,此代码也能很好的运行下去,不会有任何问题。

注1:这里形参命名为option,没有遵守上面的变量命名规范是为了方便书写与阅读,具体情况具体分析。
注2:由于||运算符对于布尔值默认赋值会出现赋值问题,所以要先进行判断是否为undefined,再利用三元运算符可以很好的完成布尔值的默认值赋值。

总的来说上面阐述的代码进化只能算的上是“修身”层面,想要真正的让代码“修心”还是得多写,多看,多练。只有这样你的代码才会更精练,更有扩展性,更好的维护性。

林林总总写了这些个总结,一来是对自己学习的记录,二来也是想同大家探讨JS还有哪些地方有潜力可挖,脑子里还有许多零零碎碎的片段,待日后再次整理验证再与大家一起分享吧。

时间: 2024-10-07 10:51:49

引爆你的Javascript代码进化 (转)的相关文章

引爆你的Javascript代码进化

方才在程序里看到一段JS代码,写法极为高明,私心想着若是其按照规范来写,定可培养对这门语言的理解,对JS编程能力提高必是极好的.说人话:丫代码写的太乱,看的窝火! 最近闲暇无事,准备对自己JS学习做一个总结.众所周知,JS是一种语法极其灵活的语言,一千个人会有一千种JS书写方式.这造成的结果往往就是给项目日后的开发及维护留下一个不小的隐患,也对你和团队再次开发及阅读代码造成一定困难,个人认为良好的书写规范是应该首当其冲的.所以参考一些优秀前端开发团队的代码规范后,总结了几点,希望能让你的Java

编写可维护的javascript代码---开篇

文章开篇主要推荐了2款检测编程风格的工具: JSLint和JSHint: jsLint是由Douglas Crockford创建的.这是一个通用的javascript代码质量检测工具,最开始JSLint只是一个简单的查找不符合javascript模式的,错误的小工具,经过数年的进化,JSLint已经成为一个有用的工具,不仅能可以找出代码潜在的错误,而且能针对你的代码给出编码风格上的警告. JSHint是JSLint的一个分支项目,在github上可以搜到. JSHint的目标是提供更加个性化的j

前端福利!10个短小却超实用的JavaScript 代码段

JavaScript正变得越来越流行,它已经成为前端开发的第一选择,并且利用基于JavaScript语言的NodeJS,我们也可以开发出高 性能的后端服务,甚至我还看到在硬件编程领域也出现了JavaScript的身影.JavaScript正在逐渐进化为一门全能的开发语言.下面是我收集 的10段实用JavaScript代码,基于它们你还可以创造出更强大的JS插件或功能函数. 但用好JavaScript并不容易,你除了需要掌握它的语法并知道如何写出高质量的代码之外,还需要了解如何解决那些几乎在每个项

FineUI(专业版)实现百变通知框(无JavaScript代码)!

曾经,有网友抱怨FineUI中连个通知框都没有,当用户进行某个操作成功时给个右下角的提示很不方便. 强大的设置参数 现在,FineUI(专业版)提供了强大的通知框机制,一个小小的通知框居然有多达 16 种不同的设置,可见威力之强大. 下面通过一张图片来简单概括一下: 1. 模式或者非模式对话框2. 消息图标可显示(消息.警告.问题.错误.成功),也可隐藏3. 正在加载图片可显示隐藏4. 消息正文可自定义5. 对话框标题可自定义6. 关闭图标可显示隐藏7. 标题栏可拖动8. 标题栏可隐藏9. 弹出

编写简洁的 JavaScript 代码

作者:尹锋链接:https://www.zhihu.com/question/20635785/answer/223515216来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 避免使用 js 糟粕和鸡肋 这些年来,随着 HTML5 和 Node.js 的发展,JavaScript 在各个领域遍地开花,已经从"世界上最被误解的语言"变成了"世界上最流行的语言".但是由于历史原因,JavaScript 语言设计中还是有一些糟粕和鸡肋,比如

代码示例:一些简单技巧优化JavaScript编译器工作详解,让你写出高性能运行的更快JavaScript代码

告诉你一些简单的技巧来优化JavaScript编译器工作,从而让你的JavaScript代码运行的更快.尤其是在你游戏中发现帧率下降或是当垃圾回收器有大量的工作要完成的时候. 单一同态: 当你定义了一个两个参数的函数,编译器会接受你的定义,如果函数参数的类型.个数或者返回值的类型改变编译器的工作会变得艰难.通常情况下,单一同态的数据结构和个数相同的参数会让你的程序会更好的工作. function example(a, b) { // 期望a,b都为数值类型 console.log(++a * +

javascript代码放置位置对程序的影响

在编写html文档时,javascript可以放置的位置有两个地方<head>或者<body>,但是放置的地方,会对 JavaScript 代码的正常执行会有一定影响.由于 HTML 文档是由浏览器从上到下依次载入的,javascript的放置位置主要影响获取网页元素.如果你的代码中包含获取网页元素的代码例如document.getElementById(),那么你需要确保你的javascript代码要在你想要获取的元素的位置之后.如过在你想要获取的元素的位置之前调用这个些代码,由

javascript代码规范 [转]

原文:http://www.css88.com/archives/5366 全局命名空间污染与 IIFE 总是将代码包裹成一个 IIFE(Immediately-Invoked Function Expression),用以创建独立隔绝的定义域.这一举措可防止全局命名空间被污染. IIFE 还可确保你的代码不会轻易被其它全局命名空间里的代码所修改(i.e. 第三方库,window 引用,被覆盖的未定义的关键字等等). 不推荐 1 var x = 10, 2 y = 100; 3 4 // Dec

可进行JavaScript代码测试与调试的12个网站

概述:JavaScript是网站前端开发最为重要的一门编程语言,本文收集了能够在线测试与调试JavaScript代码的12个网站 1.JS Bin JS bin是一个为JavaScript和CSS爱好者们提供特定情况下的代码片段测试的网站.它可以让你和你的同伴合作调试代码.你可以在这里编辑和测试JavaScript和HTML代码,一旦你觉得满意,可以把相关的网址发送给你的同伴,以获取他们的看法和帮助. 2.JS Nice JS Nice 是一个用于JavaScript的反代码混淆以及反极简主义的