版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、编写更加稳定 可读性强的JavaScript代码每个人都有自己的编程风 格,也无可避免的要去感受别人的编程风格修改别人的代码。”修改别人的代码”对于我们来说的一件很痛苦的事情。因为有些代码并不是那么容易阅读、可维 护的,让另一个人来修改别人的代码,或许最终只会修改一个变量,调整一个函数的调用时机,却需要花上1个小时甚至更多的时间来阅读、缕清别人的代码。本文 一步步带你重构一段获取位置的”组件”提升你的javascript代码的可读性和稳定性。本文内容如下:· 分离你的javascript代码· 函数不应该过分依赖外部环境· 语义化和复用· 组件应该关注逻
2、辑,行为只是封装· 形成自己的风格的代码分离你的javascript代码下面一段代码演示了难以阅读/修改的代码:1. (function (window, namespace) 2. var $ = window.jQuery; 3. windownamespace = function (targetId, textId) /一个尝试复用的获取位
3、置的"组件" var $target = $('#' + targetId),/按钮 $text = $('#' + textId);/显示文本 $target.on('click', function () $text.html('获取中'); var data = '北京市'/balabala
4、很多逻辑,伪代码,获取得到位置中 4. if (data) 5. $text.html(data); 6.
5、0; else 7. $text.html('获取失败'); 8. ); 9. 10. )(window, 'linkFly');
6、160;这一段代码,我们暂且认可它已经构成一个”组件”。上面的代码就是典型的一个方法搞定所有事情,一旦填充上内部的逻辑就会变得生活不能自理,而一旦增加需求,例如获取位置返回的数据格式需要加工,那么就要去里面寻找处理数据的代码然后修改。我们分离一下逻辑,得到代码如下:1. (function (window, namespace) 2. var $ = window.jQuery, 3.
7、0; $target, 4. $text, 5. states= '获取中', '获取失败' 6. function done(address) /获取位置成功 7.
8、; $text.html(address); 8. 9. function fail() 10. $text.html(states1); 11. 12. function checkData(data)
9、 13. /检查位置信息是否正确 14. return !data; 15. 16. function loadPosition() 17. &
10、#160; var data = '北京市'/获取位置中 18. if (checkData(data) 19. done(data); 20.
11、;else 21. fail(); 22. 23. var init = function () 24. $target.on('click',
12、;function () 25. $text.html(states0); 26. loadPosition(); 27. ); 28.
13、160; 29. windownamespace = function (targetId, textId) 30. $target = $('#' + targetId); 31. $text
14、160;= $('#' + textId); 32. initData(); 33. setData(); 34. 35. )(window, 'linkFly'); 函数不应该过分依赖外部环境上面的代码中,我们已经把整个组件,切割成了
15、各种函数(注意这里我说的是函数,不是方法),这里常出现一个新的问题:函数过分依赖不可控的变量。变量$target和$text身为环境中的全局变量,从组件初始化便赋值,而我们切割后的代码大多数的操作方法都依赖$text,尤其是$text和done()、fail()之间暧昧的关系,一旦$text相关的结构、逻辑改变,那么我们的代码将会进行不小的改动。和页面/DOM相关的都是不可信赖的(例如$target和$text),一旦页面结构发生改变,它的行为很大程度上也会随之改变。而函数也不应该依赖外部的环境。在不可控的变量上,我们应该解开函数和依赖变量上的关系,让函数变得更加专注自己区域的逻辑,更加的纯粹
16、。简单的说:函数所依赖的外部变量,都应该通过参数传递到函数内部。新的代码如下:1. (function (window, namespace) 2. var $ = window.jQuery; 3. /检查位置信息是否正确 4. function checkData(data) 5.
17、0; return !data; 6. 7. /获取位置中 8. function loadPosition(done, fail) 9. var data = '北京市'/获取位置中
18、 10. if (checkData(data) 11. done(data); 12. else 13.
19、; fail(); 14. 15. windownamespace = function (targetId, textId) 16. var $target = $('#' + targetId),
20、 17. $text = $('#' + textId); 18. var states = '获取中', '获取失败' 19.
21、 $target.on('click', function () 20. $text.html(states0); 21. loadPosition(function (address) /获取位置成功
22、 22. $text.html(address); 23. , function () /获取位置失败 24.
23、0; $text.html(states1); 25. ); 26. ); 27. 28. )(window, 'linkFly'); 语义
24、化和复用变量states是一个数组,它描述的行为难以阅读,每次看到states0都有一种分分钟想捏死原作者的冲动,因为我们总是要记住变量states的值,在代码上,我们应该尽可能让它可以很好的被阅读。另外,上面的代码中$text.html就是典型的代码重复,我们再一次的修改代码,请注意这一次修改的代码中,我们所抽离的changeStateText()的代码位置,它并没有被提升到上一层环境中(也就是整个大闭包的环境)。1. (function (window, namespace) 2. var
25、$ = window.jQuery; 3. function checkData(data) 4. return !data; 5. 6. function loadPosition(done, fail) 7.
26、; var data = '北京市'/获取位置中 8. if (checkData(data) 9. done(data); 10.
27、; else 11. fail(); 12. 13. windownamespace = function (targetId, textId) 14.
28、60; var $target = $('#' + targetId), 15. $text = $('#' + textId), 16.
29、0;changeEnum = LOADING: '获取中', FAIL: '获取失败' , 17. changeStateText = function (text) 18.
30、60; $text.html(text); 19. 20. $target.on('click', function () 21.
31、60; changeStateText(changeEnum.LOADING); 22. loadPosition(function (address) 23. c
32、hangeStateText(address); 24. , function () 25. changeStateText(changeEnum.FAIL); 26.
33、0; ); 27. ); 28. 29. )(window, 'linkFly'); 提及语义化,我们必须要知道当前整个代码的逻辑和语义:在这整个组件中,所有的函数模块可以分为:工具和工具提供者。上一层环境(整个大闭包)在我们的业务中扮演着工具的身份,它的任务是缔造一套和获取位置逻
34、辑相关的工具,而在windownamespace)函数中,则是工具提供者的身份,它是唯一的入口,负责提供组件完整的业务给工具的使用者。这里的$text.html()在逻辑上并不属于工具,而是属于工具提供者使用工具后所得到的反馈,所以changeStateText()函数置于工具提供者windownamespace()中。组件应该关注逻辑,行为只是封装到此为止,我们分离了函数,并让这个组件拥有了良好的语义。但这时候来了新的需求:当没有获取到位置的时候,需要进行一些其他的操作。这时候会发现,我们需要windownamespace()上加上新的参数。当我们加上新的参数之后,又被告知新的需求:当获取位
35、置失败了之后,需要修改一些信息,然后再次尝试获取位置信息。不过幸好,我们的代码已经把大部分的逻辑抽离到了工具提供者中了,对整个工具的逻辑影响并不大。同时我们再看看代码就会发现我们的组件除了工具提供者之外,没有方法(依赖在对象上的函数)。也就是说,我们的组件并没有对象。我见过很多人的代码总是喜欢打造工具提供者,而忽略了工具的本质。迎合上面的增加的需求,那么我们的工具提供者将会变得越来越重,这时候我们应该思考到:是不是应该把工具提供出去?让我们回到最初的需求仅仅只是一个获取位置的组件,没错,它的核心业务就是获取位置它不应该被组件化。它的本质应该是个工具对象,而不应该和页面相关,我们从一开始就不应该
36、关注页面上的变化,让我们重构代码如下:1. (function (window, namespace) 2. var Gps = 3. load: function (fone, fail) 4. &
37、#160; var data = '北京市'/获取位置伪代码 5. this.check(data) ? 6. done(data, Gps.state.OK)
38、0;: 7. fail(Gps.state.FAIL); 8. , 9. check: function (data) 10.
39、160; return !data; 11. , 12. state: OK: 1, FAIL: 0 13. 14.
40、0; windownamespace = Gps; 15. )(window, 'Gps'); 在这里,我们直接捏死了工具提供者,我们直接将工具提供给外面的工具使用者,让工具使用者直接使用我们的工具,这里的代码无关状态、无关页面。至此,重构完成。形成自己风格的代码之所以讲这个是因为大家都有自己的编程风格。有些人的编程风格就是开篇那种代码的我觉得形成自己的编程风格,是建立在良好代码的和结构/语义上的。否则只会让你的代码变得越来越难读,越来越难写。*单var和多var我个人是喜欢单var风格的,不过
41、我觉得代码还是尽可能在使用某一方法/函数使用前进行var,有时候甚至于为了单var而变得丧心病狂:由于我又过分的喜爱函数表达式声明,函数表达式声明并不会在var语句中执行,于是偶尔会出现这种边声明边执行的代码,为了不教坏小朋友就不贴代码了(我不会告诉你们其实是我找不到了)。对象属性的屏蔽下面的代码演示了两种对象的构建,后一种通过闭包把内部属性隐藏,同样,两种方法都实现了无new化,我个人是不喜欢看见很多this的.但还是推荐前者。1. (function () 2. /第一种,曝露了_name属性 3.
42、 var Demo = function () 4. if (!(this instanceof Demo) 5. return new Demo(); 6.
43、; this._name = 'linkFly' 7. 8. Dtotype.getName = function () 9. return this._name; 10.
44、0; 11. 12. /第二种,多一层闭包意味内存消耗更大,但是屏蔽了_name属性 13. var Demo = function () 14. var name = 'linkFly' 15.
45、 return 16. getName: function () 17. return name; 18. &
46、#160; 19. 20. 21. ); 巧用变量置顶hoisting巧用函数声明的变量置顶特性意味着处女座心态的你放弃单var,但却可以让你的函数在代码结构上十分清晰,例如下面的代码:1. (function () 2. var names = 3.
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 盖州市畜牧兽医站、动物检疫站聘用干部考试试题汇编
- 2025年遴选公务员面试真题附答案
- 2025年医院抗肿瘤分级管理处方授权考试试题附答案
- 2025年辅警面试问题及答案(范文)
- (2025年)康马县辅警协警笔试笔试真题(附答案)
- (2025年)迪庆藏族自治州公安辅警招聘知识考试题库及答案
- 2026年网络与数据安全知识竞赛题库及答案(120题)
- 赤峰市喀喇沁旗2025-2026学年第二学期五年级语文期末考试卷(部编版含答案)
- 沧州市南皮县2025-2026学年第二学期五年级语文期末考试卷(部编版含答案)
- 邢台市隆尧县2025-2026学年第二学期三年级语文期末考试卷(部编版含答案)
- 科技助农:农业新篇章
- 学前特殊儿童语言教育
- 混凝土预制块护坡施工方案
- 机械毕业设计(论文)-210吨转炉倾动装置设计设计
- 配电线路器材与电气设备-配电设备
- 垂直盾构施工方案
- 新编研究生综合英语教程UNIT1(潘海英)
- 应急能力建设评估课件
- TSG-08-2017-特种设备使用管理规则
- Z3050型-摇臂钻床使用说明书
- 饲料标签解析课件
评论
0/150
提交评论