JavaScript

本页使用了标题或全文手工转换,现处于中国大陆简体模式
求闻百科,共笔求闻
JavaScript
编程范型事件驱动函数式指令式
设计者创造者布兰登·艾克ECMAScript规范的其他关键贡献者
发行时间1995年12月4日,​28年前​(1995-12-04[1]
稳定版本
ECMAScript 2019[2]
(2019年6月,​4年前​(2019-06
预览版本
ECMAScript 2020
类型系统动态类型鸭子类型
文件扩展名
主要实现产品
V8JavaScriptCoreSpiderMonkeyChakra
受启发于
AWKCHyperTalkJava[4]LuaPerlPythonSchemeSelf
施影响于
ActionScriptAtScriptCoffeeScriptDartJScript .NETLiveScriptObjective-JOpaQMLRakuTypeScript
JavaScript
扩展名.js
互联网媒体类型application/javascript
text/javascript (obsolete)[5]
统一类型标识com.netscape.javascript-source[6]
格式类型脚本语言

JavaScript(通常缩写为JS)是一种高级的、解释型编程语言[7]。JavaScript是一门基于原型头等函数的语言[8],是一门多范式的语言,它支持面向对象程序设计,指令式编程,以及函数式编程。它提供语法来操控文本、数组、日期以及正则表达式等,不支持I/O,比如网络、存储和图形等,但这些都可以由它的宿主环境提供支持。它已经由ECMA(欧洲电脑制造商协会)通过ECMAScript实现语言的标准化[7]。它被世界上的绝大多数网站所使用,也被世界主流浏览器ChromeIEFirefoxSafariOpera)支持。

JavaScript与Java在名字或语法上都有很多相似性,但这两门编程语言从设计之初就有很大的不同,JavaScript的语言设计主要受到了Self(一种基于原型的编程语言)和Scheme(一门函数式编程语言)的影响[8]。在语法结构上它又与C语言有很多相似(例如if条件语句、switch语句、while循环、do-while循环等)[9]

在客户端,JavaScript在传统意义上被实现为一种解释语言,但在最近,它已经可以被即时编译(JIT)执行。随着最新的HTML5CSS3语言标准的推行它还可用于游戏、桌面和移动应用程序的开发和在服务器端网络环境运行,如Node.js

历史

肇始于网景

1993年,美国国家超级电脑应用中心(NCSA)发表了NCSA Mosaic浏览器,这是最早流行的图形接口网页浏览器,它在全球资讯网的普及上发挥了重要作用[10]。1994年,Mosaic的主要开发人员随即创立了Netscape公司,并雇用了许多原来的NCSA Mosaic开发者用来开发Netscape Navigator,该公司的目标是取代NCSA Mosaic成为世界第一的网页浏览器。在四个月内,已经占据了四分之三的浏览器市场,并成为1990年代网际网路的主要浏览器[11]。网景预见到网路需要变得更动态。公司的创始人马克·安德森认为HTML需要一种胶水语言,让网页设计师和兼职程序设计师可以很容易地使用它来组装图片和外挂程序之类的组件,且代码可以直接编写在网页标记中。

1995年,网景招募了布兰登·艾克,目标是把Scheme语言嵌入到Netscape Navigator浏览器当中[12]。但更早之前,网景已经跟昇阳合作在Netscape Navigator中支持Java,这时网景内部产生激烈的争论[13]。后来网景决定发明一种与Java搭配使用的辅助脚本语言并且语法上有些类似[14],这个决策导致排除了采用现有的语言,例如PerlPythonTcl或Scheme。为了在其他竞争提案中捍卫JavaScript这个想法,公司需要有一个可以运作的原型。艾克在1995年5月仅花了十天时间就把原型设计出来了。

最初命名为Mocha,1995年9月在Netscape Navigator 2.0的Beta版中改名为LiveScript,同年12月,Netscape Navigator 2.0 Beta 3中部署时被重命名为JavaScript[1][15],当时网景公司与太阳微系统公司组成的开发联盟为了让这门语言搭上Java这个编程语言“热词”,因此将其临时改名为JavaScript,日后这成为大众对这门语言有诸多误解的原因之一。

微软采纳

微软公司于1995年首次推出Internet Explorer,从而引发了与Netscape的浏览器大战。微软对Netscape Navigator直译器进行了逆向工程,创建了JScript,以与处于市场领导地位的网景产品同台竞争。JScript也是一种JavaScript实现,这两个JavaScript语言版本在浏览器端共存意味着语言标准化的缺失,发展初期,JavaScript的标准并未确定,同期有网景的JavaScript,微软的JScript双峰并峙。除此之外,微软也在网页技术上加入了不少专属对象,使不少网页使用非微软平台及浏览器无法正常显示[16][17],导致在浏览器大战期间网页设计者通常会把“用Netscape可达到最佳效果”或“用IE可达到最佳效果”的标志放在主页[16][18]

标准化

1996年11月,网景正式向ECMA(欧洲计算机制造商协会)提交语言标准。1997年6月,ECMA以JavaScript语言为基础制定了ECMAScript标准规范ECMA-262。JavaScript成为了ECMAScript最著名的实现之一[19]。除此之外,ActionScriptJScript也都是ECMAScript规范的实现语言。尽管JavaScript作为给非程序人员的脚本语言,而非作为给程序人员的脚本语言来推广和宣传,但是JavaScript具有非常丰富的特性。

概论

一般来说,完整的JavaScript包括以下几个部分:

  • ECMAScript,描述了该语言的语法和基本对象
  • 文档对象模型(DOM),描述处理网页内容的方法和接口
  • 浏览器对象模型(BOM),描述与浏览器进行交互的方法和接口

JavaScript的基本特点如下:

  • 是一种解释性脚本语言(代码不进行预编译)。
  • 主要用来向HTML页面添加交互行为
  • 可以直接嵌入HTML页面,但写成单独的js文件有利于结构和行为的分离。

JavaScript常用来完成以下任务:

  • 嵌入动态文本于HTML页面
  • 对浏览器事件作出响应
  • 读写HTML元素
  • 在数据被提交到服务器之前验证数据
  • 检测访客的浏览器信息
  • 控制cookie,包括创建和修改等

特性

不同于服务器端脚本语言,例如PHPASP,JavaScript主要被作为客户端脚本语言在用户的浏览器上运行,不需要服务器的支持。所以在早期程序设计师比较青睐于JavaScript以减少对服务器的负担,而与此同时也带来另一个问题:安全性。而随着服务器变得强大,现在的程序员更喜欢运行于服务端的脚本以保证安全,但JavaScript仍然以其跨平台、容易上手等优势大行其道。同时,有些特殊功能(如AJAX)必须依赖JavaScript在客户端进行支持。随着引擎如V8和框架如Node.js的发展,及其事件驱动异步IO等特性,JavaScript逐渐被用来编写服务器端程序。且在近几年中,Node.js的出世,让JavaScript也具有了一定的服务器功能。

以下是ECMAScript通常实现所共有的特性。

指令式与结构化

JavaScript从支持许多C语言的结构化编程语法(例如if条件语句、while循环、switch语句、do-while循环等)。但作用域是一个例外:JavaScript在过去只支持使用var关键字来定义变量的函数作用域。ECMAScript 2015加入了let关键字来支持块级作用域[20]。意味着JavaScript现在既支持函数作用域又支持块级作用域。和C语言一样,JavaScript中的表达式和语句是不同的。有一点格式上的不同,JavaScript支持自动在语句末添加分号,因此允许忽略语句末尾的分号。[21]

弱类型

Javascript是弱类型的,这意味着变量可以被隐式地转换为另一个类型。[22]

  • 二元运算符+会把两个操作数转换为字符串,除非两个操作数都为数字类型。[23]这是因为+也表示字符串连接操作。
  • 二元操作符-会把两个操作数转换为数字类型。[24]
  • 一元操作符,包括+-,都会把操作数转换为数字。

下列为变量转换为字符串的例子:

  • 字符串类型不变。
  • 数字会转换为其字符串表示。
  • 数组的元素会转换为字符串,然后连接成通过逗号,分隔的长字符串。
  • 其它对象会转换为[object Object],其中Object中该对象的构造函数名。[25]

类型的隐藏转换,是JavaScript受到批评的原因之一,因为其增加了规则的复杂度与发生错误的可能性。[26]

JavaScript中诡异的隐式转换[27][28]:
左操作数 操作符 右操作数 结果
[](空数组) + [](空数组) ""(空字符串)
[](空数组) + {}(空对象) "[object Object]"(字符串)
false(布尔值) + [](空字符串) "false"(字符串)
"123"(字符串) + 1(数字) "1231"(字符串)
"123"(字符串) - 1(数字) 122 (数字)

动态化

类型

JavaScript是动态类型的,正如大部分脚本语言,其类型与值而不是与变量关联。例如变量可以为数值,随后又可被赋值为字符串。JavaScript提供了包括鸭子类型在内的方法来检测变量类型。

运行时估值

Javascript提供eval()函数,可以在运行时直接执行Javascript语句。[29]

基于原型的面向对象

在JavaScript中,对象是关联数组,通过原型(prototype,见下)进行扩充。每一个字符串键值提供对象的一个属性的名称。可以通过两种效果相同的方式进行访问:使用点号(obj.x)或使用方括号(obj['x'])。属性可以在运行时添加、重定义或删除。一个对象大多数属性(包括来自原型继承链的属性)都可以通过 for...in循环访问。[30]

原型

JavaScript使用原型,而许多其它面向对象语言使用类用于实现继承。有了原型,使得在JavaScript中模拟基于类的面向对象特征变成可能。[31]

函数作为对象构造器

函数在JavaScript中兼作为对象构造函数。在函数调用前加上new会创建一个原型的实例,并继承来自构造函数的属性和方法(包括来自Object原型)。[32]ECMAScript 5提供Object.create方法,可以显式地创建实例还不是自动从Object继承。[33]构造函数的prototype属性决定了用于新对象的内部原型。可以通过修改构造函数的原型的方法来为对象添加新的方法。也可以修改JavaScript的内部对象的原型,如ArrayObject。尽管可以这么做,但对Object原型进行修改并不是一个好的做法。因为大多数JavaScript对象都会从Object继承,且不会希望其原型做了修改。[34]

函数作为方法

与大多数而向对象的语言不同,在JavaScript中函数定义与方法定义没有明显的区别。唯一的区别在于调用时:当函数被作为方法调用时,函数的this会指向调用此函数的对象。[35]

传统的类定义与使用格式

ECMAScript ES6加入了对classextends关键字的支持,使得类的定义与继承行为更加类似于其它面向对象语言,同时也更加容易使用。[36][37]

函数式

在JavaScript中,函数是一等的,函数也被认为是对象。因此,函数也可以有属性与方法,例如call()bind等。[38]嵌套函数指定义于其它函数内部的函数,在外部函数被调用时,嵌套函数会被创建。另外,嵌套函数是一个闭包,在外部函数的作用域(包括常量,局部变量和参数)都成为内部函数状态的一部分,甚至在外部函数执行完毕后,内部函数的状态依然保留。[39]JavaScript同时也支持匿名函数[40]

其它

运行时环境

JavaScript通常依赖于运行时环境(例如浏览器)来提供对象和方法,脚本可以通过这些对象和方法与环境(例如网页DOM)进行交互。它还依赖于运行时环境来提供包含/导入脚本(例如HTML<script>元素)的功能。这本身不是语言功能,但是在大多数JavaScript实现中很常见。

异步

JavaScript一般来说是单线程的。[41]为了并发地处理事件,JavaScript程序输入/输出是使用事件回调函数执行的。例如,这意味着JavaScript可以在等待数据库查询返回信息时处理鼠标单击。ECMAScript ES6引入了Promise用于优雅地处理异步事件,其可以使得传统的基于回调的异步代码更加清晰与简单。[42][43]

变长参数

JavaScript中函数的参数长度是可变的,在函数内部可以通过arguments对象访问这些参数。[44]

编程

JavaScript是一种脚本语言,其源代码在发往客户端执行之前不需经过编译,而是将文本格式的字符代码发送给浏览器由浏览器解释执行。直译语言的弱点是安全性较差,而且在JavaScript中,如果一条执行不了,那么下面的语言也无法执行。而其解决办法就是于使用异常处理try {} catch () {}

console.log("a");  //这是正确的
console.log("b");  //这是正确的
console.logg("c"); //这是错误的,并且到这里会停下来
console.log("d");  //这是正确的
console.log("e");  //这是正确的

/* 解決办法 */
try { console.log("a"); } catch (e) {}  //这是正确的
try { console.log("b"); } catch (e) {}  //这是正确的
try { console.logg("c"); } catch (e) {} //这是错误的,但是到这里不会停下来,而是跳过
try { console.log("d"); } catch (e) {}  //这是正确的
try { console.log("e"); } catch (e) {}  //这是正确的

JavaScript被归类为直译语言,因为目前主流的引擎都是每次执行时加载代码并解译。V8是将所有代码解译后再开始执行,其他引擎则是逐行解译(SpiderMonkey会将解译过的指令暂存,以提高性能,称为即时编译),但由于V8的核心部分多数用JavaScript撰写(而SpiderMonkey是用C++),因此在不同的测试上,两者性能互有优劣。

与其相对应的是编译语言,例如C语言,以编译语言编写的程序在执行之前,必须经过编译,将代码编译为机器码,再加以执行。

范例

以下是一个简单的JavaScript Hello World

<!DOCTYPE HTML>
<html>
    <head>
    <title>简单的JavaScript Hello World</title>
        <script>
            document.write("Hello, world!");   // 直接插入页面中
            alert("Hello, world!");            // 弹窗显示
            console.log("Hello, world!");      // 在控制台(console)里显示,需要先开启开发工具控制台
        </script>
    </head>
    <body>
    HTML内容……
    </body>
</html>

或是在浏览器地址栏中使用javascript:,以互动方式表示:

javascript:alert("Hello world!");

版本

JavaScript最初开发于1996年,被使用于Netscape Navigator网页浏览器。同年微软在Internet Explorer发布了一个实现。由于商标问题,这项实现被命名为JScript。1997年,JavaScript已经被网景公司提交给ECMA制定为标准,称之为ECMAScript,标准编号ECMA-262。使用显式版本号声明对语言的引用,作为一项Mozilla的特性,已在较新版本中被移除(至少为Firefox 59)。Firefox 4是最后一个需要显式地在引用时声明明确版本号的版本(1.8.5)。

下列表格的资讯基于多个参考来源[45][46][47][48]

版本 发布日期 基于 Netscape
Navigator
Mozilla
Firefox
Internet
Explorer
Opera Safari Google
Chrome
旧版本,不再支持: 1.0 1996年3月 2.0 3.0
旧版本,不再支持: 1.1 1996年8月 3.0
旧版本,不再支持: 1.2 1997年6月 4.0 - 4.05 3
旧版本,不再支持: 1.3 1998年10月 ECMA-262 1st + 2nd edition 4.06 - 4.7x 4.0 5[49]
旧版本,不再支持: 1.4 Netscape
Server
6
旧版本,不再支持: 1.5 2000年11月 ECMA-262 3rd edition 6.0 1.0 5.5(JScript 5.5)
6(JScript 5.6)
7(JScript 5.7)
8(JScript 5.8)
7.0 3.0-5 1.0 - 10.0.666
旧版本,不再支持: 1.6 2005年11月 1.5 + Array extras + Array and string generics + E4X 1.5
旧版本,不再支持: 1.7 2006年10月 1.6 + Pythonic generators + Iterators + Let 2.0 28.0.1500.95
旧版本,不再支持: 1.8 2008年6月 1.7 + Generator expressions + Expression closures 3.0 11.50
旧版本,不再支持: 1.8.1 1.8 + native JSON support + Minor updates 3.5
旧版本,不再支持: 1.8.2 2009年6月22日 1.8.1 + Minor updates 3.6
旧版本,不再支持: 1.8.5 2010年7月27日 1.8.2 + New features for ECMA-262 5th edition compliance 4.0

参见

参考文献

  1. 1.0 1.1 Press release announcing JavaScript, "Netscape and Sun announce JavaScript", PR Newswire, December 4, 1995
  2. Standard ECMA-262. Ecma International. 2017-07-03 [2020-02-16]. 
  3. nodejs/node-eps. GitHub. [2020-02-16]. 
  4. "Coders at Work: Reflections on the Craft of Programming". 
  5. RFC 4329. [2012-03-02]. 
  6. System-Declared Uniform Type Identifiers. Mac OS X Reference Library. Apple Inc. [2010-03-05]. 
  7. 7.0 7.1 David, Flanagan. JavaScript: The Definitive Guide 6th. O'Reilly & Associates. ISBN 978-0-596-80552-4. 
  8. 8.0 8.1 ECMAScript Language Overview (PDF): 4. 2007-10-23 [2009-05-03]. 
  9. JavaScript: The World's Most Misunderstood Programming Language. www.crockford.com. [2016-08-17]. 
  10. Bloomberg Game Changers: Marc Andreessen. Bloomberg. 2011-03-17 [2011-12-07]. 
  11. Enzer, Larry. The Evolution of the Web Browsers. Monmouth Web Developers. 2018-08-31 [2018-08-31]. 
  12. Chapter 4. How JavaScript Was Created. [2018-07-14]. 
  13. Severance, Charles. JavaScript: Designing a Language in 10 Days. Computer (IEEE Computer Society). 2012-02, 45 (2): 7–8 [2013-03-23]. doi:10.1109/MC.2012.57. 
  14. TechVision: Innovators of the Net: Brendan Eich and JavaScript (HTML). 2009-03-19 [2009-03-19]. 
  15. TechVision: Innovators of the Net: Brendan Eich and JavaScript. web.archive.org. [2009-03-19]. 
  16. 16.0 16.1 Champeon, Steve. JavaScript, How Did We Get Here?. oreilly.com. 2001-04-06 [2016-07-16]. 
  17. Microsoft Internet Explorer 3.0 Beta Now Available. microsoft.com. Microsoft. 1996-05-29 [2016-07-16]. 
  18. McCracken, Harry. The Unwelcome Return of "Best Viewed with Internet Explorer". technologizer.com. 2010-09-16 [2016-07-16]. 
  19. Nicholas, Zakas. Professional JavaScript for Web Developers 3rd. Wrox. 2012. ISBN 978-1-118-02669-4. 
  20. 存档副本. [2020-07-09]. 
  21. 存档副本. [2020-07-09]. 
  22. 存档副本. [2020-07-09]. 
  23. 存档副本. [2020-07-09]. 
  24. 存档副本. [2020-07-09]. 
  25. 存档副本. [2020-07-09]. 
  26. 存档副本. [2020-07-09]. 
  27. 存档副本. [2020-07-09]. 
  28. 存档副本. [2020-07-09]. 
  29. 存档副本. [2020-07-09]. 
  30. 存档副本. [2020-07-09]. 
  31. 存档副本. [2020-07-09]. 
  32. 使用对象 - JavaScript | MDN
  33. 存档副本. [2020-07-09]. 
  34. 存档副本. [2020-07-09]. 
  35. 存档副本. [2020-07-09]. 
  36. 存档副本. [2020-07-09]. 
  37. 存档副本. [2020-07-09]. 
  38. 存档副本. [2020-07-09]. 
  39. 存档副本. [2020-07-09]. 
  40. 存档副本. [2020-07-09]. 
  41. 存档副本. [2020-07-09]. 
  42. 存档副本. [2020-07-09]. 
  43. 存档副本. [2020-07-09]. 
  44. 存档副本. [2020-07-09]. 
  45. New in JavaScript. developer.mozilla.org. 2014 [2016-07-16]. 
  46. JavaScript – JScript – ECMAScript version history. Webmasterworld.com. [2009-12-17]. 
  47. John Resig. Versions of JavaScript. Ejohn.org. [2009-05-19]. 
  48. Version Information (JScript). Msdn.microsoft.com. [2009-12-17]. 
  49. What Version of JavaScript. [2016-08-27]. 

外部链接