充分发挥 JavaScript 语言的优势
尽管我在生产环境中使用 JavaScript 长达 8 年之久了,但是,直到最近 2 年,我才开始学习如何正确地编写 JavaScript 代码,根据我对人们的理解,很多开发者都有类似经历。我们有相当一部分人用 PHP、ASP 等语言做网站,貌似把 JavaScript 当成了一种补充。然而,随着 NodeJS 的流行以及浏览器的发展,JavaScript 已经冲到了现代前端 web 开发的最前线。
我想在本文分享一些东西,我觉得它们是当今每个开发者都应该充分发挥 JavaScript 优势的技术点。我不是要列出一份详尽的清单,而是尽量遵循我所认为的重要程度进行论述。
JavaScript 诞生于混乱的年代,因此一些好的和坏的特性就构成了这门语言。当你用 JavaScript 和其它语言开发软件时,你会尝到痛苦的教训,然后不得不回头维护(或扩展)所谓的应用程序。没有这个经历,你将很难理解我要说的内容。下面谈谈我所接受的惨痛教训。
1.改变头等函数
头等函数注1将一门编程语言变成了成年人的乐高积木。简而言之,有了头等函数,意味着 JavaScript 能够把函数做为参数传递,还能做为另一个函数的返回值、并赋给变量。这意味着你用很少的代码就能实现非常强大的功能,尤其在函数式编程中。举个实际例子:
1
2
3
4
5
6
7
8
9
10
11
|
var myArray = [1, 2, 3, 4, 5, 6] var add = function (a, b) { return a + b; }; var getTotal = function (arr) { return arr.reduce(add, 0); }; getTotal(myArray); // => 21 |
在第 7 行,我们将一个匿名函数赋给了 getTotal 变量。在第 8 行,我们把 add 函数做为参数传给了 reduce 函数。我们就可以创建更高层次的通用函数,避免了不必要的重复(符合 DRY 原则注2)。我们还能实现复合函数注3,在例子中,我们把 add 函数做为 reduce 的参数,组成了复合函数。
2.学习 Array 的原生方法
我不单单要讨论 Array.prototype.push 或 Array.prototype.splice。映入脑海的还有一些更有用的函数:
和第一个例子一样,你可以在复合函数中使用它们,并组装出某些更加通用、但功能强大的、更高级的函数。大部分应用程序都要涉及数据集的操作,为了取得这些数据,你需要明白有哪些可用的工具,这是及其宝贵的。
3.使用 ES6(ES2015)
箭头函数、let & const、解构、尾调用优化和模板字符串,都属于 ES6 的一些不错的特性。我个人设法避免使用 class 关键字,因为它鼓励类和构造函数的继承,它们更容易引发误用和副作用。
ES6 特性为编写 JavaScript 引入了一种相当新颖的方式,多研究一些细节、探索这些特性,或许是本文的一个部分,我下周可能还会有后续文章。
在浏览器/NodeJS 环境(当写代码时)使用大部分的 ES6 特性,需要用到转码器,相应工具可以访问 https://babeljs.io/。做为一名 web 开发者,我习惯使用 babel 和 browserify,用一条简单命令将 ES6 风格的代码转换成 ES5 的风格:
1
2
|
npm install -g browserify babelify browserify -t babelify es6code.js > es5code.js |
如果我们用 ES6 重新编写第一个例子中的代码,可能是如下代码:
1
2
3
4
5
|
const myArray = [1, 2, 3, 4, 5, 6] const add = (a, b) => a + b; const getTotal = (arr) => arr.reduce(add, 0); getTotal(myArray); // => 21 |
代码看起来简洁、直观,这应该足以引起你对 ES6 的兴趣了。但要牢记一点,某些和引擎相关的 ES6 特性,可能无法通过转码器。
4.理解绊脚石:作用域、闭包和类型转换
作用域
描述这个问题的最好方式就是借助一段代码,我打算借鉴 Douglass Crockfords 《JavaScript 语言精粹》上的一个类似例子,因为它非常贴切:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
var foo = function () { var a = 2, b = 4; var bar = function () { var b = 9, c = 14; // Here: a is 2, b is 9 and c is 14 a = a + b + c; // Here: a is 25, b is still 9 and c is still 14 }; // Here: a is 2, b is 4 and c is undefined bar(); // Now: a is 21, b is still 4 and c is still undefined }; |
可以看到,你声明变量的位置,和内部函数怎样被定义、以及内部函数怎样引起变量 a 改变其值,存在着关系。对变量声明保持清晰的认识,有助你编写更加可靠的软件。对于函数,要清晰地定义输入和可预期的输出,并尽可能明了。
闭包
闭包是 JavaScript 里保持私有变量的一种绝妙方式,不过,貌似也成了被误解的根源。基本上说,闭包支持你从内部函数去访问外部函数的作用域(又称作用域),类似于上面作用域例子中的 a。就这么简单。有意思的是,当你从外部函数返回一个函数、而内部函数可以访问外部函数的作用域时,内部函数将一直保留外部函数的作用域,哪怕过了整个外部函数的生命期。听起来有些复杂,举个例子:
1
2
3
4
5
6
7
8
9
10
11
12
|
var outer = function () { var a = 1; // variables declared outside of the 'inner' function declaration var b = 2; return function inner() { return a; // return 'a' that was defined in the outer function. // return b; // We could also access 'b' if we felt like it. }; }; var inner = outer(); // the outer function returns the inner function inner(); // => 1 // the inner functions still remembers that 'a' was defined as '1' from the outer function |
类型转换
由于 JavaScript 貌似荒谬的类型转换,而带来了很多笑话。为了避免所有让人讨厌的地方,最好使用可信任的 ===,它会在你所期望的大部分情况下,做严格的对象比较。只有一种情况要不好使,当你比较独立的对象字面量时,即使它们具有完全相同的属性和结构,它们也不是相等的,因为它们具有两个完全独立的对象。对于这种情况,只比较对象的每个属性就可以了,像 Underscorejs 之类的资源库就提供了上述情况的深度比较的方法。
5.避免类继承
这或许存在争议,因为软件行业的现状就用到了类继承。我敢说,你用类继承写过某个不错的应用程序,但是,如果你这样做了,那么你可能没有发挥 JavaScript 的优势。借助更加有用的方法,你就能用 JavaScript 写出更加轻量、可维护的应用程序。应用程序逃不掉修改的命运,如果你使用类继承的模式,那么当你用到服务于另一个需求的某个对象时,你将不得不继承随之而来的所有东东。当你想做单元测试时,就更加恶心了,你最终不得不为基类模拟出一整套需求,而你的目标只是为了测试高于继承链之上的简单属性。最好扔掉设计蓝图,根据数据流和对象、而非种类,开始思考你的程序。用这种方式思考,可以极大改善程序的可测试性、可维护性和简洁性。
6.坚持学习,不要失去信心
很多人抱怨 JavaScript 发展太快,有太多的坑,不过,这只是因为人们没有学习这门语言,没有专注于框架。JavaScript 肯定有一些糟粕,但是它也有一些精华,如果你想拥抱正面的东西,那么你就能充分发挥它的优势。我主要做 C# 开发,但是自从我开始正确地学习 JavaScript之后,它就变成了我的首选语言,因为它具备高度灵活的特点。如果你打算一试,那么 JavaScript 就是踏入函数式编程的入门语言,尤其在和 ReactJS 一起使用时。老实讲,我强烈推荐使用 JavaScript 进行函数式编程。
我希望本文有助于传播 JavaScript 优秀的福音,鉴于 JavaScript 的成功,我也想说句公道话,希望其它语言能从中寻找灵感、而不只是维持现状。
传送门:阮一峰《ECMAScript 6简介》
原文地址(original source):http://thenorthcode.net/2016/01/15/making-the-most-of-the-javascript-language/
作者(author): Rob Bollons(@RobBollons)
充分发挥 JavaScript 语言的优势的更多相关文章
- 《JavaScript语言精粹》学习笔记
一.in的用法 for...in 枚举一个对象的所有可枚举属性 检测DOM/BOM属性 if ("onclick" in elem) { // 元素支持onclick } if ( ...
- JavaScript语言精粹 笔记05 正则表达式
正则表达式 正则表达式以方法的形式被用于对字符串中的信息进行查找.替换画图提取操作.可处理正则表达式的方法有:regexp.exec, regexp.test,string.match, string ...
- <JavaScript语言精粹>-读书笔记(一)
用object.hasOwnProperty(variable)来确定这个属性名是否为该对象成员,还是来自于原型链. for(my in obj){ if(obj.hasOwnProperty(my) ...
- 《JavaScript语言精粹》小记
一.前言 以下内容均摘自<JavaScript语言精粹>一书,本人在读这本书时,发现作者诠释JavaScript很犀利,特别是数组部分,固记录下来,想和大家分享下. 随笔主要包含两大部分: ...
- javascript语言精粹
内容选自:<javascript语言精粹> 1.6种值会为假(==false),分别是false,null,undefined,' ',0,NaN 2.typeof有6种值,分别是'num ...
- 前端学习 第三弹: JavaScript语言的特性与发展
前端学习 第三弹: JavaScript语言的特性与发展 javascript的缺点 1.没有命名空间,没有多文件的规范,同名函数相互覆盖 导致js的模块化很差 2.标准库很小 3.null和unde ...
- Javascript 语言精粹 代码片段合集
Javascript 语言精粹 代码片段合集 标签:Douglas-Crockford Javascript 最佳实践 原文链接 更好的阅读体验 使用一个method 方法定义新方法 Function ...
- (转)JavaScript二:JavaScript语言的基本语法要求
摘自:http://blog.csdn.net/erlian1992 要学习好JavaScript,首先我们要懂JavaScript语言的一些基本语法要求: 一,区分大小写 JavaScript语言区 ...
- JavaScript语言精粹笔记
JavaScript语言精粹笔记 掌握语言的每个特性可以让你出风头,但是并不推荐,因为一部分的特性带来的麻烦可能远超本身的价值.正如书中所言,坏的材料并不能雕刻出好的作品,要成为一名更好的程序员,要取 ...
随机推荐
- BeanFactory调用getbean()对象
Spring通过资源加载器加载相应的XML文件,使用读取器读取资源加载器中的文件到读取器中,在读取过程中,解析相应的xml文件元素,转化为spring定义的数据结BeanDefinition,把相应的 ...
- JavaScript 原型与原型链
__proto__ 用来获取和设置对象原型,但它是非标准的.__proto__前后的双下划线,说明它本质上是一个内部属性,而不是一个正式的对外的API,只是由于浏览器广泛支持,才被加入了ES6.标准明 ...
- coco2d-html5制作弹弓射鸟第一部分---橡皮筋
一.写在前面的话 最近在学习cocos2d-html5方面的知识,一直想从事游戏方面的工作,自己也找了好多资料.网上关于cocos2d-html5的教程真的不多,也只有自己摸索,慢慢看示例代码.由于本 ...
- Android应用调试经常使用知识
1.Android应用启动过程调试 1).进入设置-->辅助功能-->开发人员选项:假设没有打开开发人员模式.在拨号里面输入*#*#6961#*#*: 2).找到选择调试应用,打开选择你要 ...
- FIR滤波器设计
FIR滤波器的优越性: 相位对应为严格的线性,不存在延迟失真,仅仅有固定的时间延迟: 因为不存在稳定性问题,设计相对简单: 仅仅包括实数算法,不涉及复数算法,不须要递推运算,长度为M,阶数为M-1,计 ...
- linux/unix运行级别
在SYSTEM V 风格的UNIX系统中,系统被分为不同的运行级别,这和BSD分支的UNIX有所不同,常用的为0~6七个级别:0关机 1单用户 2不带网络的多用户 3带网络的多用户 4保留,用户可以自 ...
- MVC 5 下,应用log4net收集异常信息
1.安装log4net. 首先在VS中通过nuget安装logenet,我用的是VS2013,截屏如下:
- Android-兼容问题
兼容性问题从何而来?答:使用了低版本没有的功能,可是目标设备包括低版本. 那我们如何解决兼容性问题? 1.如果是JAVA代码 1.1 使用TargetApi(x)注解,避免Android Lint报错 ...
- iOS_SN_LLDB常用命令
有一次因为封装一个控件,UI能正常显示就是不能点击,一点击就崩溃,而且异常断点也无法捕捉,把Xcode的僵尸对象打开,每次崩溃就打印一个地址,最后就必须根据地址寻找对象,可以使用frame varia ...
- UIButton上图片和文字的位置调整
UIButton 上默认是图片在左文字在右,而大多数情况这样默认的的显示形式都不能满足我们的需求,接下来我就这个问题分享一下我的心得. 默认情况下,不设置的效果,都是居中实现 UIButton *bu ...