一、为什么Javascript有设计缺陷?

这里有三个客观原因,导致Javascript的设计不够完善。

1. 设计阶段过于仓促

Javascript的设计,其实只用了十天。而且,设计师是为了向公司交差,本人其实不愿意这样设计(参见《Javascript诞生记》)。

另一方面,这种语言的设计初衷,是为了解决一些简单的网页互动(比如,检查”用户名”是否填写),并没有考虑复杂应用的需要。设计者做梦也想不到,Javascript将来可以写出像Gmail这种极其庞大复杂的网页。

2. 没有先例

Javascript同时结合了函数式编程和面向对象编程的特点,这很可能是历史上的第一例。而且直到今天为止,Javascript仍然是世界上唯一使用Prototype继承模型的主要语言。这使得它没有设计先例可以参考。

3. 过早的标准化

Javascript的发展非常快,根本没有时间调整设计。

1995年5月,设计方案定稿;10月,解释器开发成功;12月,向市场推出,立刻被广泛接受,全世界的用户大量使用。Javascript缺乏一个从小到大、慢慢积累用户的过程,而是连续的爆炸式扩散增长。大量的既成网页和业余网页设计者的参与,使得调整语言规格困难重重。

更糟的是,Javascript的规格还没来及调整,就固化了。

1996年8月,微软公司强势介入,宣布推出自己的脚本语言Jscript;11月,为了压制微软,网景公司决定申请Javascript的国际标准;1997年6月,第一个国际标准ECMA-262正式颁布。

也就是说,Javascript推出一年半之后,国际标准就问世了。设计缺陷还没有充分暴露就成了标准。相比之下,C语言问世将近20年之后,国际标准才颁布。

二、Javascript的10个设计缺陷

1. 不适合开发大型程序

Javascript没有名称空间(namespace),很难模块化;没有如何将代码分布在多个文件的规范;允许同名函数的重复定义,后面的定义可以覆盖前面的定义,很不利于模块化加载。

2. 非常小的标准库

Javascript提供的标准函数库非常小,只能完成一些基本操作,很多功能都不具备。

3. null和undefined

null属于对象(object)的一种,意思是该对象为空;undefined则是一种数据类型,表示未定义。

typeof null; // object
typeof undefined; // undefined

两者非常容易混淆,但是含义完全不同。

var foo;
alert(foo == null); // true
alert(foo == undefined); // true
alert(foo === null); // false
alert(foo === undefined); // true

在编程实践中,null几乎没用,根本不应该设计它。

4. 全局变量难以控制

Javascript的全局变量,在所有模块中都是可见的;任何一个函数内部都可以生成全局变量,这大大加剧了程序的复杂性。
a = 1;(function(){
b=2;
alert(a);
})(); // 1
alert(b); //2
5. 自动插入行尾分号

Javascript的所有语句,都必须以分号结尾。但是,如果你忘记加分号,解释器并不报错,而是为你自动加上分号。有时候,这会导致一些难以发现的错误。

比如,下面这个函数根本无法达到预期的结果,返回值不是一个对象,而是undefined。
function(){ return
{
i=1
};
}

原因是解释器自动在return语句后面加上了分号。

function(){  return;
{
          i=1
};
}

6. 加号运算符

+号作为运算符,有两个含义,可以表示数字与数字的和,也可以表示字符与字符的连接。
alert(1+10); // 11
alert("1"+"10"); // 110
1
2
alert(1+10); // 11
alert("1"+"10"); // 110

如果一个操作项是字符,另一个操作项是数字,则数字自动转化为字符。

alert(1+"10"); // 110
alert("10"+1); // 101

这样的设计,不必要地加剧了运算的复杂性,完全可以另行设置一个字符连接的运算符。

7. NaN

NaN是一种数字,表示超出了解释器的极限。它有一些很奇怪的特性:

NaN === NaN; //false
NaN !== NaN; //true
alert( 1 + NaN ); // NaN

与其设计NaN,不如解释器直接报错,反而有利于简化程序。

8. 数组和对象的区分

由于Javascript的数组也属于对象(object),所以要区分一个对象到底是不是数组,相当麻烦。Douglas Crockford的代码是这样的:

if ( arr &&
typeof arr === 'object'&&
typeof arr.length === 'number'&&
!arr.propertyIsEnumerable('length')){
alert("arr is an array");
}

9. == 和 ===

==用来判断两个值是否相等。当两个值类型不同时,会发生自动转换,得到的结果非常不符合直觉。

"" == "0" // false

0 == "" // true
0 == "0" // true
false == "false" // false
false == "0" // true
false == undefined // false
false == null // false
null == undefined // true
" trn" == 0 // true

因此,推荐任何时候都使用”===”(精确判断)比较符。

10. 基本类型的包装对象

Javascript有三种基本数据类型:字符串、数字和布尔值。它们都有相应的建构函数,可以生成字符串对象、数字对象和布尔值对象。
JavaScript

new Boolean(false);
new Number(1234);
new String("Hello World");

与基本数据类型对应的对象类型,作用很小,造成的混淆却很大。
alert( typeof 1234); // number
alert( typeof new Number(1234)); // object

关于Javascript的更多怪异行为,请参见Javascript Garden和wtfjs.com。

三、如何看待Javascript的设计缺陷?

既然Javascript有缺陷,数量还不少,那么它是不是一种很糟糕的语言?有没有前途?

回答是Javascript并不算糟糕,相反它的编程能力很强大,前途很光明。

首先,如果遵守良好的编程规范,加上第三方函数库的帮助,Javascript的这些缺陷大部分可以回避。

其次,Javascript目前是网页编程的唯一语言,只要互联网继续发展,它就必然一起发展。目前,许多新项目大大扩展了它的用途,node.js使得Javascript可以用于后端的服务器编程,coffeeScript使你可以用python和ruby的语法,撰写Javascript。

最后,只要发布新版本的语言标准(比如 ECMAscript 5),就可以弥补这些设计缺陷。当然,标准的发布和标准的实现是两回事,上述的很多缺陷也许会一直伴随到Javascript存在的最后一天。

阮一峰对js的见解(10大缺陷)的更多相关文章

  1. 2018.5.2(7:20到的办公室开始早课 阮一峰的JS) 所有的默默努力都是为了让自己看起来毫不费力

    continue语句用于立即终止本轮循环,返回循环结构的头部,开始下一轮循环. break语句用于跳出代码块或循环. 标签(label) JavaScript 语言允许,语句的前面有标签(label) ...

  2. 阮一峰的js教程,值得一读

    http://javascript.ruanyifeng.com/introduction/intro.html

  3. 【js 笔记】读阮一峰老师 es6 入门笔记 —— 第一章

      鉴于最近用 vuejs 框架开发项目,其中有很多涉及到 es6 语法不太理解所以便认真地读了一下这本书. 地址:http://es6.ruanyifeng.com/#README 第一章:let ...

  4. Javascript模块化编程(三):require.js的用法 作者: 阮一峰

    声明:转载自阮一峰的网络日志 这个系列的第一部分和第二部分,介绍了Javascript模块原型和理论概念,今天介绍如何将它们用于实战. 我采用的是一个非常流行的库require.js. 一.为什么要用 ...

  5. 27、理解js的继承机制(转载自阮一峰)

    Javascript继承机制的设计思想   作者: 阮一峰 日期: 2011年6月 5日 我一直很难理解Javascript语言的继承机制. 它没有"子类"和"父类&qu ...

  6. 读阮一峰老师 es6 入门笔记 —— 第一章

    鉴于最近用 vuejs 框架开发项目,其中有很多涉及到 es6 语法不太理解所以便认真地读了一下这本书. 地址:http://es6.ruanyifeng.com/#README 第一章:let ,c ...

  7. ES6特性:(阮一峰老师)学习总结

    ES6(阮一峰)学习总结   1.块级作用域的引入 在ES6之前,js只有全局作用域和函数作用域,ES6中let关键字为其引入了块级作用域. { var a = 5; let b = 6; } con ...

  8. 看完阮一峰的React教程后, 我写了一个TodoList

    看完阮一峰的React教程后,就自己做了这个TodoList,自己慢慢琢磨效率差了点但是作为入门小练习还是不错的. 以下是效果图:我的源码:todolistUI:bootstrap 4 一.组件化 我 ...

  9. 12种不宜使用的Javascript语法 ---阮一峰

    原文链接-阮一峰博客 1. == Javascript有两组相等运算符,一组是==和!=,另一组是===和!==.前者只比较值的相等,后者除了值以外,还比较类型是否相同. 请尽量不要使用前一组,永远只 ...

随机推荐

  1. git+github上传与管理

    1.首先下载并安装git,方便管理github上的代码 https://git-scm.com/downloads 2.然后点击安装好的git bash(注册好自己的github) git confi ...

  2. CROSS APPLY应用实例

    --功能说明:统计每个人的平均分数,新字段[AVG_Score]根据PersonID链接到原表[tbiz_AssScore]上 SELECT [ID] ,[ProjectID] ,[PersonID] ...

  3. 《转载》Spring MVC之@RequestParam @RequestBody @RequestHeader 等详解

    引言: 接上一篇文章,对@RequestMapping进行地址映射讲解之后,该篇主要讲解request 数据到handler method 参数数据的绑定所用到的注解和什么情形下使用: 简介: han ...

  4. WebView随学笔记

    对于WebView而言我们需要掌握的内容是: /** 学习目标:webView * 1).将WebView加入到应用中 * 2).使用WebView加载页面 * 3).获取网络访问 * 4).在Web ...

  5. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  6. Windows Server 2008 R2 IIS7.5 部署 MVC HTTP 404.0 Not Found 错误

    如图 在Windows Server 2008 R2 IIS7.5 部署 MVC HTTP 404.0 Not Found 错误,在Win7环境下测试正常,在百度中查找相关解决方法,如修改配置文件等, ...

  7. OpenGL glMultMatrixf() glPushMatrix() glPushMatrix()浅析

    我在之前的博客中曾提到过,OpenGL中坐标是采用行向量表示的,与之相对应的是,在矩阵变换中使用的是变换矩阵的转置,并且使用的是后乘的方式.本文直接使用下面的代码来及其后的图示来解释函数 p,li { ...

  8. Java异常处理机构(日常笔记)

    try{ 需要保护的代码块 }catch(异常类型 实例){ 捕捉到异常时的代码处理块 }[可有0~多个catch语句] finaly{ 不管异常是否发生都要执行的代码块}

  9. WinForm任务栏最小化

    在C#编写的WinForm里,在FormBorderStyle设为None的时候,任务栏点击程序图标,不会自动最小化.在主窗口WinForm.cs里加入如下代码后,即可恢复该功能. protected ...

  10. js 字符串操作函数

    concat() – 将两个或多个字符的文本组合起来,返回一个新的字符串. indexOf() – 返回字符串中一个子串第一处出现的索引.如果没有匹配项,返回 -1 . charAt() – 返回指定 ...