BLOG

Record, summarize, and improve.

Java Script

概述 指令式与结构化 弱类型 动态化 类型 运行时估值 基于原型的面向对象 原型 函数作为对象构造器 函数作为方法 传统的类定义与使用格式 函数式 其它 运行时环境 异步 变长参数 example JavaScript引擎 JIT引擎 运行时解释器 JavaScript 语法 JavaScript 标准 JavaScript 字面量 JavaScript 变量 JavaScript 操作符 赋值运算符 比较运算符 算术运算符 位运算符 位逻辑运算符 移位运算符 逻辑运算符 短路求值 字符串运算符 条件(三元)运算符 逗号操作符 一元操作符 delete typeof void 关系运算符 in instanceof 运算符优先级 表达式 基本表达式 this 分组操作符 数值推导 左值表达式 new 扩展语句 JavaScript 关键字 JavaScript 保留关键字 1. goto keyword 2. in keyword 3. instanceof keyword 4. arguments keyword 5. public C 6. Do keyword 7. Function keyword 8. class* keyword 9. return keyword 10. Eval keyword 11. For keyword 12. if keyword 13. Break keyword 14. debugger keyword 15. Yield keyword 16. Continue keyword 17. export* keyword 18. null keyword 19. New keyword 20. throw keyword 21. while keyword 22. Delete keyword 23. super* keyword 24. default keyword 25. protected keyword 26. Package keyword 27. Interface keyword 28. implements keyword 29. With keyword 30. import* keyword 31. typeof keyword 32. Var keyword 33. await* keyword 34. enum* keyword 35. try keyword 36. Catch keyword 37. finally keyword 38. Const keyword 39. private keyword 40. True keyword 41. False keyword 42. Void keyword 43. Case keyword 44. switch keyword 45. extends* keyword 46. This keyword 47. let* keyword 48. else keyword 49. Static keyword JavaScript 对象、属性和方法 Java 保留关键字 Windows 保留关键字 HTML 事件句柄

概述

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

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

对于客户端来说,JavaScript通常被实现为一门解释语言,但如今它已经可以被即时编译(JIT)。随着HTML5CSS3语言标准的推行,它还可以用于游戏、桌面和移动应用程序的开发,以及在服务器端网络环境运行(如Node.js)。

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

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

JavaScript的基本特点如下:

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

JavaScript常用来完成以下任务:

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

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

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

指令式与结构化

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

弱类型

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

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

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

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

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

左操作数 操作符 右操作数 结果
[](空数组) + [](空数组) ""(空字符串)
[](空数组) + {}(空对象) "[object Object]"(字符串)
false(布尔值) + ""(空字符串) "false"(字符串)
"123"(字符串) + 1(数字) "1231"(字符串)
"123"(字符串) - 1(数字) 122 (数字)

动态化

类型

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

运行时估值

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

基于原型的面向对象

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

原型

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

函数作为对象构造器

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

函数作为方法

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

=>

这是一个箭头函数。箭头函数是一种短语法,由 ECMAscript 6 引入,可以像使用函数表达式一样使用。换句话说,您可以经常使用它们来代替像function (foo) {...}. 但它们有一些重要的区别。例如,它们不绑定自己的值this(讨论见下文)。

箭头函数是 ECMAscript 6 规范的一部分。并非所有浏览器都支持它们,但Node v.4.0+和 2018 年使用的大多数现代浏览器都部分或完全支持它们。

与函数表达式相比,箭头函数表达式(也称为胖箭头函数)的语法更短,并且在词法上绑定this值(不绑定它自己的thisargumentssuper, or new.target)。箭头函数总是匿名的。这些函数表达式最适合非方法函数,它们不能用作构造函数。

this关于箭头函数如何工作的解释

箭头函数最方便的特性之一隐藏在上面的文本中:

箭头函数...词法绑定this值(不绑定它自己的this...)

简单来说,这意味着箭头函数保留this其上下文中的值,而没有自己的this. 传统函数可能会绑定自己的this值,具体取决于它的定义和调用方式。这可能需要大量的操作self = this;,这样才能从一个函数访问或操作this另一个函数

var a = [
  "We're up all night 'til the sun",
  "We're up all night to get some",
  "We're up all night for good fun",
  "We're up all night to get lucky"
];

// These two assignments are equivalent:

// Old-school:
var a2 = a.map(function(s){ return s.length });

// ECMAscript 6 using arrow functions
var a3 = a.map( s => s.length );

// both a2 and a3 will be equal to [31, 30, 31, 31]
传统的类定义与使用格式

ECMAScript 2015中加入了对classextends关键字的支持,使得类的定义与继承更类似于其他的面向对象语言,同时也更易使用。

函数式

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

其它

运行时环境

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

异步

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

变长参数

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

example

以下是一个简单的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引擎是一个专门处理JavaScript脚本的虚拟机,一般会附带在网页浏览器之中。

一个典型的浏览器有一个图形引擎和一个独立的JavaScript引擎。这样JavaScript引擎能够被更方便的测试、重新生成或者在另一些项目中使用。

JIT引擎

下列是用于网页浏览器的新一代ECMAScript引擎,它们都实现了即时编译(JIT)或这个想法的变体。即时编译的性能利益使其更加适合于用JavaScript写的网页应用:

运行时解释器

下列引擎使用运行时解释器,它们不编译成本地机器代码故而一般而言运行得更慢:

  • Rhino:来自Mozilla的JavaScript引擎之一,使用Java平台
  • Jsish:一个JavaScript解释器,内建了SQLiteJSONWebSocketZIP虚拟文件系统支持。
  • Duktape:一个小体量易于嵌入的Ecmascript E5/E5.1引擎。
  • MuJS:一个轻量级的ECMAScript解释器库,设计用于嵌入其他软件中来为其扩展上脚本功能。最初为MuPDF开发。
  • njs:为网页服务器脚本和最快的VM上下文创建而优化的轻量级的JavaScript解释器,用于nginx
  • Moddable SDK:是为微控制器建造应用的开发工具和运行时软件的组合,Kinoma平台的后继者,目前是活跃计划并致力于支持更新近版本的ECMAScript。
  • Espruino:特别用于微控制器的一个非常小体量的解释器,通过执行源代码(而非字节码),可以运行在小于8kB的RAM之下。
  • mjs:设计用于资源有限的微控制器的JavaScript引擎,它实现了ECMAScript 6的一个严格子集。
  • JerryScript:三星为小于64KB RAM的微控制器提供的一个轻量级的JavaScript引擎。
  • V7:嵌入式JavaScript引擎,实现了ECMAScript 5.1,声称是用C写的最小的JavaScript引擎,现已经让位给mjs。
  • Tiny-JS:用C++写成的极小化的JavaScript解释器。
  • JS-Interpreter,用JavaScript实现的轻量级的JavaScript解释器,带有step-by-step执行。
  • GNU GuileGNU Scheme实现,自版本1.9起提供ECMAScript 3.1解释器。

JavaScript 语法

JavaScript 标准

所有的现代浏览器完全支持 ECMAScript 3(ES3,JavaScript 的第三版,从 1999 年开始)。

ECMAScript 4(ES4)未通过。

ECMAScript 5(ES5,2009 年发布)。

ECMAScript 6(ES6,2015 年发布),是 JavaScript 最新的官方版本。

随着时间的推移,我们开始看到,所有的现代浏览器已经完全支持 ES6。


JavaScript 字面量

数字(Number)字面量 可以是整数或者是小数,或者是科学计数(e)

3.14
1001
123e5

字符串(String)字面量 可以使用单引号或双引号:

"John Doe"
'John Doe'

表达式字面量 用于计算:

5 + 6
5 * 10

数组(Array)字面量 定义一个数组:

[40, 100, 1, 5, 25, 10]

对象(Object)字面量 定义一个对象:

{firstName:"John", lastName:"Doe", age:50, eyeColor:"blue"}

函数(Function)字面量 定义一个函数:

function myFunction(a, b) { return a * b;}

JavaScript 变量

JavaScript 使用关键字 var 来定义变量, 使用等号来为变量赋值:

var x, length
x = 5
length = 6

变量可以通过变量名访问。在指令式语言中,变量通常是可变的。字面量是一个恒定的值。

JavaScript 操作符

一个完整详细的运算符列表和表达式可以参见 reference

JavaScript 拥有如下类型的运算符。本节描述了运算符和运算符的优先级。

赋值运算符

一个 赋值运算符 (assignment operator) (en-US) 将它右边操作数的值赋给它左边的操作数。最简单的赋值运算符是等于(=),它将右边的操作数值赋给左边的操作数。那么 x = y 就是将 y 的值赋给 x。

还有一些复合赋值操作符,它们是下表列出的这些操作的缩写:

比较运算符

比较运算符 (en-US)比较它的操作数并返回一个基于表达式是否为真的逻辑值。操作数可以是数字,字符串,逻辑,对象值。字符串比较是基于标准的字典顺序,使用 Unicode 值。在多数情况下,如果两个操作数不是相同的类型,JavaScript 会尝试转换它们为恰当的类型来比较。这种行为通常发生在数字作为操作数的比较。类型转换的例外是使用 === 和 !== 操作符,它们会执行严格的相等和不相等比较。这些运算符不会在检查相等之前转换操作数的类型。下面的表格描述了该示例代码中的各比较运算符

运算符 描述 返回 true 的示例
等于 Equal (en-US) (==) 如果两边操作数相等时返回 true。 3 == var1 "3" == var1 3 == '3'
不等于 Not equal (en-US) (!=) 如果两边操作数不相等时返回 true var1 != 4 var2 != "3"
全等 Strict equal (en-US) (===) 两边操作数相等且类型相同时返回 true。参见 Object.is and sameness in JS. 3 === var1
不全等 Strict not equal (en-US) (!==) 两边操作数不相等或类型不同时返回 true。 var1 !== "3" 3 !== '3'
大于 Greater than (en-US) (>) 左边的操作数大于右边的操作数返回 true var2 > var1 "12" > 2
大于等于 Greater than or equal (en-US) (>=) 左边的操作数大于或等于右边的操作数返回 true var2 >= var1 var1 >= 3
小于 Less than (en-US) (<) 左边的操作数小于右边的操作数返回 true var1 < var2 "2" < 12
小于等于 Less than or equal (en-US) (<=) 左边的操作数小于或等于右边的操作数返回 true var1 <= var2 var2 <= 5
算术运算符

算术运算符使用数值 (字面量或者变量) 作为操作数并返回一个数值。标准的算术运算符就是加减乘除 (+ - * /)。当操作数是浮点数时,这些运算符表现得跟它们在大多数编程语言中一样(特殊要注意的是,除零会产生Infinity)。例如:

1 / 2; // 0.5
1 / 2 == 1.0 / 2.0; // true

除了标准的算术运算符(+, - ,* /),JavaScript 还提供了下表中的算术运算符。

Operator Description Example
求余 (%) 二元运算符。返回相除之后的余数。 12 % 5 返回 2。
自增 (++) 一元运算符。将操作数的值加一。如果放在操作数前面 (++x), 则返回加一后的值; 如果放在操作数后面 (x++), 则返回操作数原值,然后再将操作数加一。 var x=3; console.log(++x); //4 console.log(x); //4 var y=3; console.log(y++); //3 console.log(y); //4
自减 (--) 一元运算符。将操作数的值减一。前后缀两种用法的返回值类似自增运算符。 var x=3; console.log(--x); //输入 2,x=2var y=3;console.log(y--);//输出 3,x=2;
一元负值符 (-) 一元运算符,返回操作数的负值。 var x=3; console.log(-x); //输入 -3
一元正值符 (+) 一元运算符,如果操作数在之前不是 number,试图将其转换为 number console.log( +'3' ); // 3 console.log( '3' ); // '3' console.log(+true); // 1
指数运算符 (**) 计算 base(底数) 的 exponent(指数) 次方, 表示为base^exponent 2 ** 3 returns 810 ** -1 returns 0.1.
位运算符

位运算符将它的操作数视为 32 位元的二进制串(0 和 1 组成)而非十进制八进制或十六进制数。例如:十进制数字 9 用二进制表示为 1001,位运算符就是在这个二进制表示上执行运算,但是返回结果是标准的 JavaScript 数值。

下表总结了 JavaScript 的位运算符。

Operator Usage Description
按位与 AND (en-US) a & b 在 a,b 的位表示中,每一个对应的位都为 1 则返回 1,否则返回 0.
按位或 OR (en-US) a | b 在 a,b 的位表示中,每一个对应的位,只要有一个为 1 则返回 1,否则返回 0.
按位异或 XOR (en-US) a ^ b 在 a,b 的位表示中,每一个对应的位,两个不相同则返回 1,相同则返回 0.
按位非 NOT (en-US) ~ a 反转被操作数的位。
左移 shift (en-US) a << b 将 a 的二进制串向左移动 b 位,右边移入 0.
算术右移 a >> b 把 a 的二进制表示向右移动 b 位,丢弃被移出的所有位。(译注:算术右移左边空出的位是根据最高位是 0 和 1 来进行填充的)
无符号右移 (左边空出位用 0 填充) a >>> b 把 a 的二进制表示向右移动 b 位,丢弃被移出的所有位,并把左边空出的位都填充为 0
位逻辑运算符

概念上来讲,位逻辑运算符工作流程如下:

  • 操作数被转换为 32bit 整數,以位序列(0 和 1 组成)表示。若超過 32bits,則取低位 32bit,如下所示:

    Before: 11100110111110100000000000000110000000000001
    After: 10100000000000000110000000000001

  • 第一个操作数的每一位都与第二个操作数的对应位组对:第一位对应第一位,第二位对应第二位,以此类推。
  • 运算符被应用到每一对"位"上,最终的运算结果由每一对“位”的运算结果组合起来。

例如,十进制数 9 的二进制表示是 1001,十进制数 15 的二进制表示是 1111.因此,当位运算符应用到这两个值时,结果如下:

表达式 结果 二进制描述
15 & 9 9 1111 & 1001 = 1001
15 | 9 15 1111 | 1001 = 1111
15 ^ 9 6 1111 ^ 1001 = 0110
~15 -16 ~ 0000 0000 … 0000 1111 = 1111 1111 … 1111 0000
~9 -10 ~ 0000 0000 … 0000 1001 = 1111 1111 … 1111 0110

注意位运算符“非”将所有的 32 位取反,而值的最高位 (最左边的一位) 为 1 则表示负数 (2-补码表示法)。

移位运算符

移位运算符带两个操作数:第一个是待移位的数,第二个是指定第一个数要被移多少位的数。移位的方向由运算符来控制。

移位运算符把操作数转为 32bit 整数,然后得出一个与待移位数相同种类的值。

移位运算符列表如下。

移位运算符

运算符 描述 范例
<< (左移位) 将第一个操作数向左移动指定数量的位。左边移出位被抛弃。左边移出的几位被丢弃。右边多出的空位由 0 补齐 9<<2 产生 36,因为 1001 移位 2 比特向左变为 100100,它是 36。
>> (带符号右移) 将第一个操作数向右移动指定数量的位。右边移出位被抛弃。左边多出的空位由原值的最左边数字补齐。 9>>2 产生 2,因为 1001 移位 2 位向右变为 10,其是 2。同样,-9>>2 产生 -3,由于符号被保留。
>>> (补零右移) 将第一个操作数向右移动指定数量的位。右边移出位被抛弃。左边多出的空位由 0 补齐。 19>>>2产生 4,因为 10011 移位 2 位向右变为 100,它是 4。对非负数值,补零右移和带符号右移产生相同结果。
逻辑运算符

逻辑运算符常用于布尔(逻辑)值之间; 当操作数都是布尔值时,返回值也是布尔值。不过实际上&&||返回的是一个特定的操作数的值,所以当它用于非布尔值的时候,返回值就可能是非布尔值。逻辑运算符的描述如下。

逻辑运算符

运算符 范例 描述
逻辑与 (en-US) (&&) expr1 && expr2 (逻辑与) 如果 expr1 能被转换为 false,那么返回 expr1;否则,返回expr2。因此,&&用于布尔值时,当操作数都为 true 时返回 true;否则返回 false.
逻辑或 (en-US) (||) expr1 || expr2 (逻辑或) 如果 expr1 能被转换为 true,那么返回 expr1;否则,返回expr2。因此,|| 用于布尔值时,当任何一个操作数为 true 则返回 true;如果操作数都是 false 则返回 false。
逻辑非 (en-US) (!) !expr (逻辑非) 如果操作数能够转换为 true 则返回 false;否则返回 true。

能被转换为false的值有null0NaN, 空字符串 ("") 和undefined。(译者注:也可以称作”falsy“)

下面是&&(逻辑"与")操作符的示例。

var a1 =  true && true;     // t && t returns true
var a2 =  true && false;    // t && f returns false
var a3 = false && true;     // f && t returns false
var a4 = false && (3 == 4); // f && f returns false
var a5 = "Cat" && "Dog";    // t && t returns Dog
var a6 = false && "Cat";    // f && t returns false
var a7 = "Cat" && false;    // t && f returns false

下面是 ||(逻辑"或")操作符的示例。

var o1 =  true || true;     // t || t returns true
var o2 = false || true;     // f || t returns true
var o3 =  true || false;    // t || f returns true
var o4 = false || (3 == 4); // f || f returns false
var o5 = "Cat" || "Dog";    // t || t returns Cat
var o6 = false || "Cat";    // f || t returns Cat
var o7 = "Cat" || false;    // t || f returns Cat

下面是!(逻辑"非")操作符的示例。

var n1 = !true;  // !t returns false
var n2 = !false; // !f returns true
var n3 = !"Cat"; // !t returns false
短路求值

作为逻辑表达式进行求值是从左到右,它们是为可能的“短路”的出现而使用以下规则进行测试:

  • false && anything // 被短路求值为 false
  • true || anything // 被短路求值为 true

逻辑的规则,保证这些评估是总是正确的。请注意,上述表达式的anything部分不会被求值,所以这样做不会产生任何副作用。

字符串运算符

除了比较操作符,它可以在字符串值中使用,连接操作符(+)连接两个字符串值相连接,返回另一个字符串,它是两个操作数串的结合。

例如,

console.log("my " + "string"); // console logs the string "my string".

简写操作符 += 也可以用来拼接字符串,例如:

var myString = "alpha";
myString += "bet"; // 返回 "alphabet"
条件(三元)运算符

条件运算符是 JavaScript 中唯一需要三个操作数的运算符。运算的结果根据给定条件在两个值中取其一。语法为:

条件 ? 值 1 : 值 2

如果条件为真,则结果取值 1。否则为值 2。你能够在任何允许使用标准运算符的地方使用条件运算符。

例如,

var status = (age >= 18) ? "adult" : "minor";

当 age 大于等于 18 的时候,将“adult”赋值给 status;否则将“minor”赋值给 status

逗号操作符

逗号操作符,)对两个操作数进行求值并返回最终操作数的值。它常常用在 for 循环中,在每次循环时对多个变量进行更新。

例如,假如 a 是一个二维数组,每个维度各有 10 个元素,以下代码利用逗号操作符来同时改变两个变量的值。这段代码的功能是打印出该二维数组的对角线元素的值:

var x = [0,1,2,3,4,5,6,7,8,9]
var a = [x, x, x, x, x];

for (var i = 0, j = 9; i <= j; i++, j--)
  console.log('a[' + i + '][' + j + ']= ' + a[i][j]);
一元操作符

一元操作符仅对应一个操作数。

delete

delete操作符,删除一个对象的属性或者一个数组中某一个键值。语法如下:

delete objectName.property;
delete objectName[index];
delete property; // legal only within a with statement

objectName是一个对象名,property 是一个已经存在的属性,index是数组中的一个已经存在的键值的索引值。

第三行的形式只在with声明的状态下是合法的,从对象中删除一个属性。

你能使用 delete 删除各种各样的隐式声明,但是被var声明的除外。

如果 delete 操作成功,属性或者元素会变成 undefined。如果 delete可行会返回true,如果不成功返回false

x = 42;
var y = 43;
myobj = new Number();
myobj.h = 4;    // create property h
delete x;       // returns true (can delete if declared implicitly)
delete y;       // returns false (cannot delete if declared with var)
delete Math.PI; // returns false (cannot delete predefined properties)
delete myobj.h; // returns true (can delete user-defined properties)
delete myobj;   // returns true (can delete if declared implicitly)

删除数组元素

删除数组中的元素时,数组的长度是不变的,例如删除 a[3]a[4]a[4] 和 a[3] 仍然存在变成了 undefined

delete 删除数组中的一个元素,这个元素就不在数组中了。例如,trees[3]被删除,trees[3] 仍然可寻址并返回 undefined

var trees = new Array("redwood", "bay", "cedar", "oak", "maple");
delete trees[3];
if (3 in trees) {
  // 不会被执行
}

如果想让数组中存在一个元素但是是undefined值,使用undefined关键字而不是delete操作。如下: trees[3] 分配一个 undefined,但是这个数组元素仍然存在:

var trees = new Array("redwood", "bay", "cedar", "oak", "maple");
trees[3] = undefined;
if (3 in trees) {
  // this gets executed(会被执行)
}
typeof

typeof 操作符 可通过下面 2 种方式使用:

typeof operand
typeof (operand)

typeof 操作符返回一个表示 operand 类型的字符串值。operand 可为字符串、变量、关键词或对象,其类型将被返回。operand 两侧的括号为可选。

假设你定义了如下的变量:

var myFun = new Function("5 + 2");
var shape = "round";
var size = 1;
var today = new Date();

typeof 操作符将会返回如下的结果:

typeof myFun;     // returns "function"
typeof shape;     // returns "string"
typeof size;      // returns "number"
typeof today;     // returns "object"
typeof dontExist; // returns "undefined"

对于关键词 true 和 null, typeof 操作符将会返回如下结果:

typeof true; // returns "boolean"
typeof null; // returns "object"

对于一个数值或字符串, typeof 操作符将会返回如下结果:

typeof 62;            // returns "number"
typeof 'Hello world'; // returns "string"

对于属性值,typeof 操作符将会返回属性所包含值的类型:

typeof document.lastModified; // returns "string"
typeof window.length;         // returns "number"
typeof Math.LN2;              // returns "number"

对于方法和函数,typeof 操作符将会返回如下结果:

typeof blur;        // returns "function"
typeof eval;        // returns "function"
typeof parseInt;    // returns "function"
typeof shape.split; // returns "function"

对于预定义的对象,typeof 操作符将会返回如下结果:

typeof Date;     // returns "function"
typeof Function; // returns "function"
typeof Math;     // returns "object"
typeof Option;   // returns "function"
typeof String;   // returns "function"
void

void 运算符运用方法如下:

void (expression)
void expression

void 运算符,表明一个运算没有返回值。expression 是 javaScript 表达式,括号中的表达式是一个可选项,当然使用该方式是一种好的形式。

你可以使用 void 运算符指明一个超文本链接。该表达式是有效的,但是并不会在当前文档中进行加载。

如下创建了一个超链接文本,当用户单击该文本时,不会有任何效果。

<a href="javascript:void(0)">Click here to do nothing</a>

下面的代码创建了一个超链接,当用户单击它时,提交一个表单。

<a href="javascript:void(document.form.submit())">
Click here to submit</a>
关系运算符

关系运算符对操作数进行比较,根据比较结果真或假,返回相应的布尔值。

in

in操作符,如果所指定的属性确实存在于所指定的对象中,则会返回true,语法如下:

propNameOrNumber in objectName

在这里 propNameOrNumber可以是一个代表着属性名的字符串或者是一个代表着数组索引的数值表达式,而objectName则是一个对象名。

下面的例子是 in 操作的常见用法。

// Arrays
var trees = new Array("redwood", "bay", "cedar", "oak", "maple");
0 in trees;        // returns true
3 in trees;        // returns true
6 in trees;        // returns false
"bay" in trees;    // returns false (you must specify the index number,
                   // not the value at that index)
"length" in trees; // returns true (length is an Array property)

// Predefined objects
"PI" in Math;          // returns true
var myString = new String("coral");
"length" in myString;  // returns true

// Custom objects
var mycar = {make: "Honda", model: "Accord", year: 1998};
"make" in mycar;  // returns true
"model" in mycar; // returns true
instanceof

如果所判别的对象确实是所指定的类型,则返回true。其语法如下:

objectName instanceof objectType

objectName 是需要做判别的对象的名称,而objectType是假定的对象的类型,例如Date或 Array.

当你需要确认一个对象在运行时的类型时,可使用instanceof. 例如,需要 catch 异常时,你可以针对抛出异常的类型,来做不同的异常处理。

例如,下面的代码使用instanceof去判断 theDay是否是一个 Date 对象。因为 theDay是一个Date对象,所以 if中的代码会执行。

var theDay = new Date(1995, 12, 17);
if (theDay instanceof Date) {
  // statements to execute
}
运算符优先级

运算符的优先级,用于确定一个表达式的计算顺序。在你不能确定优先级时,可以通过使用括号显式声明运算符的优先级。

下表列出了描述符的优先级,从最高到最低。

运算符优先级

Operator type Individual operators
member . []
call / create instance () new
negation/increment ! ~ - + ++ -- typeof void delete
multiply/divide * / %
addition/subtraction + -
bitwise shift << >> >>>
relational < <= > >= in instanceof
equality == != === !==
bitwise-and &
bitwise-xor ^
bitwise-or |
logical-and &&
logical-or ||
conditional ?:
assignment = += -= *= /= %= <<= >>= >>>= &= ^= |=
comma ,

上表有一个更详细的版本,它包含了各操作符更详细的说明,可在 JavaScript 参考手册中找到。

表达式

表达式是一组代码的集合,它返回一个值。(译注:定义比较不好理解,看下面的举例就很好懂了。)

每一个合法的表达式都能计算成某个值,但从概念上讲,有两种类型的表达式:有副作用的(比如赋值)和单纯计算求值的。

表达式 x=7 是第一类型的一个例子。该表达式使用=运算符将值 7 赋予变量 x。这个表达式自己的值等于 7。

代码 3 + 4 是第二个表达式类型的一个例子。该表达式使用 + 运算符把 3 和 4 加到一起但并没有把结果(7)赋值给一个变量。

JavaScript 有以下表达式类型:

  • 算数:得出一个数字,例如 3.14159。(通常使用算数运算符
  • 字符串:得出一个字符串,例如,"Fred" 或 "234"。(通常使用字符串运算符。)
  • 逻辑值:得出 true 或者 false。(经常涉及到逻辑运算符。)
  • 基本表达式:javascript 中基本的关键字和一般表达式。
  • 左值表达式:分配给左值。
基本表达式
this

this关键字被用于指代当前的对象,通常,this指代的是方法中正在被调用的对象。用法如下:

this["propertyName"]
this.propertyName

假设一个用于验证对象value属性的validate函数,传参有对象,最高值和最低值。

function validate(obj, lowval, hival){
  if ((obj.value < lowval) || (obj.value > hival))
    console.log("Invalid Value!");
}

你可以在任何表单元素的onchange事件处理中调用validat函数,用this来指代当前的表单元素,用例如下:

<p>Enter a number between 18 and 99:</p><input type="text" name="age" size=3 onChange="validate(this, 18, 99);">

分组操作符

分组操作符()控制了表达式中计算的优先级。举例来说,你可以改变先乘除后加减的顺序,转而先计算加法。

var a = 1;
var b = 2;
var c = 3;

// 默认优先级
a + b * c     // 7
// 默认是这样计算的
a + (b * c)   // 7

// 现在使加法优先于乘法
(a + b) * c   // 9

// 这等价于
a * c + b * c // 9
数值推导

Comprehensions 是一个带有实验性质的 JavaScript 特性,计划将在未来的 ECMAScript 版本中加入该特性。有两种类型的 comprehensions:

实验性 [for (x of y) x] (en-US)数列数值推导(非标准用法)实验性 (for (x of y) y) (en-US)生成器数值推导(译者注:生成器数值推导标准化可能不大,推荐使用 生成器函数 (en-US)

Comprehensions 特性被许多编程语言所采用,该特性能够使你快速地通过一个已有的数组来创建出一个新的数组,比如:

[for (i of [ 1, 2, 3 ]) i*i ];
// [ 1, 4, 9 ]

var abc = [ "A", "B", "C" ];
[for (letters of abc) letters.toLowerCase()];
// [ "a", "b", "c" ]
左值表达式

左值可以作为赋值的目标。

new

你可以使用new operator 创建一个自定义类型或者是预置类型的对象实例。用法如下:

var objectName = new objectType([param1, param2, ..., paramN]);

super

super 关键字可以用来调用一个对象父类的函数,它在用来调用一个的父类的构造函数时非常有用,比如:

super([arguments]); // calls the parent constructor. super.functionOnParent([arguments]);

扩展语句

扩展语句符允许一个表达式在原地展开,当需要多个参数 (比如函数调用时) 或者多个值 (比如字面量数组) 。

  • *例如:**现在你有一个数组,你想创建一个新数组,并将刚才那个作为它的一部分,用 array 的字面语法是不够的,你不得不写一些代码实现它,比如用些pushspliceconcat 等等。但是用spread syntax 就没问题了:
    var parts = ['shoulder', 'knees'];
    var lyrics = ['head', ...parts, 'and', 'toes'];

类似的,扩展语句也可以用在函数调用的时候:

function f(x, y, z) { }
var args = [0, 1, 2];
f(...args);

JavaScript 关键字

JavaScript 保留关键字

Javascript 的保留关键字不可以用作变量、标签或者函数名。有些保留关键字是作为 Javascript 以后扩展使用。

abstract arguments boolean break byte
case catch char class* const
continue debugger default delete do
double else enum* eval export*
extends* false final finally float
for function goto if implements
import* in instanceof int interface
let long native new null
package private protected public return
short static super* switch synchronized
this throw throws transient true
try typeof var void volatile
while with yield
  • 标记的关键字是 ECMAScript5 中新添加的。
1. goto keyword

用于将执行控制返回到一个特定的位置。一般来说,goto可以通过break和continue关键字来完成。

Example

var no=0;
sposition
document.write(" something print here ");
no++;
if(no < 10) goto sposition;

现在,我们用break和continue关键字重写同样的代码

var no=0;
sposition: while(true) {
	document.write(" something print here ");
	no++;
	if(no < 10) continue sposition;
		break;
}
2. in keyword

如果指定对象中存在指定属性,则它是一个返回true的运算符,否则它将返回false。

Example

var fruits={f1: "apple", f2: "banana", f3: "orange"};
// output as true expected
console.log('apple' in fruits);
3. instanceof keyword

如果对象是该类的实例,则返回true,否则返回false。

Example

var fruits=["apple", "banana", "orange"];
// Returns true
fruits instanceof Object;
// Returns true
fruits instanceof Array;
// Returns false
fruits instanceof String;
4. arguments keyword

表示调用函数时传递给函数的参数列表。

Example

const func = function(p1, p2, p3) {
	const param = Array.from(arguments);
	console.log(param) // [11, 22, 33]
}
func(11, 22, 33);
5. public C

它是一种访问修饰符,可用于属性、类、构造函数和方法,使它可以被其他类访问。

Example

public class Employee {
	public String efn = "Joseph";
	public String eln = "Doe";
}
class MainClass {
	public static void main(String[] args) {
	Employee obj = new Employee ();
	System.out.println("Name= " + obj.efn + " " + obj.lname);
	}
}
6. Do keyword

用于定义一个 do-while 循环。

Example

var a=1;
do {
	document.write("loop is running for " + a + "times</p>");
	a++;
} while(a <= 10);
7. Function keyword

用于定义一个函数来执行一段代码。

Example

var func = function(){
	return "Hello";
}
alert(func());
8. class* keyword

用来定义一个类

Example

public class Employee {
	public String efn = "Joseph";
	public String eln = "Doe";
}
9. return keyword

用于从函数或方法中返回一个值或不返回一个值。

Example

var func = function(){
	return "Hello";
}
10. Eval keyword

用来评估一个指定的字符串。评价作为一个全局函数eval()使用。

Example

function fun( ) {
	var str1=2;
	var str1=3;
	var res = eval(new String(str1 + str2));
	document.write(res);
}
fun();
11. For keyword

用来定义一个循环,for循环重复执行一个代码块,直到一个条件为真。

Example

for(var a=0; a<=10; a++) {
	document.write("The loop is running for " + a + " times");
}
12. if keyword

用于定义一个有条件的结构。如果该语句用于在条件为真时运行一个代码块。

Example

var date = new Date();
var day = date.getDay(); // Sunday  Saturday : 0  6
if(day==5) {
	alert("This is weekend!");
} else {
	alert("This is non-weekend!");
13. Break keyword

用于循环以中断或停止循环的执行。

Example

for(var a=0; a<=10; a++) {
	if(a == 5)
		break;
	document.write("The loop is running for " + a + " times");
}
14. debugger keyword

用于停止javascript代码的执行,并在定义时调用调试函数。Debugger关键字的字数与break相同。

Example

var prod = 10 * 10;
debugger;
document.getElementbyId("id").innerHTML = prod;
15. Yield keyword

用于暂停和恢复一个生成器函数。生成器函数与普通函数相同,但在返回数值时使用了yield关键字来代替return。

Example

function* iter( a ) {
	while (a < 4) {
		yield a++;
	}
}
const i = iter ( 1 );
console.log(i.next().value);  //return 1
console.log(i.next().value);  //return 2
console.log(i.next().value);  //return 3
16. Continue keyword

用于循环以continue跳过下一个循环。

Example

for(var a=0; a<=10; a++) {
	if(a == 5)
		continue;
	document.write("The loop is running for " + a + " times");
}
17. export* keyword

用于从模块中导出对象、函数或值,以便在导入语句的帮助下在另一个程序中使用。

Example

export let var fruits = ["apple", "banana", "orange"];// export an array
export const fruit= "apple";// export a constant
18. null keyword

用于表示特殊数据类型的无值。

Example

var age = null;
alert(age);
19. New keyword

用于创建对象。

Example

Employee obj = new Employee ();
20. throw keyword

在 try 块中使用以显式抛出异常对象。

Example

Var i=1
try {
	if(i == "") throw "is Empty";
	if(x > 0) throw "positive";
	if(x < 0) throw "negative";
}
catch(msg) {
	message.innerHTML = "Input " + msg;
}
21. while keyword

用于while循环,while循环执行代码块直到条件为真。

Example

var a=1;
while(a <= 10)
{
	document.write("loop is running for " + a + "times</p>");
	a++;
}
22. Delete keyword

用于从对象中删除属性。

Example

var fruits={f1: "apple", f2: "banana", f3: "orange"};
delete fruits.f1;
23. super* keyword

用于调用父类的函数或方法。

Example

super.disp(); //the disp is a method of a parent class
24. default keyword

在switch表达式中,用于指定在没有case的情况下要执行的动作。

Example

var date = new Date();
switch(date.getDay()) {
case 6:
	alert("This is weekend.");
	break;
case 0:
	alert("This is weekend.");
default:
	alert("Looking for a weekend.");
	break;
}
25. protected keyword

访问修饰符可以用于属性、类、构造函数和方法,使其不能被其他类访问。

Example

public class Employee {
	protected String efn = "Joseph";
}
26. Package keyword

用于识别java类和执行javascript中的java方法。

Example

inBlock['package'] = something;
27. Interface keyword

用于定义一个接口(接口包含所有抽象方法)。

Example

interface car
method drive(whichSpeed)
method break( )
class car1 implements car
{
	// Class code here
}
28. implements keyword

用于实现类中的接口。

Example

interface car
method drive(whichSpeed)
method break( )
class car1 implements car
29. With keyword

用于迭代,简而言之,它是迭代的简称。

Example

var  fruits = ["apple", "banana", "orange"];
for ( var i = fruits.length; i--; ) {
	with ({ no : i }) {
		link.onclick = function() {
			alert(no);
		};
	}
}
30. import* keyword

用于在javascript程序中导入模块。

Example

import * as alias from 'https://cdn.educba.com/modules/mymodule.js';
31. typeof keyword

用于返回操作数的数据类型。

Example

typeof("hello") // output as string
32. Var keyword

用于声明一个变量,

Example

var  fruits = ["apple", "banana", "orange"];
var age=22;
33. await* keyword

用来等待javascript,直到promise返回其结果。

Example

async function fun() {
	let promise = new Promise((resolve, reject) => { setTimeout(() => resolve(" yes, it is done!"), 100) });
	let res = await promise; // wait until the promise returns us a value
	alert(result); // output give yes, it is done
	}
};
fun();
34. enum* keyword

用于定义预定义列表。

Example

const fruits={
	APPLE: 'apple',
	BANANA: 'banana',
	Orange: 'orange',
}
let fruit =fruits.APPLE
if(!fruit){
	throw new Error(' fruit is not defined ')
}
switch( fruit ){
case fruit.APPLE: alert("This is an apple.");
	break;
case fruit.BANANA: alert("This is a banana.");
	break;
case fruit.ORANGE: alert("This is an orange.");
}
35. try keyword

用于异常处理,检查一个代码块的错误。

Example

Var i=1
try {
	if(i == "") throw "is Empty";
	if(x > 0) throw "positive";
	if(x < 0) throw "negative";
}
catch(msg) {
	message.innerHTML = "Input " + msg;
}
36. Catch keyword

再次用于异常处理以处理错误。

Example

Var i=1
try {
	if(i == "") throw "is Empty";
	if(x > 0) throw "positive";
	if(x < 0) throw "negative";
}
catch(msg) {
	message.innerHTML = " Input " + msg;
}
37. finally keyword

在异常处理中使用,finally 代码块总是执行,不管错误是否产生。

Example

Var i=1
try {
	if(i == "") throw "is Empty";
	if(x > 0) throw "positive";
	if(x < 0) throw "negative";
}
catch(msg) {
	message.innerHTML = "Input " + msg;
}
finally
{
alert("This is a finally code, which always execute.");
38. Const keyword

用于定义一个常量变量,并且不能被更多地重新赋值。

Example

const age=22;
39. private keyword

IS访问修饰符可以用于属性、类、构造函数和方法,使其不能被其他类访问。

Example

public class Employee {
	private String efn = "Joseph";
}
class MainClass {
	public static void main(String[] args) {
		Employee obj = new Employee ();
		
System.out.println("Name= " + obj.efn + " " + obj.lname);// gives error
	}
}
40. True keyword

用于存储或表示原始数据类型布尔'true'。

Example

var inp = true;
41. False keyword

用于存储或表示原始数据类型布尔值'false'。

Example

var inp = false;
42. Void keyword

用来评估一个表达式,并返回未定义的值。空白操作符经常被用来获取未定义的原始值。

Example

<a href = "javascript:void(0);">
	click link
</a>
43. Case keyword

在switch-case结构中使用,表达式的值与case子句的值进行比较,并执行与case值匹配的case相关的语句。

Example

var date = new Date();
switch(date.getDay()) {
case 6:
	alert("This is weekend.");
	break;
case 0:
	alert("This is weekend.");
default:
	alert("Looking for a weekend.");
	break;
}
44. switch keyword

在switch-case结构中使用,其中switch评估一个表达式。

Example

var date = new Date();
switch(date.getDay()) {
case 6:
	alert("This is weekend.");
	break;
case 0:
	alert("This is weekend.");
default:
	alert("Looking for a weekend.");
	break;
}
45. extends* keyword

在类的声明中使用,用于创建一个继承另一个类的类。

Example

class Employee extends Person {
	constructor(name, eid, salary) {
		super(name);
	}
	get incsalary() {
		return this.salary * 0.2;
	}
}
46. This keyword

用于引用当前对象。

Example

class Employee extends Person {
	constructor(name, eid, salary) {
		super(name);
	}
	get incsalary() {
		return this.salary * 0.2;
	}
}
47. let* keyword

用于声明限制在一个代码块范围内的变量,与var关键字声明的变量不同。

Example

let var fruits = ["apple", "banana", "orange"];
48. else keyword

在if-else语句中使用,else表示在表达式评估为false时要执行的语句块。

Example

var date = new Date();
var day = date.getDay(); // Sunday - Saturday : 0 - 6
if(day==5) {
	alert("This is weekend!");
} else {
	alert("This is non-weekend!");
49. Static keyword

用于在一个类中定义静态方法。静态方法是那些不在对象上调用的方法。

Example

class Employee extends Person {
	constructor(name, eid, salary) {
		super(name);
	}
	static disp()
	{
		return "This is static method "
	}
}
document.writeln( Employee.disp()  );


JavaScript 对象、属性和方法

您也应该避免使用 JavaScript 内置的对象、属性和方法的名称作为 Javascript 的变量或函数名:

Array Date eval function hasOwnProperty
Infinity isFinite isNaN isPrototypeOf length
Math NaN name Number Object
prototype String toString undefined valueOf

Java 保留关键字

JavaScript 经常与 Java 一起使用。您应该避免使用一些 Java 对象和属性作为 JavaScript 标识符:

getClass java JavaArray javaClass JavaObject JavaPackage

Windows 保留关键字

JavaScript 可以在 HTML 外部使用。它可在许多其他应用程序中作为编程语言使用。

在 HTML 中,您必须(为了可移植性,您也应该这么做)避免使用 HTML 和 Windows 对象和属性的名称作为 Javascript 的变量及函数名:

alert all anchor anchors area
assign blur button checkbox clearInterval
clearTimeout clientInformation close closed confirm
constructor crypto decodeURI decodeURIComponent defaultStatus
document element elements embed embeds
encodeURI encodeURIComponent escape event fileUpload
focus form forms frame innerHeight
innerWidth layer layers link location
mimeTypes navigate navigator frames frameRate
hidden history image images offscreenBuffering
open opener option outerHeight outerWidth
packages pageXOffset pageYOffset parent parseFloat
parseInt password pkcs11 plugin prompt
propertyIsEnum radio reset screenX screenY
scroll secure select self setInterval
setTimeout status submit taint text
textarea top unescape untaint window

HTML 事件句柄

除此之外,您还应该避免使用 HTML 事件句柄的名称作为 Javascript 的变量及函数名。

实例:

onblur onclick onerror onfocus
onkeydown onkeypress onkeyup onmouseover
onload onmouseup onmousedown onsubmit