JavaScript的历史

1994年,网景公司(Netscape)发布了Navigator浏览器0.9版。这是历史上第一个比较成熟的网络浏览器,轰动一时。但是,这个版本的浏览器只能用来浏览,不具备与访问者互动的能力。网景公司急需一种网页脚本语言,使得浏览器可以与网页互动。

网页脚本语言到底是什么语言?网景公司当时有两个选择:一个是采用现有的语言,比如Perl、Python、Tcl、Scheme等等,允许它们直接嵌入网页;另一个是发明一种全新的语言。
这两个选择各有利弊。第一个选择,有利于充分利用现有代码和程序员资源,推广起来比较容易;第二个选择,有利于开发出完全适用的语言,实现起来比较容易。到底采用哪一个选择,网景公司内部争执不下,管理层一时难以下定决心。

就在这时,发生了另外一件大事:1995年Sun公司将Oak语言改名为Java,正式向市场推出。
Sun公司大肆宣传,许诺这种语言可以”一次编写,到处运行”(Write Once, Run Anywhere),它看上去很可能成为未来的主宰。网景公司动了心,决定与Sun公司结成联盟。它不仅允许Java程序以applet(小程序)的形式,直接在浏览器中运行;甚至还考虑直接将Java作为脚本语言嵌入网页,只是因为这样会使HTML网页过于复杂,后来才不得不放弃。总之,当时的形势就是,网景公司的整个管理层,都是Java语言的信徒,Sun公司完全介入网页脚本语言的决策。因此,Javascript后来就是网景和Sun两家公司一起携手推向市场的,这种语言被命名为”Java+script”并不是偶然的。

此时,34岁的系统程序员Brendan Eich登场了。1995年4月,网景公司录用了他。

Brendan Eich的主要方向和兴趣是函数式编程,网景公司招聘他的目的,是研究将Scheme语言作为网页脚本语言的可能性。Brendan Eich本人也是这样想的,以为进入新公司后,会主要与Scheme语言打交道。
JavaScript的诞生 - 图1
仅仅一个月之后,1995年5月,网景公司做出决策,未来的网页脚本语言必须”看上去与Java足够相似”,但是比Java简单,使得非专业的网页作者也能很快上手。这个决策实际上将Perl、Python、Tcl、Scheme等非面向对象编程的语言都排除在外了。Brendan Eich被指定为这种”简化版Java语言”的设计师。
5.
但是,他对Java一点兴趣也没有。为了应付公司安排的任务,他只用10天时间就把Javascript设计出来了。
由于设计时间太短,语言的一些细节考虑得不够严谨,导致后来很长一段时间,Javascript写出来的程序混乱不堪。如果Brendan Eich预见到,未来这种语言会成为互联网第一大语言,全世界有几百万学习者,他会不会多花一点时间呢?
总的来说,他的设计思路是这样的:

  (1)借鉴C语言的基本语法;   (2)借鉴Java语言的数据类型和内存管理;   (3)借鉴Scheme语言,将函数提升到”第一等公民”(first class)的地位;   (4)借鉴Self语言),使用基于原型(prototype)的继承机制。

所以,Javascript语言实际上是两种语言风格的混合产物——(简化的)函数式编程+(简化的)面向对象编程。这是由Brendan Eich(函数式编程)与网景公司(面向对象编程)共同决定的。
——摘抄自阮一峰的JavaScript诞生记

ECMAScript标准的制定

时间
1997年6月,第一版ECMAScript发布
1999年12月,第三版发布(ES3),这个版本使用最广
第四版,流产
2009年12月,第五版发布,增加了一些功能
2015年6月,第六版发布(ES6),新浏览器都支持这一版
之后每年发布一版,版本号以年份命名

JS与ECMAScript的关系

ECMAScript是纸上的标准,JS是浏览器的实现
纸上的标准往往落后于浏览器,先实现,再写进标准

JavaScript的兴起

杀手级应用Gmail
2004年愚人节,谷歌发布Gmail在线网页
当时人们认为网页只能用来看新闻和图片
Gmail的发布让用户和开发者眼前一亮
2005年,Jesse将谷歌用到的技术命名为AJAX
从此,前端技术正式出现
在此之前的网页开发都是由后端和设计师完成
2006年,JQuery发布,是目前最长寿的JS库
后来十年,JQuery大放异彩,直到IE不行了,JQuery才稍微没有那么火

JavaScript爆发

V8快如闪电
Chrome的JS引擎叫做V8(不是JS的第八版,是这个作者写了8个引擎,第八个是给JS写的)
2009年,Ryan基于V8创建了Node.js
2010年,Isaac基于Node.js写出了npm
前端工程师可以再浏览器之外执行JS了,Node.js快速风靡
同年,TJ受Sinatra启发,发布了Express.js
从此,前端工程师可以愉快地写后端应用了

JavaScript设计缺陷

三个客观原因
1.设计阶段过于仓促
JavaScript的设计,其实只用了10天。而且,设计师是为了向公司交差,本人并不愿意这样设计。另一方面,设计的初衷,是为了解决简单的网页互动,并没有考虑复杂应用的需要
2.没有先例
JavaScript同时结合了函数式编程和面向对象编程的特点,很可能是历史上的第一例。而且直到今天,JS仍是世界上唯一使用Prototype继承模型的主要语言。
3.过早的标准化
Javascript的发展非常快,根本没有时间调整设计。
1995年5月,设计方案定稿;10月,解释器开发成功;12月,向市场推出,立刻被广泛接受,全世界的用户大量使用。Javascript缺乏一个从小到大、慢慢积累用户的过程,而是连续的爆炸式扩散增长。大量的既成网页和业余网页设计者的参与,使得调整语言规格困难重重。
更糟的是,Javascript的规格还没来及调整,就固化了。
1996年8月,微软公司强势介入,宣布推出自己的脚本语言Jscript;11月,为了压制微软,网景公司决定申请Javascript的国际标准;1997年6月,第一个国际标准ECMA-262正式颁布。
也就是说,Javascript推出一年半之后,国际标准就问世了。设计缺陷还没有充分暴露就成了标准。相比之下,C语言问世将近20年之后,国际标准才颁布。
为了兼容旧网站,ES不能删除旧的特性

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

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

  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   “ \t\r\n” == 0 // true

因此,推荐任何时候都使用”===”(精确判断)比较符。
10. 基本类型的包装对象
Javascript有三种基本数据类型:字符串、数字和布尔值。它们都有相应的建构函数,可以生成字符串对象、数字对象和布尔值对象。

  new Boolean(false);   new Number(1234);   new String(“Hello World”);

与基本数据类型对应的对象类型,作用很小,造成的混淆却很大。

  alert( typeof 1234); // number   alert( typeof new Number(1234)); // object

js中==和===区别

简单来说: == 代表相同, ===代表严格相同, 为啥这么说呢,
这么理解: 当进行双等号比较时候: 先检查两个操作数数据类型,如果相同, 则进行===比较, 如果不同, 则愿意为你进行一次类型转换, 转换成相同类型后再进行比较, 而===比较时, 如果类型不同,直接就是false.

操作数1 == 操作数2, 操作数1 === 操作数2
比较过程:
  双等号==:
  (1)如果两个值类型相同,再进行三个等号(===)的比较
  (2)如果两个值类型不同,也有可能相等,需根据以下规则进行类型转换在比较:
    1)如果一个是null,一个是undefined,那么相等
    2)如果一个是字符串,一个是数值,把字符串转换成数值之后再进行比较

  三等号===:
  (1)如果类型不同,就一定不相等
  (2)如果两个都是数值,并且是同一个值,那么相等;如果其中至少一个是NaN,那么不相等。(判断一个值是否是NaN,只能使用isNaN( ) 来判断)
  (3)如果两个都是字符串,每个位置的字符都一样,那么相等,否则不相等。
  (4)如果两个值都是true,或是false,那么相等
  (5)如果两个值都引用同一个对象或是函数,那么相等,否则不相等
  (6)如果两个值都是null,或是undefined,那么相等