ES6 快速指南



ES6 - 概述

ECMAScript (ES) 是一种由ECMAScript国际标准化组织标准化的脚本语言规范。应用程序使用它来启用客户端脚本。该规范受到Self、Perl、Python、Java等编程语言的影响。JavaScript、Jscript和ActionScript等语言都遵循此规范。

本教程将介绍JavaScript中ES6的实现。

JavaScript

JavaScript由Netscape Communications Corporation的开发者Brendan Eich于1995年开发。JavaScript最初名为Mocha,在正式更名为JavaScript之前简称为LiveScript。它是一种由浏览器执行的脚本语言,即在客户端执行。它与HTML结合使用,以开发响应式网页。

此处讨论的ECMAScript 6的实现涵盖了以下新特性:

  • 支持常量
  • 块级作用域
  • 箭头函数
  • 扩展的参数处理
  • 模板字面量
  • 扩展的字面量
  • 增强的对象属性
  • 解构赋值
  • 模块
  • 迭代器
  • 生成器
  • 集合
  • 各种类的新的内置方法
  • Promise

ECMAScript 版本

ECMA-262共有九个版本,如下所示:

版本 名称 描述
1 ECMAScript 1 1997年发布的第一个版本
2 ECMAScript 2 1998年发布的第二个版本,为满足ISO/IEC 16262标准而进行的少量更改
3 ECMAScript 3 1999年发布的第三版,包含语言增强功能
4 ECMAScript 4 第四版发布计划被取消,一些特性后来添加到ES6中,其他复杂的特性被放弃
5 ECMAScript 5 2009年发布的第五版
5.1 ECMAScript 5.1 2011年发布的5.1版,为满足ISO/IEC 16262:2011标准而进行的少量更改
6 ECMAScript 2015/ES6 2015年发布的第六版,请参阅ES6章节了解新特性
7 ECMAScript 2016/ES7 2016年发布的第七版,请参阅ES7章节了解新特性
8 ECMAScript 2017/ES8 2017年发布的第八版,请参阅ES8章节了解新特性
9 ECMAScript 2018/ES9 2018年发布的第九版,请参阅ES9章节了解新特性

ES6 - 环境搭建

在本章中,我们将讨论ES6环境的设置。

本地环境搭建

JavaScript可以在任何浏览器、任何主机和任何操作系统上运行。您将需要以下内容来编写和测试标准的JavaScript程序:

文本编辑器

文本编辑器帮助您编写源代码。一些编辑器的示例包括Windows记事本、Notepad++、Emacs、vim或vi等。使用的编辑器可能因操作系统而异。源文件通常以.js为扩展名命名。

安装Node.js

Node.js是一个开源的、跨平台的服务器端JavaScript运行环境。Node.js是运行JavaScript而无需浏览器支持的必要条件。它使用Google V8 JavaScript引擎来执行代码。您可以下载Node.js源代码或适合您平台的预构建安装程序。Node可在https://node.org.cn/en/download下载

在Windows上安装

下载并运行Node的.msi安装程序

MSI Installer

要验证安装是否成功,请在终端窗口中输入命令node –v

Node -v

在Mac OS X上安装

要在OS X上安装node.js,您可以下载预编译的二进制包,这使得安装非常简单。访问www.nodejs.org并点击安装按钮下载最新包。

Latest Package

按照安装向导安装.dmg中的包,这将同时安装nodenpm。npm是Node包管理器,它方便安装Node.js的附加包。

Install Node

在Linux上安装

在安装Node.js和npm之前,您需要安装许多依赖项

  • RubyGCC。您需要Ruby 1.8.6或更高版本和GCC 4.2或更高版本

  • Homebrew。Homebrew最初是Mac的包管理器,但已被移植到Linux作为Linuxbrew。您可以在https://brew.sh.cn/https://brew.sh.cn/linuxbrew了解有关Homebrew的更多信息。

集成开发环境 (IDE) 支持

JavaScript可以在许多开发环境中构建,例如Visual Studio、Sublime Text 2、WebStorm/PHPStorm、Eclipse、Brackets等。本节将讨论Visual Studio Code和Brackets IDE。此处使用的开发环境是Visual Studio Code(Windows平台)。

Visual Studio Code

这是Visual Studio的开源IDE。它适用于Mac OS X、Linux和Windows平台。VScode可在https://vscode.js.cn获取。

在Windows上安装

下载适用于Windows的Visual Studio Code。

Visual Studio Code for Windows

双击VSCodeSetup.exe VSCodeSetup启动安装过程。这只需要一分钟。

Setup Wizard

以下是IDE的屏幕截图。

Screenshot of IDE

您可以通过右键单击文件→在命令提示符中打开直接转到文件的路径。同样,“在资源管理器中显示”选项会在文件资源管理器中显示该文件。

Reveal in Explorer

在Mac OS X上安装

Visual Studio Code的Mac OS X特定安装指南可在https://vscode.js.cn/docs/setup/setup-overview找到

在Linux上安装

Visual Studio Code的Linux特定安装指南可在https://vscode.js.cn/Docs/editor/setup.找到

Brackets

Brackets是由Adobe Systems创建的免费开源Web开发编辑器。它适用于Linux、Windows和Mac OS X。Brackets可在http://brackets.io获取。

Brackets

您可以通过添加另一个扩展Brackets Shell在Brackets本身中运行DOS提示符/Shell。

Prompt Shell

安装后,您将在编辑器的右侧找到一个shell图标Editor Icon。单击该图标后,您将看到如下所示的shell窗口。

Shell

一切准备就绪!!!

ES6 - 语法

语法定义了编写程序的一组规则。每种语言规范都定义了自己的语法。

JavaScript程序可以由以下部分组成:

  • 变量 - 代表一个命名的内存块,可以存储程序的值。

  • 字面量 - 代表常量/固定值。

  • 运算符 - 定义如何处理操作数的符号。

  • 关键字 - 在语言上下文中具有特殊含义的词。

下表列出了一些JavaScript关键字。下表列出了一些常用的关键字。

break as any switch
case if throw else
var number string get
module type instanceof typeof
finally for enum export
while void this new
null super catch let
static return true false
  • 模块 - 代表可以在不同程序/脚本中重用的代码块。

  • 注释 - 用于提高代码的可读性。这些会被JavaScript引擎忽略。

  • 标识符 - 这些是赋予程序中元素(如变量、函数等)的名称。标识符的规则如下:

    • 标识符可以包含字符和数字。但是,标识符不能以数字开头。

    • 标识符不能包含特殊符号,除了下划线 (_) 或美元符号 ($)。

    • 标识符不能是关键字。它们必须是唯一的。

    • 标识符区分大小写。标识符不能包含空格。

下表说明了一些有效和无效的标识符。

有效标识符示例 无效标识符示例

firstName

first_name

num1

$result

Var#

first name

first-name

1number

空格和换行符

ES6忽略程序中出现的空格、制表符和换行符。您可以在程序中随意使用空格、制表符和换行符,并且可以自由地以整洁一致的方式格式化和缩进程序,使代码易于阅读和理解。

JavaScript区分大小写

JavaScript区分大小写。这意味着JavaScript区分大写和小写字符。

分号是可选的

每一行指令称为语句。在JavaScript中,分号是可选的。

示例

console.log("hello world") 
console.log("We are learning ES6") 

单行可以包含多个语句。但是,这些语句必须用分号隔开。

JavaScript中的注释

注释是提高程序可读性的一种方法。注释可用于包含有关程序的附加信息,例如代码的作者、关于函数/构造的提示等。编译器会忽略注释。

JavaScript支持以下类型的注释:

  • 单行注释 (//) - // 和行尾之间的任何文本都被视为注释。

  • 多行注释 (/* */) - 这些注释可以跨越多行。

示例

//this is single line comment  
/* This is a  
Multi-line comment 
*/

你的第一个JavaScript代码

让我们从传统的“Hello World”示例开始。

var message = "Hello World" 
console.log(message)

程序可以分析如下:

  • 第1行声明一个名为message的变量。变量是程序中存储值的机制。

  • 第 2 行将变量的值打印到提示符中。此处,控制台指的是终端窗口。log() 函数用于在屏幕上显示文本。

代码执行

我们将使用 Node.js 来执行我们的代码。

  • 步骤 1 − 将文件保存为 Test.js

  • 步骤 2 − 在 Visual Studio Code 的项目资源管理器窗口中的工作文件选项下,右键单击 Test.js 文件。

  • 步骤 3 − 选择“在命令提示符中打开”选项。

  • 步骤 4 − 在 Node 的终端窗口中键入以下命令。

node Test.js 

文件成功执行后,将显示以下输出。

Hello World

Node.js 和 JS/ES6

ECMAScript 2015 (ES6) 功能分为三组:

  • 已发布 − 这些是 V8 认为稳定的功能。

  • 已分阶段的功能 − 这些功能几乎已完成,但 V8 团队认为不稳定。

  • 正在进行中 − 这些功能仅应用于测试目的。

第一类功能完全受支持,并且默认情况下已启用。分阶段的功能需要运行时 --harmony 标志才能执行。

Node.js 的组件特定 CLI 标志列表可在此处找到:https://node.org.cn/api/cli.html

严格模式

ECMAScript 规范的第五版引入了严格模式。严格模式对 JavaScript 施加了一层约束。它对正常的 JavaScript 语义进行了一些更改。

可以通过包含以下内容来转换代码以在严格模式下工作:

// Whole-script strict mode syntax 
"use strict"; 
 v = "Hi!  I'm a strict mode script!";  // ERROR: Variable v is not declared

在上例代码片段中,整个代码作为一个受约束的 JavaScript 变体运行。

JavaScript 还允许限制函数作用域内的严格模式。如下所示:

v = 15 
function f1() { 
   "use strict"; 
   var v = "Hi!  I'm a strict mode script!"; 
}

在上例代码片段中,函数外部的任何代码都将在非严格模式下运行。函数内的所有语句都将在严格模式下执行。

ES6 和提升

JavaScript 引擎默认情况下会将声明移动到顶部。此功能称为提升。此功能适用于变量和函数。提升允许 JavaScript 在声明组件之前使用它。但是,提升的概念不适用于在严格模式下运行的脚本。

后续章节将解释变量提升和函数提升。

ES6 - 变量

根据定义,变量是“内存中命名的空间”,用于存储值。换句话说,它充当程序中值的容器。变量名称称为标识符。以下是标识符的命名规则:

  • 标识符不能是关键字。

  • 标识符可以包含字母和数字。

  • 标识符不能包含空格和特殊字符,下划线 (_) 和美元符号 ($) 除外。

  • 变量名不能以数字开头。

类型语法

必须在使用变量之前声明它。ES5 语法使用var关键字来实现相同的功能。声明变量的 ES5 语法如下所示。

//Declaration using var keyword 
var  variable_name

ES6 引入了以下变量声明语法:

  • 使用 let。
  • 使用 const。

变量初始化是指将值存储在变量中的过程。变量可以在声明时或稍后初始化。

声明和初始化变量的传统 ES5 类型语法如下所示:

//Declaration using var keyword 
var variable_name = value

示例:使用变量

var name = "Tom" 
console.log("The value in the variable is: "+name)

上面的示例声明了一个变量并打印其值。

成功执行后,将显示以下输出。

The value in the variable is Tom

JavaScript 和动态类型

JavaScript 是一种无类型语言。这意味着 JavaScript 变量可以保存任何数据类型的值。与许多其他语言不同,您不必在变量声明期间告诉 JavaScript 变量将保存何种类型的值。变量的值类型可以在程序执行期间更改,JavaScript 会自动处理它。此功能称为动态类型

JavaScript 变量作用域

变量的作用域是定义它的程序区域。传统上,JavaScript 只定义了两种作用域:全局作用域和局部作用域。

  • 全局作用域− 全局作用域的变量可以从 JavaScript 代码的任何部分访问。

  • 局部作用域− 局部作用域的变量可以从声明它的函数中访问。

示例:全局变量与局部变量

以下示例声明了两个名为num的变量——一个在函数外部(全局作用域),另一个在函数内部(局部作用域)。

var num = 10 
function test() { 
   var num = 100 
   console.log("value of num in test() "+num) 
} 
console.log("value of num outside test() "+num) 
test()

在函数内引用变量时,将显示局部作用域变量的值。但是,在函数外部访问变量num时,将返回全局作用域实例。

成功执行后,将显示以下输出。

value of num outside test() 10
value of num in test() 100

ES6 定义了一个新的变量作用域:块作用域。

Let 和块作用域

块作用域将变量的访问权限限制为声明它的块。var关键字为变量分配函数作用域。与 var 关键字不同,let关键字允许脚本将对变量的访问权限限制为最近的封闭块。

"use strict" 
function test() { 
   var num = 100 
   console.log("value of num in test() "+num) { 
      console.log("Inner Block begins") 
      let num = 200 
      console.log("value of num : "+num)  
   } 
} 
test()

脚本在函数的局部作用域内声明了一个变量num,并使用 let 关键字在块内重新声明它。当在内部块外部访问变量时,将打印局部作用域变量的值,而内部块内将引用块作用域变量。

注意 − 严格模式是一种选择加入 JavaScript 受限变体的方法。

成功执行后,将显示以下输出。

value of num in test() 100 
Inner Block begins 
value of num : 200

示例:let 与 var

var no = 10; 
var no = 20; 
console.log(no);

执行上述代码后,将显示以下输出。

20

让我们使用let关键字重写相同的代码。

let no = 10; 
let no = 20; 
console.log(no);

上面的代码将抛出一个错误:标识符“no”已被声明。任何使用 let 关键字声明的变量都被分配了块作用域。

let 和块级安全性

如果我们尝试在同一个块中两次声明一个let变量,它将抛出一个错误。考虑以下示例:

<script>
   let balance = 5000 // number type
   console.log(typeof balance)
   let balance = {message:"hello"} // changing number to object type
   console.log(typeof balance)
</script>

上面的代码将导致以下错误:

Uncaught SyntaxError: Identifier 'balance' has already been declared

let 和多个块

但是,可以在不同的块级作用域中使用相同的let变量,而不会出现任何语法错误。

示例

<script>
   let count = 100
   for (let count = 1;count <= 10;count++){
      //inside for loop brackets ,count value starts from 1
      console.log("count value inside loop is ",count);
   }
   //outside for loop brackets ,count value is 100
   console.log("count value after loop is",count);

   if(count == 100){
      //inside if brackets ,count value is 50
      let count = 50;
      console.log("count inside if block",count);
   }
   console.log(count);
</script>

上述代码的输出如下:

count value inside loop is 1
count value inside loop is 2
count value inside loop is 3
count value inside loop is 4
count value inside loop is 5
count value inside loop is 6
count value inside loop is 7
count value inside loop is 8
count value inside loop is 9
count value inside loop is 10
count value after loop is 100
count inside if block 50
100

const

const声明创建对值的只读引用。这并不意味着它保存的值是不可变的,只是变量标识符不能重新赋值。常量具有块作用域,就像使用 let 语句定义的变量一样。常量的值不能通过重新赋值来更改,并且不能重新声明。

使用const关键字声明的变量,以下规则适用:

  • 常量不能重新赋值。
  • 常量不能重新声明。
  • 常量需要初始化器。这意味着常量必须在其声明期间初始化。
  • 分配给const变量的值是可变的。

示例

const x = 10
x = 12 // will result in an error!!

上面的代码将返回一个错误,因为常量不能重新赋值。常量变量是不可变的。

常量是不可变的

与使用let关键字声明的变量不同,常量是不可变的。这意味着它的值不能更改。例如,如果我们尝试更改常量变量的值,将显示错误。

<script>
   let income = 100000
   const INTEREST_RATE = 0.08
   income += 50000 // mutable
   console.log("changed income value is ",income)
   INTEREST_RATE += 0.01
   console.log("changed rate is ",INTEREST_RATE) //Error: not mutable
</script>

上述代码的输出如下:

changed income value is 150000
Uncaught TypeError: Assignment to constant variable

const 和数组

以下示例显示如何创建不可变数组。可以向数组中添加新元素。但是,重新初始化数组将导致错误,如下所示:

<script>
   const DEPT_NOS = [10,20,30,50]
   DEPT_NOS.push(40)
   console.log('dept numbers is ',DEPT_NOS)

   const EMP_IDS = [1001,1002,1003]
   console.log('employee ids',EMP_IDS)
   //re assigning variable employee ids
   EMP_IDS = [2001,2002,2003]
   console.log('employee ids after changing',EMP_IDS)
</script>

上述代码的输出将如下所示:

dept numbers is (5) [10, 20, 30, 50, 40]
employee ids (3) [1001, 1002, 1003]
Uncaught TypeError: Assignment to constant variable.

var 关键字

在 ES6 之前,var关键字用于在 JavaScript 中声明变量。使用var声明的变量不支持块级作用域。这意味着如果在循环或if 块中声明了一个变量,则可以在循环或if 块外部访问它。这是因为使用var关键字声明的变量支持提升。

var 和提升

变量提升允许在 JavaScript 程序中使用变量,即使在声明它之前也是如此。此类变量默认情况下将初始化为undefined。JavaScript 运行时将扫描变量声明并将它们放在函数或脚本的顶部。使用var关键字声明的变量将提升到顶部。考虑以下示例:

<script>
   variable company is hoisted to top , var company = undefined
   console.log(company); // using variable before declaring
   var company = "TutorialsPoint"; // declare and initialized here
   console.log(company);
</script>

上述代码的输出将如下所示:

undefined
TutorialsPoint

var 和块作用域

块作用域将变量的访问权限限制为声明它的块。var关键字为变量分配函数作用域。使用var关键字声明的变量没有块作用域。考虑以下示例:

<script>
   //hoisted to top ; var i = undefined
   for (var i = 1;i <= 5;i++){
      console.log(i);
   }
   console.log("after the loop i value is "+i);
</script>

上述代码的输出如下:

1
2
3
4
5
after the loop i value is 6

变量i使用var关键字在 for 循环内声明。变量 i 在循环外部是可访问的。但是,有时可能需要限制块内变量的访问权限。在这种情况下,我们不能使用var关键字。ES6 引入了let关键字来克服此限制。

var 和块级安全性

如果我们在块内使用var 关键字两次声明相同的变量,编译器不会抛出错误。但是,这可能会导致运行时出现意外的逻辑错误。

<script>
   var balance = 5000
   console.log(typeof balance)
   var balance = {message:"hello"}
   console.log(typeof balance)
</script>

上述代码的输出如下所示:

number
object

ES6 - 运算符

表达式是一种特殊类型的语句,它计算出一个值。每个表达式都由以下部分组成:

  • 操作数 − 表示数据。

  • 运算符 − 定义如何处理操作数以生成值。

考虑以下表达式:2 + 3。在此表达式中,2 和 3 是操作数,符号 +(加号)是运算符。JavaScript 支持以下类型的运算符:

  • 算术运算符
  • 逻辑运算符
  • 关系运算符
  • 按位运算符
  • 赋值运算符
  • 三元/条件运算符
  • 字符串运算符
  • 类型运算符
  • void 运算符

算术运算符

假设变量ab中的值分别为 10 和 5。

显示示例

运算符 功能 示例
+ 加法

返回操作数的总和。

a + b 为 15
- 减法

返回值的差。

a-b 为 5
* 乘法

返回值。

a*b 为 50
/ 除法

执行除法运算并返回商。

a/b 为 2
% 模数

执行除法并返回余数。

a%b 为 0
++ 递增

将变量的值递增 1。

a++ 为 11
-- 递减

将变量的值递减 1。

a-- 为 9

关系运算符

关系运算符测试或定义两个实体之间关系的类型。关系运算符返回布尔值,即 true/false。

假设 A 的值为 10,B 的值为 20。

显示示例

运算符 描述 示例
> 大于 (A > B) 为 False
< 小于 (A < B) 为 True
>= 大于或等于 (A >= B) 为 False
<= 小于或等于 (A <= B) 为 True
== 相等 (A == B) 为 False
!= 不等于 (A!= B) 为真

逻辑运算符

逻辑运算符用于组合两个或多个条件。逻辑运算符也返回布尔值。假设变量 A 的值为 10,B 的值为 20。

显示示例.

运算符 描述 示例
&& 与(And)

只有当所有指定的表达式都返回真时,运算符才返回真。

(A > 10 && B > 10) 为假
|| 或(Or)

如果至少一个指定的表达式返回真,则运算符返回真。

(A > 10 || B > 10) 为真
! 非(Not)

该运算符返回表达式的结果的反值。例如:!(7>5) 返回假。

!(A > 10) 为真

位运算符

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

显示示例.

运算符 用法 描述
按位与(Bitwise AND) a & b 对于两个操作数的相应位都为 1 的每一位位置,返回 1
按位或(Bitwise OR) a | b 对于两个操作数中任何一个或两个操作数的相应位为 1 的每一位位置,返回 1
按位异或(Bitwise XOR) a^b 对于两个操作数中只有一个操作数的相应位为 1 的每一位位置,返回 1
按位非(Bitwise NOT) ~ a 反转其操作数的位
左移(Left shift) a << b 将 a 的二进制表示向左移动 b (< 32) 位,从右边移入零
算术右移(Sign-propagating right shift) a >> b 将 a 的二进制表示向右移动 b (< 32) 位,丢弃移出的位
逻辑右移(Zero-fill right shift) a >>> b 将 a 的二进制表示向右移动 b (< 32) 位,丢弃移出的位,并从左边移入零

赋值运算符

下表总结了赋值运算符。

显示示例.

序号 运算符和描述
1

= (简单赋值)

将右侧操作数的值赋给左侧操作数。

示例 − C = A + B 将 A + B 的值赋给 C

2

+= (加法赋值)

它将右侧操作数添加到左侧操作数,并将结果赋给左侧操作数。

示例 − C += A 等效于 C = C + A

3

-= (减法赋值)

它从左侧操作数中减去右侧操作数,并将结果赋给左侧操作数。

示例 C -= A 等效于 C = C - A

4

*= (乘法赋值)

它将右侧操作数乘以左侧操作数,并将结果赋给左侧操作数。

示例 C *= A 等效于 C = C * A

5

/= (除法赋值)

它将左侧操作数除以右侧操作数,并将结果赋给左侧操作数。

注意 − 位运算符也适用相同的逻辑,因此它们将变为 <<=、>>=、>>>=、&=、|= 和 ^=。

其他运算符

以下是一些其他运算符。

负号运算符 (-)

更改值的符号。以下程序是相同的示例。

var x = 4 
var y = -x; 
console.log("value of x: ",x); //outputs 4 
console.log("value of y: ",y); //outputs -4

上述程序成功执行后将显示以下输出。

value of x: 4 
value of y: -4 

字符串运算符:连接运算符 (+)

当 + 运算符应用于字符串时,它会将第二个字符串附加到第一个字符串。以下程序有助于理解这个概念。

var msg = "hello"+"world" 
console.log(msg) 

上述程序成功执行后将显示以下输出。

helloworld

连接操作不会在字符串之间添加空格。可以在单个语句中连接多个字符串。

条件运算符 (?)

此运算符用于表示条件表达式。条件运算符有时也称为三元运算符。以下是语法。

Test ? expr1 : expr2

其中,

Test − 指的是条件表达式

expr1 − 如果条件为真则返回的值

expr2 − 如果条件为假则返回的值

示例

var num = -2 
var result = num > 0 ?"positive":"non-positive" 
console.log(result)

第 2 行检查变量 num 中的值是否大于零。如果 num 设置为大于零的值,则返回字符串“positive”,否则返回“non-positive”字符串。

上述程序成功执行后将显示以下输出。

non-positive 

typeof 运算符

这是一个一元运算符。此运算符返回操作数的数据类型。下表列出了 JavaScript 中 typeof 运算符返回的数据类型和值。

类型 typeof 返回的字符串
数字 "number"
字符串 "string"
布尔值 "boolean"
对象 "object"

以下示例代码显示数字作为输出。

var num = 12 
console.log(typeof num); //output: number

执行上述代码后,将显示以下输出。

number

扩展运算符

ES6 提供了一个名为扩展运算符的新运算符。扩展运算符由三个点“...”表示。扩展运算符将数组转换为单个数组元素。

扩展运算符和函数

以下示例说明了在函数中使用扩展运算符。

<script>
   function addThreeNumbers(a,b,c){
      return a+b+c;
   }
   const arr = [10,20,30]
   console.log('sum is :',addThreeNumbers(...arr))
   console.log('sum is ',addThreeNumbers(...[1,2,3]))
</script>

上述代码的输出将如下所示:

sum is : 60
sum is 6

扩展运算符和数组复制与连接

扩展运算符可用于将一个数组复制到另一个数组。它还可用于连接两个或多个数组。这在下面的示例中显示:

示例

<script>
   //copy array using spread operator
   let source_arr = [10,20,30]
   let dest_arr = [...source_arr]
   console.log(dest_arr)
	
   //concatenate two arrays
   let arr1 = [10,20,30]
   let arr2 =[40,50,60]
   let arr3 = [...arr1,...arr2]
   console.log(arr3)
</script>

上述代码的输出将如下所示:

[10, 20, 30]
[10, 20, 30, 40, 50, 60]

扩展运算符和对象复制与连接

扩展运算符可用于将一个对象复制到另一个对象。它还可用于连接两个或多个对象。这在下面的示例中显示:

<script>
   //copy object
   let student1 ={firstName:'Mohtashim',company:'TutorialsPoint'}
   let student2 ={...student1}
   console.log(student2)
   //concatenate objects
   let student3 = {lastName:'Mohammad'}
   let student4 = {...student1,...student3}
   console.log(student4)
</script>

上述代码的输出将如下所示:

{firstName: "Mohtashim", company: "TutorialsPoint"}
{firstName: "Mohtashim", company: "TutorialsPoint", lastName: "Mohammad"}

ES6 - 决策语句

条件/决策结构在执行指令之前评估条件。

Decision Making

JavaScript 中的条件结构在下表中进行了分类。

序号 语句和描述
1 if 语句

“if”语句由一个布尔表达式后跟一个或多个语句组成。

2 if…else 语句

“if”语句后面可以跟一个可选的“else”语句,当布尔表达式为假时执行此语句。

3 else..if 阶梯/嵌套 if 语句

else…if 阶梯用于测试多个条件。以下是相同的语法。

4 switch…case 语句

switch 语句评估表达式,将表达式的值与 case 子句匹配,并执行与该 case 关联的语句。

ES6 - 循环语句

有时,某些指令需要重复执行。循环是执行此操作的理想方法。循环表示必须重复的一组指令。在循环的上下文中,重复称为迭代

下图说明了循环的分类:

Loops

确定性循环

迭代次数确定/固定的循环称为确定性循环。“for 循环”是确定性循环的一种实现。

for (initial_count_value; termination-condition; step) { 
   //statements
}   

序号 确定性循环和描述
1 “for”循环

for 循环在指定次数内执行代码块。

2 for…in 循环

for...in 循环用于循环遍历对象的属性。

3 for…of 循环

for…of 循环用于迭代可迭代对象而不是对象字面量。

不确定性循环

当循环中的迭代次数是不确定或未知时,使用不确定性循环。

可以使用以下方法实现不确定性循环:

序号 不确定性循环和描述
1 while 循环

while 循环每次指定的条件计算结果为真时执行指令。

2 do…while 循环

do…while 循环类似于 while 循环,只是 do...while 循环在第一次执行循环时不评估条件。

循环控制语句

序号 循环控制语句和描述
1 break 语句

break 语句用于将控制权从结构中移出。

2 continue 语句

continue 语句跳过当前迭代中的后续语句,并将控制权带回循环的开头。

使用标签控制流程

标签只是一个后跟冒号 (:) 的标识符,应用于语句或代码块。标签可以与breakcontinue 一起使用以更精确地控制流程。

‘continue’‘break’ 语句与其标签名称之间不允许换行。此外,标签名称和关联循环之间也不应有任何其他语句。

序号 标签和描述
1 带 break 的标签

标签可以与 break 和 continue 一起使用以更精确地控制流程。

2 带 continue 的标签

‘continue’ 或 ‘break’ 语句与其标签名称之间不允许换行。

ES6 - 函数

函数是可读、可维护和可重用代码的构建块。函数使用 function 关键字定义。以下是定义标准函数的语法。

function function_name() { 
   // function body 
} 

要强制执行函数,必须调用它。这称为函数调用。以下是调用函数的语法。

function_name()

示例:简单的函数定义

//define a  function 
function test() { 
   console.log("function called") 
} 
//call the function 
test()

此示例定义了一个函数 test()。一对定界符 ({ }) 定义函数体。它也称为函数作用域。必须调用函数才能强制其执行。

执行上述代码后,将显示以下输出。

function called

函数分类

函数可以分为返回值函数和参数化函数。

返回值函数

函数还可以将值与控制一起返回给调用方。此类函数称为返回值函数。

以下是返回值函数的语法。

function function_name() { 
   //statements 
   return value; 
}
  • 返回值函数必须以 return 语句结尾。

  • 函数最多可以返回一个值。换句话说,每个函数只能有一个 return 语句。

  • return 语句应该是函数中的最后一个语句。

以下代码片段是返回值函数的示例:

function retStr() { 
   return "hello world!!!" 
}  
var val = retStr() 
console.log(val) 

上述示例定义了一个函数,该函数将字符串“hello world!!!”返回给调用方。上述代码成功执行后将显示以下输出。

hello world!!! 

参数化函数

参数是一种向函数传递值的方式。参数构成函数签名的一部分。在调用函数期间,参数值将传递给函数。除非明确指定,否则传递给函数的值的数量必须与定义的参数数量匹配。

以下是定义参数化函数的语法。

function func_name( param1,param2 ,…..paramN) {   
   ...... 
   ...... 
}

示例 - 参数化函数

此示例定义了一个名为 add 的函数,它接受两个参数 **n1** 和 **n2**,并打印它们的和。在调用函数时,参数值将传递给函数。

function add( n1,n2) { 
   var sum = n1 + n2 
   console.log("The sum of the values entered "+sum) 
} 
add(12,13) 

执行上述代码后,将显示以下输出。

The sum of the values entered 25

默认函数参数

在 ES6 中,如果函数未传递任何值或值为 undefined,则允许参数初始化为默认值。以下代码对此进行了说明。

function add(a, b = 1) { 
   return a+b; 
} 
console.log(add(4))

上面的函数将 b 的值默认设置为 1。除非显式传递值,否则函数将始终认为参数 b 的值为 1。成功执行上述代码后将显示以下输出。

5

如果函数显式传递值,则参数的默认值将被覆盖。

function add(a, b = 1) { 
   return a + b; 
} 
console.log(add(4,2))

上面的代码将参数 b 的值显式设置为 2,从而覆盖其默认值。成功执行上述代码后将显示以下输出。

6

为了更好地理解,让我们考虑以下示例。

示例 1

以下示例显示了一个接受两个参数并返回其和的函数。第二个参数的默认值为 10。这意味着,如果未向第二个参数传递任何值,则其值为 10。

<script>
   function addTwoNumbers(first,second = 10){
      console.log('first parameter is :',first)
      console.log('second parameter is :',second)
      return first+second;
   }

   console.log("case 1 sum:",addTwoNumbers(20)) // no value
   console.log("case 2 sum:",addTwoNumbers(2,3))
   console.log("case 3 sum:",addTwoNumbers())
   console.log("case 4 sum",addTwoNumbers(1,null))//null passed
   console.log("case 5 sum",addTwoNumbers(3,undefined))
</script>

上述代码的输出如下所示:

first parameter is : 20
second parameter is : 10
case 1 sum: 30
first parameter is : 2
second parameter is : 3
case 2 sum: 5
first parameter is : undefined
second parameter is : 10
case 3 sum: NaN
first parameter is : 1
second parameter is : null
case 4 sum 1
first parameter is : 3
second parameter is : 10
case 5 sum 13

示例 2

<script>
   let DEFAULT_VAL = 30
      function addTwoNumbers(first,second = DEFAULT_VAL){
         console.log('first parameter is :',first)
         console.log('second parameter is :',second)
         return first+second;
      }
      console.log("case 1 sum",addTwoNumbers(1))
      console.log("case 2 sum",addTwoNumbers(3,undefined))
</script>

上述代码的输出将如下所示:

first parameter is : 1
second parameter is : 30
case 1 sum 31
first parameter is : 3
second parameter is : 30
case 2 sum 33

剩余参数

剩余参数类似于 Java 中的可变参数。剩余参数不会限制您可以传递给函数的值的数量。但是,传递的值必须全部为相同类型。换句话说,剩余参数充当相同类型多个参数的占位符。

要声明剩余参数,参数名前缀为三个点,称为扩展运算符。以下示例说明了这一点。

function fun1(...params) { 
   console.log(params.length); 
}  
fun1();  
fun1(5); 
fun1(5, 6, 7); 

执行上述代码后,将显示以下输出。

0 
1 
3

**注意** - 剩余参数应位于函数参数列表的最后。

匿名函数

未绑定到标识符(函数名)的函数称为匿名函数。这些函数在运行时动态声明。匿名函数可以接受输入并返回输出,就像标准函数一样。匿名函数在其初始创建后通常不可访问。

变量可以赋值为匿名函数。这样的表达式称为 **函数表达式**。

以下是匿名函数的语法。

var res = function( [arguments] ) { ... } 

示例 - 匿名函数

var f = function(){ return "hello"} 
console.log(f()) 

执行上述代码后,将显示以下输出。

hello 

示例 - 匿名参数化函数

var func = function(x,y){ return x*y }; 
function product() { 
   var result; 
   result = func(10,20); 
   console.log("The product : "+result) 
} 
product()

执行上述代码后,将显示以下输出。

The product : 200 

Function 构造函数

函数语句不是定义新函数的唯一方法;您可以使用 Function() 构造函数和 new 运算符动态定义函数。

以下是使用 Function() 构造函数和 new 运算符创建函数的语法。

var variablename = new Function(Arg1, Arg2..., "Function Body"); 

Function() 构造函数接受任意数量的字符串参数。最后一个参数是函数的主体——它可以包含任意 JavaScript 语句,这些语句之间用分号隔开。

Function() 构造函数不会传递任何指定其创建的函数名称的参数。

示例 - Function 构造函数

var func = new Function("x", "y", "return x*y;"); 
function product() { 
   var result; 
   result = func(10,20); 
   console.log("The product : "+result)
} 
product()

在上面的示例中,Function() 构造函数用于定义匿名函数。该函数接受两个参数并返回它们的乘积。

执行上述代码后,将显示以下输出。

The product : 200

递归和 JavaScript 函数

递归是一种通过让函数反复调用自身直到得到结果来迭代操作的技术。当需要在循环中使用不同的参数反复调用同一个函数时,递归最适用。

示例 - 递归

function factorial(num) { 
   if(num <= 0) { 
      return 1; 
   } else { 
      return (num * factorial(num-1)  ) 
   } 
} 
console.log(factorial(6)) 

在上面的示例中,函数调用自身。成功执行上述代码后将显示以下输出。

720 

示例 - 匿名递归函数

(function() { 
   var msg = "Hello World" 
   console.log(msg)
})()

该函数使用一对括号 () 调用自身。成功执行上述代码后将显示以下输出。

Hello World 

Lambda 函数

Lambda 指的是编程中的匿名函数。Lambda 函数是一种表示匿名函数的简洁机制。这些函数也称为 **箭头函数**。

Lambda 函数 - 结构

Lambda 函数有三个部分:

  • **参数** - 函数可以选择具有参数。

  • **胖箭头符号/lambda 符号** (=>):它也称为“转到”运算符。

  • **语句** - 表示函数的指令集。

**提示** - 按惯例,鼓励使用单个字母参数来进行紧凑而精确的函数声明。

Lambda 表达式

这是一个指向单行代码的匿名函数表达式。以下是相同的语法。

([param1, parma2,…param n] )=>statement;

示例 - Lambda 表达式

var foo = (x)=>10+x 
console.log(foo(10)) 

此示例声明了一个 lambda 表达式函数。该函数返回 10 和传递的参数的和。

执行上述代码后,将显示以下输出。

20

Lambda 语句

这是一个指向代码块的匿名函数声明。当函数体跨越多行时,使用此语法。以下是相同的语法。

( [param1, parma2,…param n] )=> {       
   //code block 
}

示例 - Lambda 语句

var msg = ()=> { 
   console.log("function invoked") 
} 
msg() 

函数的引用被返回并存储在变量 msg 中。成功执行上述代码后将显示以下输出。

function  invoked 

语法变体

单个参数的可选括号。

var msg = x=> { 
   console.log(x) 
} 
msg(10)

单个语句的可选大括号。无参数的空括号。

var disp = ()=>console.log("Hello World") 
disp();

函数表达式和函数声明

函数表达式和函数声明并非同义词。与函数表达式不同,函数声明受函数名称约束。

两者之间的根本区别在于,函数声明在其执行之前被解析。另一方面,函数表达式仅在脚本引擎在执行期间遇到它时才被解析。

当 JavaScript 解析器在主代码流中看到一个函数时,它会假设函数声明。当函数作为语句的一部分出现时,它就是一个函数表达式。

函数提升

像变量一样,函数也可以提升。与变量不同,函数声明在提升时会提升函数定义,而不仅仅是提升函数名称。

以下代码片段说明了 JavaScript 中的函数提升。

hoist_function();  
function hoist_function() { 
   console.log("foo"); 
} 

执行上述代码后,将显示以下输出。

foo 

但是,函数表达式不能提升。以下代码片段说明了这一点。

hoist_function(); // TypeError: hoist_function() is not a function  
var hoist_function() = function() { 
   console.log("bar"); 
};

立即调用函数表达式

立即调用函数表达式 (IIFE) 可用于避免块内的变量提升。它允许公开访问方法,同时保留函数内定义的变量的私有性。这种模式称为自执行匿名函数。以下两个示例更好地解释了这个概念。

示例 1:IIFE

var main = function() { 
   var loop = function() { 
      for(var x = 0;x<5;x++) {
         console.log(x); 
      } 
   }(); 
   console.log("x can not be accessed outside the block scope x value is :"+x); 
} 
main();

示例 2:IIFE

var main = function() { 
   (function() { 
      for(var x = 0;x<5;x++) { 
         console.log(x); 
      } 
   })(); 
   console.log("x can not be accessed outside the block scope x value is :"+x); 
} 
main();

这两个示例都将呈现以下输出。

0 
1 
2 
3 
4 
Uncaught ReferenceError: x is not define

生成器函数

调用普通函数时,控制权将保留在被调用函数中,直到它返回。使用 ES6 中的生成器,调用函数现在可以控制被调用函数的执行。生成器类似于普通函数,不同之处在于:

  • 函数可以在任何时候将控制权返回给调用者。

  • 调用生成器时,它不会立即运行。相反,您将获得一个迭代器。当您调用迭代器的 next 方法时,函数将运行。

生成器用在函数关键字后添加星号来表示;否则,它们的语法与普通函数相同。

以下示例说明了这一点。

"use strict" 
function* rainbow() { 
   // the asterisk marks this as a generator 
   yield 'red'; 
   yield 'orange'; 
   yield 'yellow'; 
   yield 'green'; 
   yield 'blue'; 
   yield 'indigo'; 
   yield 'violet'; 
} 
for(let color of rainbow()) { 
   console.log(color); 
} 

生成器允许调用者和被调用函数之间进行双向通信。这是通过使用 **yield** 关键字实现的。

考虑以下示例:

function* ask() { 
   const name = yield "What is your name?"; 
   const sport = yield "What is your favorite sport?"; 
   return `${name}'s favorite sport is ${sport}`; 
}  
const it = ask(); 
console.log(it.next()); 
console.log(it.next('Ethan'));  
console.log(it.next('Cricket')); 

生成器函数的顺序如下:

  • 生成器以暂停状态启动;返回迭代器。

  • it.next() 产生“What is your name”。生成器暂停。这是由 yield 关键字完成的。

  • 调用 it.next(“Ethan”) 将值 Ethan 分配给变量 name 并产生“What is your favorite sport?”。生成器再次暂停。

  • 调用 it.next(“Cricket”) 将值 Cricket 分配给变量 sport 并执行随后的 return 语句。

因此,上述代码的输出将是:

{ 
   value: 'What is your name?', done: false 
} 
{ 
   value: 'What is your favorite sport?', done: false 
} 
{ 
   value: 'Ethan\'s favorite sport is Cricket', done: true 
}

**注意** - 生成器函数不能使用箭头函数表示。

箭头函数

ES 中引入的箭头函数有助于以简洁的方式编写 JavaScript 函数。现在让我们详细了解一下。

ES5 和匿名函数

JavaScript 大量使用 **匿名函数**。匿名函数是没有附加名称的函数。匿名函数用于 **函数回调**。以下示例说明了在 ES5 中使用匿名函数:

<script>
   setTimeout(function(){
      console.log('Learning at TutorialsPoint is fun!!')
   },1000)
</script>

上面的示例将匿名函数作为参数传递给预定义的 **setTimeout() 函数**。setTimeout() 函数将在 1 秒后回调匿名函数。

1 秒后显示以下输出:

Learning at TutorialsPoint is fun!!

箭头函数语法

ES6 引入了 **箭头函数** 的概念,以简化 **匿名函数** 的使用。箭头函数有三个部分,如下所示:

  • **参数** - 箭头函数可以选择具有参数

  • **胖箭头符号 (=>)** - 它也称为“转到”运算符

  • **语句** - 表示函数的指令集

**提示** - 按惯例,鼓励使用单个字母参数来进行紧凑而精确的箭头函数声明。

语法

//Arrow function that points to a single line of code
()=>some_expression

//Arrow function that points to a block of code
()=> { //some statements }`

//Arrow function with parameters
(param1,param2)=>{//some statement}

示例:ES6 中的箭头函数

以下示例使用箭头函数定义了两个函数表达式 **add** 和 **isEven**

<script>
   const add = (n1,n2) => n1+n2
   console.log(add(10,20))

   const isEven = (n1) => {
      if(n1%2 == 0)
         return true;
      else
         return false;
   }
   console.log(isEven(10))
</script>

上述代码的输出如下所示:

30
true

Array.prototype.map() 和箭头函数

在以下示例中,箭头函数作为参数传递给 **Array.prototype.map() 函数。** map() 函数对数组中的每个元素执行箭头函数。在这种情况下,箭头函数显示数组中的每个元素及其索引。

<script>
   const names = ['TutorialsPoint','Mohtashim','Bhargavi','Raja']
   names.map((element,index)=> {
      console.log('inside arrow function')
      console.log('index is '+index+' element value is :'+element)
   })
</script>

上述代码的输出将如下所示:

inside arrow function
index is 0 element value is :TutorialsPoint
inside arrow function
index is 1 element value is :Mohtashim
inside arrow function
index is 2 element value is :Bhargavi
inside arrow function
index is 3 element value is :Raja

示例:window.setTimeout() 和箭头函数

以下示例将箭头函数作为参数传递给预定义的 **setTimeout() 函数**。**setTimeout()** 函数将在 1 秒后回调箭头函数。

<script>
   setTimeout(()=>{
      console.log('Learning at TutorialsPoint is fun!!')
   },1000)
</script>

1 秒后显示以下输出:

Learning at TutorialsPoint is fun!!

箭头函数和“this”

在箭头函数内部,如果我们使用 **this 指针**,它将指向封闭的词法作用域。这意味着箭头函数不会在每次调用时创建一个新的 **this 指针** 实例。箭头函数使用其封闭作用域。为了理解这一点,让我们来看一个例子。

<script>
   //constructor function
   function Student(rollno,firstName,lastName) {
      this.rollno = rollno;
      this.firstName = firstName;
      this.lastName = lastName;
      this.fullNameUsingAnonymous = function(){
         setTimeout(function(){
            //creates a new instance of this ,hides outer scope of this
            console.log(this.firstName+ " "+this.lastName)
         },2000)
      }
      this.fullNameUsingArrow = function(){
         setTimeout(()=>{
            //uses this instance of outer scope
            console.log(this.firstName+ " "+this.lastName)
         },3000)
      }
   }
   const s1 = new Student(101,'Mohammad','Mohtashim')
   s1.fullNameUsingAnonymous();
   s1.fullNameUsingArrow();
</script>

当匿名函数与 **setTimeout()** 一起使用时,函数将在 2000 毫秒后被调用。将创建一个新的 **“this”** 实例,它会隐藏 Student 函数的实例。因此,**this.firstName** 和 **this.lastName** 的值将为 **undefined**。该函数不使用词法作用域或当前执行的上下文。这个问题可以使用 **箭头函数** 来解决。

上述代码的输出如下:

undefined undefined
Mohammad Mohtashim

ES6 - 事件

JavaScript 旨在为您的页面添加交互性。JavaScript 使用事件机制来实现这一点。**事件** 是文档对象模型 (DOM) 级别 3 的一部分,每个 HTML 元素都包含一组可以触发 JavaScript 代码的事件。

事件是由软件识别的动作或事件。它可以由用户或系统触发。一些常见的事件示例包括用户单击按钮、加载网页、单击超链接等等。以下是一些常见的 HTML 事件。

事件处理程序

事件发生时,应用程序会执行一组相关的任务。实现此目的的代码块称为**事件处理程序 (eventhandler)**。每个HTML元素都有一组与其关联的事件。我们可以使用事件处理程序在JavaScript中定义如何处理这些事件。

onclick 事件类型

这是最常用的事件类型,它在用户点击鼠标左键时发生。您可以针对此事件类型添加验证、警告等。

示例

<html> 
   <head> 
      <script type = "text/javascript">  
         function sayHello() {  
            document.write ("Hello World")  
         }   
      </script> 
   </head> 
   
   <body> 
      <p> Click the following button and see result</p> 
      <input type = "button" onclick = "sayHello()" value = "Say Hello" /> 
   </body> 
</html> 

执行上述代码后,将显示以下输出。

Onclick Event Type

onsubmit 事件类型

**onsubmit** 事件在您尝试提交表单时发生。您可以针对此事件类型添加表单验证。

以下示例显示如何使用**onsubmit**。这里我们在将表单数据提交到Web服务器之前调用 validate() 函数。如果 validate() 函数返回 true,则提交表单;否则,不提交数据。

示例

<html> 
   <head> 
      <script type = "text/javascript">  
         function validation() {  
            all validation goes here  
            .........  
            return either true or false  
         }   
      </script> 
   </head> 
   
   <body> 
      <form method = "POST" action = "t.cgi" onsubmit = "return validate()"> 
         .......  
         <input type = "submit" value = "Submit" /> 
      </form> 
   </body> 
</html>

onmouseover 和 onmouseout

这两个事件类型将帮助您为图像甚至文本创建不错的效果。当您将鼠标移到任何元素上时,**onmouseover** 事件触发;当您将鼠标从该元素移开时,**onmouseout** 事件触发。

示例

<html> 
   <head> 
      <script type = "text/javascript"> 
         function over() {  
            document.write ("Mouse Over");  
         }  
         function out() {  
            document.write ("Mouse Out");  
         }  
      </script> 
   </head> 

   <body> 
      <p>Bring your mouse inside the division to see the result:</p> 
      <div onmouseover = "over()" onmouseout = "out()"> 
         <h2> This is inside the division </h2> 
      </div> 
   </body> 
</html>

执行上述代码后,将显示以下输出。

Onmouseover Onmouseout

HTML 5 标准事件

下表列出了标准HTML 5 事件,供您参考。脚本指示针对该事件执行的JavaScript函数。

属性 描述
offline 脚本 文档离线时触发
onabort 脚本 在中止事件时触发
onafterprint 脚本 文档打印后触发
onbeforeonload 脚本 文档加载前触发
onbeforeprint 脚本 文档打印前触发
onblur 脚本 窗口失去焦点时触发
oncanplay 脚本 媒体可以开始播放时触发,但可能需要停止缓冲
oncanplaythrough 脚本 媒体可以播放到结尾时触发,无需停止缓冲
onchange 脚本 元素更改时触发
onclick 脚本 鼠标点击时触发
oncontextmenu 脚本 触发上下文菜单时触发
ondblclick 脚本 鼠标双击时触发
ondrag 脚本 拖动元素时触发
ondragend 脚本 拖动操作结束时触发
ondragenter 脚本 将元素拖动到有效的放置目标时触发
ondragleave 脚本 元素离开有效的放置目标时触发
ondragover 脚本 将元素拖动到有效的放置目标上方时触发
ondragstart 脚本 拖动操作开始时触发
ondrop 脚本 拖动元素被放下时触发
ondurationchange 脚本 媒体长度更改时触发
onemptied 脚本 媒体资源元素突然变空时触发
onended 脚本 媒体播放结束时触发
onerror 脚本 发生错误时触发
onfocus 脚本 窗口获得焦点时触发
onformchange 脚本 表单更改时触发
onforminput 脚本 表单获得用户输入时触发
onhaschange 脚本 文档已更改时触发
oninput 脚本 元素获得用户输入时触发
oninvalid 脚本 元素无效时触发
onkeydown 脚本 按下键时触发
onkeypress 脚本 按下并释放键时触发
onkeyup 脚本 释放键时触发
onload 脚本 文档加载时触发
onloadeddata 脚本 媒体数据加载时触发
onloadedmetadata 脚本 媒体元素的持续时间和其他媒体数据加载时触发
onloadstart 脚本 浏览器开始加载媒体数据时触发
onmessage 脚本 触发消息时触发
onmousedown 脚本 按下鼠标按钮时触发
onmousemove 脚本 鼠标指针移动时触发
onmouseout 脚本 鼠标指针移出元素时触发
onmouseover 脚本 鼠标指针移到元素上时触发
onmouseup 脚本 释放鼠标按钮时触发
onmousewheel 脚本 旋转鼠标滚轮时触发
onoffline 脚本 文档离线时触发
ononline 脚本 文档上线时触发
onpagehide 脚本 窗口隐藏时触发
onpageshow 脚本 窗口变为可见时触发
onpause 脚本 媒体数据暂停时触发
onplay 脚本 媒体数据即将开始播放时触发
onplaying 脚本 媒体数据已开始播放时触发
onpopstate 脚本 窗口的历史记录更改时触发
onprogress 脚本 浏览器正在获取媒体数据时触发
onratechange 脚本 媒体数据的播放速率更改时触发
onreadystatechange 脚本 就绪状态更改时触发
onredo 脚本 文档执行重做操作时触发
onresize 脚本 窗口大小调整时触发
onscroll 脚本 滚动元素的滚动条时触发
onseeked 脚本 媒体元素的 seeking 属性不再为 true,并且搜索已结束时触发
onseeking 脚本 媒体元素的 seeking 属性为 true,并且搜索已开始时触发
onselect 脚本 选择元素时触发
onstalled 脚本 获取媒体数据时发生错误时触发
onstorage 脚本 文档加载时触发
onsubmit 脚本 提交表单时触发
onsuspend 脚本 浏览器一直在获取媒体数据,但在获取整个媒体文件之前停止时触发
ontimeupdate 脚本 媒体更改其播放位置时触发
onundo 脚本 文档执行撤消操作时触发
onunload 脚本 用户离开文档时触发
onvolumechange 脚本 媒体更改音量时触发,将音量设置为“静音”时也会触发
onwaiting 脚本 媒体已停止播放,但预计会恢复播放时触发

ES6 - Cookie

Web浏览器和服务器使用HTTP协议进行通信。HTTP是无状态协议,即它不维护客户端在客户端发出的多个请求中的数据。客户端和服务器之间完整的请求-响应周期定义为**会话 (session)**。Cookie是浏览器用于存储与用户会话相关的数据的默认机制。

它是如何工作的?

您的服务器以Cookie的形式向访问者的浏览器发送一些数据。浏览器可能会接受Cookie。如果接受,它将作为纯文本记录存储在访问者的硬盘驱动器上。现在,当访问者访问您网站上的另一个页面时,浏览器会将相同的Cookie发送到服务器以进行检索。检索后,您的服务器就会知道/记住之前存储的内容。

Cookie是5个可变长度字段的纯文本数据记录。

  • **Expires** - Cookie将过期的日期。如果为空,则Cookie将在访问者退出浏览器时过期。

  • **Domain** - 您网站的域名。

  • **Path** - 设置Cookie的目录或网页的路径。如果要从任何目录或页面检索Cookie,则此路径可以为空。

  • **Secure** - 如果此字段包含单词“secure”,则只能使用安全服务器检索Cookie。如果此字段为空,则不存在此类限制。

  • **Name = Value** - Cookie以键值对的形式设置和检索。

Cookie最初是为CGI编程设计的。Cookie中包含的数据会在Web浏览器和Web服务器之间自动传输,因此服务器上的CGI脚本可以读取和写入存储在客户端的Cookie值。

JavaScript还可以使用Document对象的cookie属性操作Cookie。JavaScript可以读取、创建、修改和删除适用于当前网页的Cookie。

存储Cookie

创建Cookie的最简单方法是为**document.cookie**对象赋值一个字符串值,如下所示。

"document.cookie = "key1 = value1; key2 = value2; expires = date";

这里,“expires”属性是可选的。如果您为该属性提供有效的日期或时间,则Cookie将在给定的日期或时间过期,此后将无法访问Cookie的值。

**注意** - Cookie值可能不包含分号、逗号或空格。因此,您可能需要使用JavaScript的**escape()**函数在将值存储到Cookie之前对其进行编码。如果这样做,在读取Cookie值时,您还必须使用相应的**unescape()**函数。

示例

<html> 
   <head> 
      <script type = "text/javascript">  
         function WriteCookie() {  
            if( document.myform.customer.value == "" ){  
               alert ("Enter some value!");  
               return;  
            }  
            cookievalue =  escape(document.myform.customer.value) + ";";  
            document.cookie = "name = " + cookievalue;  
            document.write ("Setting Cookies : " + "name = " + cookievalue );  
         }  
      </script> 
   </head> 
      
   <body> 
      <form name = "myform" action = ""> 
         Enter name: <input type = "text" name = "customer"/> 
         <input type = "button" value = "Set" onclick = "WriteCookie();"/> 
      </form> 
   </body> 
</html>

执行上述代码后,将显示以下输出。

Cookies

现在您的计算机上有一个名为name的Cookie。您可以使用多个用逗号分隔的键=值对设置多个Cookie。

读取Cookie

读取Cookie与写入Cookie一样简单,因为**document.cookie**对象的值就是Cookie。因此,您可以随时使用此字符串访问Cookie。**document.cookie**字符串将保留用分号分隔的键=值对列表,其中键是Cookie的名称,值是其字符串值。

您可以使用字符串的**split()**函数将字符串分解为键和值,如下例所示。

示例

<html> 
   <head> 
      <script type = "text/javascript"> 
         function ReadCookie() {  
            var allcookies  =  document.cookie;  
            document.write ("All Cookies : " + allcookies ); 
         } 
         // Get all the cookies pairs in an array  
         cookiearray = allcookies.split(';');  
         
         // Now take key value pair out of this array  
         for(var i = 0; i<cookiearray.length; i++) {  
            name  =  cookiearray[i].split('=')[0];  
            value = cookiearray[i].split('=')[1];  
            document.write ("Key is : " + name + " and Value is : " + value); 
         }  
      </script> 
   </head> 

   <body> 
      <form name = "myform" action = ""> 
         <p> click the following button and see the result:</p> 
         <input type = "button" value = "Get Cookie" onclick = "ReadCookie()"/> 
      </form> 
   </body> 
</html> 

**注意** - 这里,length是Array类的⼀种⽅法,⽤于返回数组的长度。

您的计算机上可能已经设置了其他一些Cookie。以上代码将显示您计算机上设置的所有Cookie。

执行上述代码后,将显示以下输出。

Reading Cookies

设置Cookie过期日期

您可以通过设置过期日期并在Cookie中保存过期日期来延长Cookie的使用寿命,使其超过当前浏览器会话。这可以通过将“expires”属性设置为日期和时间来完成。以下示例说明如何将Cookie的过期日期延长1个月。

示例

<html> 
   <head> 
      <script type = "text/javascript"> 
         function WriteCookie() {  
            var now = new Date();  
            now.setMonth( now.getMonth() + 1 );  
            cookievalue = escape(document.myform.customer.value) + ";"  
            document.cookie = "name = " + cookievalue;  
            document.cookie = "expires = " + now.toUTCString() + ";"  
            document.write ("Setting Cookies : " + "name = " + cookievalue );  
         } 
      </script> 
   </head> 

   <body> 
      <form name = "formname" action = ""> 
         Enter Cookie Name: <input type = "text" name = "customer"/> 
         <input type = "button" value = "Set Cookie" onclick = "WriteCookie()"/> 
      </form> 
   </body> 
</html> 

执行上述代码后,将显示以下输出。

Cookies Expiry Date

删除Cookie

有时您可能想要删除Cookie,以便后续尝试读取Cookie时返回空值。为此,您只需要将过期日期设置为过去的时间即可。以下示例说明如何通过将Cookie的过期日期设置为当前日期前一个月来删除Cookie。

示例

<html> 
   <head> 
      <script type = "text/javascript"> 
         function WriteCookie() {  
            var now = new Date();  
            now.setMonth( now.getMonth() - 1 );  
            cookievalue = escape(document.myform.customer.value) + ";" 
            document.cookie = "name=" + cookievalue;  
            document.cookie = "expires = " + now.toUTCString() + ";"  
            document.write("Setting Cookies : " + "name = " + cookievalue );  
         }  
      </script> 
   </head> 

   <body> 
      <form name = "formname" action = ""> 
         Enter Cookie Name: <input type = "text" name = "customer"/> 
         <input type = "button" value = "Set Cookie" onclick = "WriteCookie()"/> 
      </form> 
   </body> 
</html>

执行上述代码后,将显示以下输出。

Deleting Cookie

ES6 - 页面跳转

**重定向 (Redirect)** 是一种将用户和搜索引擎发送到与他们最初请求的URL不同的URL的方法。页面重定向是一种自动将一个网页重定向到另一个网页的方法。重定向的页面通常位于同一网站上,也可以位于不同的网站或Web服务器上。

JavaScript页面重定向

window.location 和 window.location.href

在JavaScript中,您可以使用多种方法将一个网页重定向到另一个网页。几乎所有方法都与**window.location**对象相关,该对象是Window对象的属性。它可以用来获取当前的URL地址(网址)以及将浏览器重定向到新页面。就行为而言,这两种用法相同。**window.location**返回一个对象。如果未设置**.href**,则**window.location**默认为更改参数**.href**。

示例

<!DOCTYPE html> 
<html> 
   <head> 
      <script> 
         function newLocation() { 
            window.location = "http://www.xyz.com"; 
         } 
      </script> 
   </head> 

   <body> 
      <input type = "button" value = "Go to new location" onclick = "newLocation()"> 
   </body> 
</html>

location.replace()

另一个最常用的方法是 `window.location` 对象的 `replace()` 方法,它将用新文档替换当前文档。在 `replace()` 方法中,您可以传递一个新的 URL 到 `replace()` 方法,它将执行 HTTP 重定向。

以下是该方法的语法。

window.location.replace("http://www.abc.com

location.assign()

`location.assign()` 方法在浏览器窗口中加载一个新文档。

以下是该方法的语法。

window.location.assign("http://www.abc.org"); 

assign() 与 replace()

`assign()` 和 `replace()` 方法的区别在于,`location.replace()` 方法会删除文档历史记录中的当前 URL,因此无法返回到原始文档。在这种情况下,您无法使用浏览器的“后退”按钮。如果您想避免这种情况,应该使用 `location.assign()` 方法,因为它会在浏览器中加载一个新文档。

location.reload()

`location.reload()` 方法重新加载浏览器窗口中的当前文档。

以下是该方法的语法。

window.location.reload("http://www.yahoo.com");

window.navigate()

`window.navigate()` 方法类似于为 `window.location.href` 属性赋值。因为它只在 MS Internet Explorer 中可用,所以您应该避免在跨浏览器开发中使用它。

以下是该方法的语法。

window.navigate("http://www.abc.com"); 

重定向和搜索引擎优化

如果您想通知搜索引擎 (SEO) 您的 URL 转发,您应该将 `rel="canonical"` 元标记添加到您的网站头部,因为搜索引擎不会分析 JavaScript 来检查重定向。

以下是该方法的语法。

<link rel = "canonical" href = "http://abc.com/" />

ES6 - 对话框

JavaScript 支持三种重要的对话框类型。这些对话框可用于发出警报,或获取对任何输入的确认,或从用户那里获得某种输入。在这里,我们将逐一讨论每个对话框。

警告对话框

警告对话框主要用于向用户发送警告消息。例如,如果一个输入字段要求输入一些文本,但用户没有提供任何输入,那么作为验证的一部分,您可以使用警告框来发送警告消息。

尽管如此,警告框仍然可以用于更友好的消息。警告框只提供一个“确定”按钮供选择并继续。

示例

<html> 
   <head> 
      <script type = "text/javascript"> 
         function Warn() {  
            alert ("This is a warning message!");  
            document.write ("This is a warning message!");  
         } 
      </script> 
   </head> 

   <body> 
      <p>Click the following button to see the result: </p> 
      <form> 
         <input type = "button" value = "Click Me" onclick = "Warn();" /> 
      </form> 
   </body> 
</html> 

执行上述代码后,将显示以下输出。

alert dialogue box

确认对话框

确认对话框主要用于获取用户对任何选项的同意。它显示一个带有两个按钮的对话框:“确定”和“取消”。

如果用户单击“确定”按钮,则 `confirm()` 窗口方法将返回 `true`。如果用户单击“取消”按钮,则 `confirm()` 返回 `false`。您可以按如下方式使用确认对话框。

示例

<html> 
   <head> 
      <script type = "text/javascript"> 
         function getConfirmation(){  
            var retVal = confirm("Do you want to continue ?");  
            
            if( retVal == true ){  
               document.write ("User wants to continue!");  
               return true;  
            } else {  
               Document.write ("User does not want to continue!");  
               return false;  
            }  
         }  
      </script> 
   </head> 

   <body> 
      <p>Click the following button to see the result: </p> 
      <form> 
         <input type = "button" value = "Click Me" onclick = "getConfirmation();" /> 
      </form> 
   </body> 
</html> 

执行上述代码后,将显示以下输出。

confirmation dialogue box

提示对话框

当您想弹出一个文本框以获取用户输入时,提示对话框非常有用。因此,它使您能够与用户交互。用户需要填写字段,然后单击“确定”。

此对话框使用名为 `prompt()` 的方法显示,该方法接受两个参数:(i)您要在文本框中显示的标签;(ii)要在文本框中显示的默认字符串。

此对话框有两个按钮:“确定”和“取消”。如果用户单击“确定”按钮,则 `prompt()` 窗口方法将返回文本框中输入的值。如果用户单击“取消”按钮,则 `prompt()` 窗口方法将返回 `null`。

示例

<html> 
   <head> 
      <script type = "text/javascript"> 
         function getValue(){  
            var retVal = prompt("Enter your name : ", "your name here");  
            document.write("You have entered : " + retVal);  
         }  
      </script> 
   </head> 

   <body> 
      <p>Click the following button to see the result: </p> 
      <form> 
         <input type = "button" value = "Click Me" onclick = "getValue();" /> 
      </form> 
   </body> 
</html> 

执行上述代码后,将显示以下输出。

prompt dialogue box

ES6 - void 关键字

`void` 是 JavaScript 中一个重要的关键字,可以用作一元运算符,出现在其单个操作数之前,该操作数可以是任何类型。此运算符指定要计算的表达式,但不返回值。该运算符计算给定的表达式,然后返回 `undefined`。

以下是该方法的语法。

void expression

Void 和立即调用函数表达式

使用立即调用函数表达式时,`void` 可用于强制将 `function` 关键字视为表达式而不是声明。

考虑以下示例:

void function iife_void() { 
   var msg = function () {console.log("hello world")}; 
   msg(); 
}();

执行上述代码后,将显示以下输出。

hello world

Void 和 JavaScript URI

`JavaScript: URI` 是 HTML 页面中常见的语法。浏览器会计算 URI 并用返回的值替换页面的内容。除非返回的值是 `undefined`,否则情况属实。此运算符最常见的用途是在客户端 `JavaScript: URL` 中,它允许您计算表达式的副作用,而不会让浏览器显示计算表达式的值。

考虑以下代码片段:

<a href = "javascript:void(javascript:alert('hello world!!'))"> 
  Click here to do nothing 
</a> 
<br/><br/><br/> 
<a href = "javascript:alert('hello');">Click here for an alert</a>

将上述文件保存为 HTML 文档,并在浏览器中打开它。第一个超链接在单击时计算 `javascript:alert(“hello”)` 并将其传递给 `void()` 运算符。但是,由于 `void` 运算符返回 `undefined`,因此页面上不会显示任何结果。

另一方面,单击第二个超链接时会显示一个警告对话框。

ES6 - 页面打印

很多时候,您可能希望在网页上放置一个按钮,以便通过实际打印机打印该网页的内容。JavaScript 帮助您使用 `window` 对象的 `print` 函数实现此功能。

JavaScript `print` 函数 `window.print()` 在执行时会打印当前网页。您可以使用 `onclick` 事件直接调用此函数,如下例所示。

示例

<html> 
   <body> 
      <form> 
         <input type = "button" value = "Print" onclick = "window.print()"/> 
      </form> 
   </body> 
</html>

执行上述代码后,将显示以下输出。

page printing

ES6 - 对象

JavaScript 支持扩展数据类型。JavaScript 对象是定义自定义数据类型的好方法。

一个 `对象` 是一个实例,它包含一组键值对。与原始数据类型不同,对象可以表示多个或复杂的值,并且可以在其生命周期内发生变化。值可以是标量值、函数甚至是其他对象的数组。

将进一步讨论定义对象的语法变体。

对象初始化器

与原始类型一样,对象也有字面量语法:`花括号` ({和})。以下是定义对象的语法。

var identifier = {
   Key1:value, Key2: function () { 
      //functions 
   }, 
   Key3: [“content1”,” content2”] 
} 

对象的内容称为 `属性`(或成员),属性由 `名称`(或键)和 `` 组成。属性名必须是字符串或符号,值可以是任何类型(包括其他对象)。

与所有 JavaScript 变量一样,对象名(可以是普通变量)和属性名都区分大小写。您可以使用简单的点表示法访问对象的属性。

以下是访问对象属性的语法。

objectName.propertyName 

示例:对象初始化器

var person = { 
   firstname:"Tom", 
   lastname:"Hanks", 
   func:function(){return "Hello!!"},    
}; 
//access the object values 
console.log(person.firstname)   
console.log(person.lastname) 
console.log(person.func())

上述示例定义了一个对象 `person`。该对象具有三个属性。第三个属性是指向一个函数。

执行上述代码后,将显示以下输出。

Tom 
Hanks 
Hello!!

在 ES6 中,为与属性名称匹配的属性值赋值时,您可以省略属性值。

示例

var foo = 'bar' 
var baz = { foo } 
console.log(baz.foo)

上面的代码片段定义了一个对象 `baz`。该对象具有一个属性 `foo`。此处省略属性值,因为 ES6 会隐式地将变量 `foo` 的值分配给对象的键 `foo`。

以下是上述代码的 ES5 等效代码。

var foo = 'bar' 
var baz = { foo:foo } 
console.log(baz.foo)

执行上述代码后,将显示以下输出。

bar

使用此简写语法,JS 引擎会在包含作用域中查找具有相同名称的变量。如果找到,则将该变量的值赋给属性。如果找不到,则会抛出 `ReferenceError`。

`Object()` 构造函数

JavaScript 提供了一个名为 `Object()` 的特殊构造函数来构建对象。`new` 运算符用于创建对象的实例。要创建对象,`new` 运算符后跟构造方法。

以下是定义对象的语法。

var obj_name = new Object(); 
obj_name.property = value;    
OR             
obj_name["key"] = value 

以下是访问属性的语法。

Object_name.property_key                    
OR              
Object_name["property_key"]

示例

var myCar = new Object(); 
myCar.make = "Ford"; //define an object 
myCar.model = "Mustang"; 
myCar.year = 1987;  

console.log(myCar["make"]) //access the object property 
console.log(myCar["model"]) 
console.log(myCar["year"])

执行上述代码后,将显示以下输出。

Ford 
Mustang 
1987

对象的未赋值属性为 `undefined`。

示例

var myCar = new Object(); 
myCar.make = "Ford"; 
console.log(myCar["model"])

执行上述代码后,将显示以下输出。

undefined

注意 - 对象属性名可以是任何有效的 JavaScript 字符串,或者任何可以转换为字符串的内容,包括空字符串。但是,任何不是有效 JavaScript 标识符的属性名(例如,具有空格或连字符,或者以数字开头的属性名)只能使用方括号表示法访问。

也可以使用存储在变量中的字符串值来访问属性。换句话说,对象的属性键可以是动态值。例如:一个变量。以下示例说明了这一概念。

示例

var myCar = new Object()  
var propertyName = "make"; 
myCar[propertyName] = "Ford"; 
console.log(myCar.make)

执行上述代码后,将显示以下输出。

Ford

构造函数

可以使用以下两个步骤创建对象:

步骤 1 - 通过编写构造函数来定义对象类型。

以下是该方法的语法。

function function_name() { 
   this.property_name = value 
}

`this` 关键字引用当前正在使用的对象,并定义对象的属性。

步骤 2 - 使用 `new` 语法创建对象的实例。

var Object_name= new function_name() 
//Access the property value  

Object_name.property_name

`new` 关键字调用函数构造函数并初始化函数的属性键。

示例 - 使用函数构造函数

function Car() { 
   this.make = "Ford" 
   this.model = "F123" 
}  
var obj = new Car() 
console.log(obj.make) 
console.log(obj.model)

上述示例使用函数构造函数来定义对象。

执行上述代码后,将显示以下输出。

Ford 
F123 

总是可以向先前定义的对象添加新属性。例如,考虑以下代码片段:

function Car() { 
   this.make = "Ford" 
} 
var obj = new Car() 
obj.model = "F123" 
console.log(obj.make) 
console.log(obj.model)

执行上述代码后,将显示以下输出。

Ford 
F123

`Object.create` 方法

也可以使用 `Object.create()` 方法创建对象。它允许您创建所需对象的原型,而无需定义构造函数。

示例

var roles = { 
   type: "Admin", // Default value of properties 
   displayType : function() {  
      // Method which will display type of role 
      console.log(this.type); 
   } 
}  
// Create new role type called super_role 
var super_role = Object.create(roles); 
super_role.displayType(); // Output:Admin  

// Create new role type called Guest 
var guest_role = Object.create(roles); 
guest_role.type = "Guest"; 
guest_role.displayType(); // Output:Guest

上述示例定义了一个对象 `roles` 并为属性设置默认值。创建了两个新实例,它们覆盖了对象的默认属性值。

执行上述代码后,将显示以下输出。

Admin 
Guest

`Object.assign()` 函数

`Object.assign()` 方法用于将一个或多个源对象的全部可枚举自身属性的值复制到目标对象。它将返回目标对象。

以下是该方法的语法。

Object.assign(target, ...sources)    

示例 - 克隆对象

"use strict" 
var det = { name:"Tom", ID:"E1001" }; 
var copy = Object.assign({}, det); 
console.log(copy);  
for (let val in copy) { 
   console.log(copy[val]) 
}

执行上述代码后,将显示以下输出。

Tom 
E1001

示例 - 合并对象

var o1 = { a: 10 }; 
var o2 = { b: 20 }; 
var o3 = { c: 30 }; 
var obj = Object.assign(o1, o2, o3); 
console.log(obj);  
console.log(o1);

执行上述代码后,将显示以下输出。

{ a: 10, b: 20, c: 30 } 
{ a: 10, b: 20, c: 30 }

注意 - 与复制对象不同,当对象合并时,较大的对象不会维护属性的新副本。相反,它持有原始对象中包含的属性的引用。以下示例解释了这个概念。

var o1 = { a: 10 }; 
var obj = Object.assign(o1); 
obj.a++ 
console.log("Value of 'a' in the Merged object after increment  ") 
console.log(obj.a);  
console.log("value of 'a' in the Original Object after increment ") 
console.log(o1.a);

执行上述代码后,将显示以下输出。

Value of 'a' in the Merged object after increment 
11  
value of 'a' in the Original Object after increment 
11 

删除属性

您可以使用 `delete` 运算符删除属性。以下代码显示了如何删除属性。

示例

// Creates a new object, myobj, with two properties, a and b. 
var myobj = new Object; 
myobj.a = 5; 
myobj.b = 12; 

// Removes the ‘a’ property 
delete myobj.a; 
console.log ("a" in myobj) // yields "false"

执行上述代码后,将显示以下输出。

false

代码片段从对象中删除属性。该示例打印 `false`,因为 `in` 运算符在对象中找不到该属性。

比较对象

在 JavaScript 中,对象是引用类型。两个不同的对象永远不相等,即使它们具有相同的属性。这是因为它们指向完全不同的内存地址。只有那些共享公共引用的对象在比较时才会返回 `true`。

示例 1 - 不同的对象引用

var val1 = {name: "Tom"}; 
var val2 = {name: "Tom"}; 
console.log(val1 == val2)  // return false 
console.log(val1 === val2)  // return false

在上述示例中,`val1` 和 `val2` 是两个不同的对象,它们引用两个不同的内存地址。因此,在比较相等性时,运算符将返回 `false`。

示例 2 - 单个对象引用

var val1 = {name: "Tom"}; 
var val2 = val1  

console.log(val1 == val2) // return true 
console.log(val1 === val2) // return true

在上述示例中,`val1` 中的内容被赋给 `val2`,即 `val1` 中属性的引用与 `val2` 共享。由于对象现在共享对属性的引用,因此对于引用两个不同内存地址的两个不同的对象,相等运算符将返回 `true`。因此,在比较相等性时,运算符将返回 `false`。

对象解构

`解构` 一词指的是分解实体的结构。JavaScript 中的解构赋值语法可以将数据从数组或对象提取到不同的变量中。以下示例说明了这一点。

示例 1

解构对象时,变量名和对象属性名必须匹配。

<script>
let student = {
   rollno:20,
   name:'Prijin',
   cgpa:7.2
}

//destructuring to same property name
   let {name,cgpa} = student
   console.log(name)
   console.log(cgpa)

//destructuring to different name
   let {name:student_name,cgpa:student_cgpa}=student
   console.log(student_cgpa)
   console.log("student_name",student_name)
</script>

上述代码的输出将如下所示:

Prijin
7.2
7.2
student_name Prijin

示例 2

如果变量和赋值在两个不同的步骤中,则解构对象语法将被括号 `()` 包围,如示例 `({rollno} = student)` 所示:

<script>
   let student = {
      rollno:20,
      name:'Prijin',
      cgpa:7.2
   }

   // destructuring to already declared variable
   let rollno;
   ({rollno} = student)
   console.log(rollno)

   // assign default values to variables

   let product ={ id:1001,price:2000} //discount is not product property
   let {id,price,discount=.10} = product
   console.log(id)
   console.log(price)
   console.log(discount)
</script>

上述代码的输出如下所示:

20
1001
2000
0.1

示例 3

以下示例展示了使用 `rest` 运算符进行 `解构` 以及如何解构嵌套对象。

<script>
   // rest operator with object destructuring
   let customers= {
      c1:101,
      c2:102,
      c3:103
   }

   let {c1,...others} = customers
   console.log(c1)
   console.log(others)

   //nested objects
   let emp = {
      id:101,
      address:{
         city:'Mumbai',
         pin:1234
      }
   }
   let {address} = emp;

   console.log(address)
   let {address:{city,pin}} = emp
   console.log(city)
</script>

上述代码的输出如下所示:

101
{c2: 102, c3: 103}
{city: "Mumbai", pin: 1234}
Mumbai

ES6 - 数字

Number 对象表示数值日期,可以是整数或浮点数。通常,您不需要担心 Number 对象,因为浏览器会自动将数字字面量转换为 Number 类实例。

以下是创建数字对象的语法。

var val = new Number(number); 

number的位置,如果提供任何非数字参数,则该参数无法转换为number,它返回NaN(非数字)。

Number 属性

序号 属性 & 描述
1 Number.EPSILON

两个可表示数字之间的最小间隔。

2 Number.MAX_SAFE_INTEGER

JavaScript 中的最大安全整数 (2^53 - 1)。

3 Number.MAX_VALUE

最大的正可表示数。

4 MIN_SAFE_INTEGER

JavaScript 中的最小安全整数 (-(2^53 - 1))。

5 Number.MIN_VALUE

最小的正可表示数——也就是最接近零的正数(但并非零)

6 Number.NaN

特殊的“非数字”值

7 Number.NEGATIVE_INFINITY

表示负无穷大的特殊值;溢出时返回

8 Number.POSITIVE_INFINITY

表示无穷大的特殊值;溢出时返回

9 Number.prototype

表示无穷大的特殊值;溢出时返回

Number 方法

序号 方法 & 描述
1 Number.isNaN()

确定传递的值是否为 NaN。

2 Number.isFinite()

确定传递的值是否为有限数。

3 Number.isInteger()

确定传递的值是否为整数。

4 Number.isSafeInteger()

确定传递的值是否为安全整数(介于 -(253 - 1) 和 253 - 1 之间的数)

5 Number.parseFloat()

值与全局对象的 parseFloat() 相同

6 Number.parseInt()

值与全局对象的 parseInt() 相同

Number 实例方法

Number 对象只包含作为每个对象定义一部分的默认方法。

序号 实例方法 & 描述
1 toExponential()

返回一个以指数表示法表示数字的字符串

2 toFixed()

返回一个以定点表示法表示数字的字符串

3 toLocaleString()

返回一个包含此数字的语言敏感表示形式的字符串

4 toPrecision()

返回一个以定点或指数表示法表示指定精度的数字的字符串

5 toString()

返回以指定的基数(进制)表示指定对象的字符串。

6 valueOf()

返回指定对象的原始值。

二进制和八进制字面量

在 ES6 之前,关于整数的二进制或八进制表示的最佳方法是将它们与基数一起传递给 parseInt()。在 ES6 中,您可以使用 0b 和 0o 前缀分别表示二进制和八进制整数字面量。同样,要表示十六进制值,请使用0x前缀。

前缀可以是大写或小写。但是,建议坚持使用小写版本。

示例 - 二进制表示

console.log(0b001) 
console.log(0b010) 
console.log(0b011) 
console.log(0b100)

执行上述代码后,将显示以下输出。

1 
2 
3 
4

示例 - 八进制表示

console.log(0o010)
console.log(0o100)

执行上述代码后,将显示以下输出。

8
64

示例 - 十六进制表示

console.log(0x010)
console.log(0x100)

执行上述代码后,将显示以下输出。

255
384

对象字面量扩展

ES6 在对象字面量声明中引入了以下语法更改

  • 对象属性初始化程序语法
  • 计算属性语法
  • 简洁方法语法

对象属性初始化程序

对象属性初始化程序语法中,我们可以直接用变量初始化对象。这将创建属性,其名称与变量的名称相同。

<script>
   let firstName = 'Tutorials',lastName='Point'
   let company = {
      firstName,
      lastName
   }
   console.log(company)
   console.log(company.firstName)
   console.log(company.lastName)
</script>

上述代码的输出将如下所示:

{firstName: "Tutorials", lastName: "Point"}
Tutorials
Point

计算属性

计算属性语法中,对象的属性可以根据变量动态创建。在下面的示例中,名为suffix的变量用于计算company对象。

<script>
   let suffix = 'Name'
   let company = {
      ['first'+suffix]:'Tutorials',
      ['last'+suffix]:'Point'
   }
   console.log(company)
   console.log(company['firstName'])
   console.log(company['lastName'])
</script>

上述代码的输出将如下所示:

{firstName: "Tutorials", lastName: "Point"}
Tutorials
Point

简洁方法语法中,我们可以直接使用和声明方法,而无需使用function关键字。这是一种简化的语法,用于在对象字面量中包含函数。

<script>
   let firstName = 'Tutorials',lastName='Point'
   let company = {
      firstName,
      lastName,
      getFullName(){
         return this.firstName+" - "+this.lastName
      }
   }
   console.log(company.getFullName())
   console.log(company)
</script>

上述代码的输出如下所示:

Tutorials - Point
{firstName: "Tutorials", lastName: "Point", getFullName: ƒ}

ES6 - 布尔值

布尔对象表示两个值,即“true”“false”。如果省略值参数或值为 0、-0、null、false、NaN、undefined 或空字符串 (“”),则对象具有 false 的初始值。

使用以下语法创建一个布尔对象

var val = new Boolean(value);

布尔属性

以下是布尔对象属性的列表。

序号 属性 & 描述
1 constructor

返回对创建该对象的 Boolean 函数的引用。

2 prototype

prototype 属性允许您向对象添加属性和方法。

布尔方法

以下是布尔对象的方法及其描述的列表。

序号 方法 & 描述
1 toSource()

返回一个包含布尔对象源代码的字符串;您可以使用此字符串创建等效的对象。

2 toString()

返回一个“true”或“false”字符串,具体取决于对象的值。

3 valueOf()

返回布尔对象的原始值。

在以下部分中,我们将查看一些示例以演示布尔方法的使用。

ES6 - 字符串

String 对象允许您使用一系列字符;它使用许多辅助方法包装 JavaScript 的字符串原始数据类型。

由于 JavaScript 会自动在字符串基元和 String 对象之间进行转换,因此您可以对字符串基元调用 String 对象的任何辅助方法。

使用以下语法创建一个 String 对象。

var val = new String(string);

字符串参数是一系列已正确编码的字符。String。

String 属性

以下是 String 对象属性及其描述的列表。

序号 属性 & 描述
1 constructor

返回对创建该对象的 String 函数的引用。

2 length

返回字符串的长度。

3 Prototype

prototype 属性允许您向对象添加属性和方法。

String 方法

以下是 String 对象中可用方法及其描述的列表。

序号 方法 & 描述
1 charAt()

返回指定索引处的字符。

2 charCodeAt()

返回一个数字,指示给定索引处字符的 Unicode 值。

3 concat()

组合两个字符串的文本并返回一个新字符串。

4 indexOf()

返回在调用 String 对象中指定值的第一次出现的索引,如果未找到则返回 -1。

5 lastIndexOf()

返回在调用 String 对象中指定值的最后一次出现的索引,如果未找到则返回 -1。

6 localeCompare()

返回一个数字,指示参考字符串在排序顺序中是在给定字符串之前、之后还是与之相同。

7 match()

用于将正则表达式与字符串匹配。

8 replace()

用于查找正则表达式和字符串之间的匹配项,并将匹配的子字符串替换为新的子字符串。

9 search()

执行对正则表达式和指定字符串之间匹配项的搜索。

10 slice()

提取字符串的一部分并返回一个新字符串。

11 split()

通过将字符串分成子字符串,将 String 对象拆分为字符串数组。

12 substr()

返回从指定位置开始的指定数量字符的字符串中的字符。

13 substring()

返回字符串中两个索引之间的字符。

14 toLocaleLowerCase()

字符串中的字符转换为小写,同时尊重当前区域设置。

15 toLocaleUpperCase()

字符串中的字符转换为大写,同时尊重当前区域设置。

16 toLowerCase()

返回转换为小写的调用字符串值。

17 toString()

返回表示指定对象的字符串。

18 toUpperCase()

返回转换为大写的调用字符串值。

19 valueOf()

返回指定对象的原始值。

ES6 - Symbol

Symbol 简介

ES6 引入了一种称为 Symbol 的新的原始类型。它们有助于在 JavaScript 程序中实现元编程。

语法

const mySymbol = Symbol()
const mySymbol = Symbol(stringDescription)

符号只是您可以存储一些数据的内存片段。每个符号都将指向不同的内存位置。Symbol() 构造函数返回的值是唯一且不可变的。

示例

让我们通过一个示例来理解这一点。最初,我们创建了两个没有描述的符号,然后是具有相同描述的符号。在这两种情况下,当比较符号时,相等运算符都将返回 false。

<script>
   const s1 = Symbol();
   const s2 = Symbol();
   console.log(typeof s1)
   console.log(s1===s2)
   const s3 = Symbol("hello");//description
   const s4 = Symbol("hello");
   console.log(s3)
   console.log(s4)
   console.log(s3==s4)
</script>

上述代码的输出如下所示:

symbol
false
Symbol(hello)
Symbol(hello)
false
序号 属性 & 描述
1 Symbol.for(key)

在符号注册表中搜索具有给定键的现有符号并返回它(如果找到)。否则,将使用此键在全局符号注册表中创建一个新的符号。

2 Symbol.keyFor(sym)

从全局符号注册表中检索给定符号的共享符号键。

Symbol & 类

符号可以与类一起使用来定义类中的属性。优点是,如果属性是如下所示的符号,则只有在知道符号名称的情况下才能在包外部访问该属性。因此,当使用符号作为属性时,数据得到了更好的封装。

示例

<script>
   const COLOR = Symbol()
   const MODEL = Symbol()
   const MAKE = Symbol()
   class Bike {
      constructor(color ,make,model){
      this[COLOR] = color;
      this[MAKE] = make;
      this[MODEL] = model;
   }
}
let bike = new Bike('red','honda','cbr')
console.log(bike)
//property can be accessed ony if symbol name is known
console.log(bike[COLOR])
</script>

上述代码的输出将如下所示:

Bike {Symbol(): "red", Symbol(): "honda", Symbol(): "cbr"}
red

ES6 - 新的字符串方法

以下是方法及其描述的列表。

序号 方法 & 描述
1 String.prototype.startsWith(searchString, position = 0)

如果接收器以 searchString 开头,则返回 true;position 允许您指定要检查的字符串的起始位置。

2 String.prototype.endsWith(searchString, endPosition = searchString.length)

如果接收器以 searchString 开头,则返回 true;position 允许您指定要检查的字符串的起始位置。

3 String.prototype.includes(searchString, position = 0)

如果接收器包含 searchString,则返回 true;position 允许您指定要搜索的字符串的起始位置。

4 String.prototype.repeat(count)

返回接收器,连接 count 次。

模板字面量

模板字面量是允许嵌入表达式的字符串字面量。模板字符串使用反引号 (``) 而不是单引号或双引号。因此,模板字符串可以写成:

var greeting = `Hello World!`; 

字符串插值和模板字面量

模板字符串可以使用 ${ } 语法使用占位符进行字符串替换,如下所示。

示例 1

var name = "Brendan"; 
console.log('Hello, ${name}!');

执行上述代码后,将显示以下输出。

Hello, Brendan!

示例 2:模板字面量和表达式

var a = 10; 
var b = 10; 
console.log(`The sum of ${a} and ${b} is  ${a+b} `);

执行上述代码后,将显示以下输出。

The sum of 10 and 10 is 20 

示例 3:模板字面量和函数表达式

function fn() { return "Hello World"; } 
console.log(`Message: ${fn()} !!`);

执行上述代码后,将显示以下输出。

Message: Hello World !!

多行字符串和模板字面量

模板字符串可以包含多行。

示例

var multiLine = `
   This is 
   a string 
   with multiple 
   lines`; 
console.log(multiLine)

执行上述代码后,将显示以下输出。

This is 
a string 
with multiple 
line

String.raw()

ES6 包含用于原始字符串的标记函数 String.raw,其中反斜杠没有任何特殊含义。String.raw 使我们能够像在正则表达式字面量中一样编写反斜杠。考虑以下示例。

var text =`Hello \n World` 
console.log(text)  

var raw_text = String.raw`Hello \n World ` 
console.log(raw_text)

执行上述代码后,将显示以下输出。

Hello 
World 
Hello \n World

标记模板

标记是一个函数,它可以解释和处理模板字面量。标记出现在模板字面量前面。语法如下所示。

语法

let output_fromTag = tagFunction `Template literal with ${variable1} , ${variable2}`

标记函数实现语法如下:

function tagFunction(literals,...variable_values){
   //process
   return "some result"
}

示例

以下示例定义了一个标记函数myTagFn()。它显示传递给它的参数。显示后,它将Done返回给调用方。

<script>
   function myTagFn(literals,...values){
      console.log("literal values are");
      for(let c of literals){
         console.log(c)
      }

      console.log("variable values are ");
      for(let c of values){
         console.log(c)
      }

      return "Done"
   }
   let company = `TutorialsPoint`
   let company_location = `Mumbai`
   let result = myTagFn `Hello this is ${company} from ${company_location}`

   console.log(result)

</script>

上述代码的输出将如下所示:

//literal
literal values are
Hello this is
from
//values
variable values are
TutorialsPoint
Mumbai
Done

示例

以下标记函数采用模板字面量并将其转换为大写,如下所示:

<script>
   function convertToUpperTagFn(literals, ...values) {
      let result = "";
      for (let i = 0; i < literals.length; i++) {
         result += literals[i];
         if (i < values.length) {
            result += values[i];
         }
      }
      return result.toUpperCase();
   }
   let company = `TutorialsPoint`
   let company_location = `Mumbai`
   let result = convertToUpperTagFn `Hello this is ${company} from ${company_location}`

   console.log(result)

</script>

上述代码的输出如下所示:

HELLO THIS IS TUTORIALSPOINT FROM MUMBAI

String.fromCodePoint()

静态 String.fromCodePoint() 方法返回一个使用指定的 unicode 代码点序列创建的字符串。如果传递无效的代码点,则该函数将抛出 RangeError。

console.log(String.fromCodePoint(42))        
console.log(String.fromCodePoint(65, 90))

执行上述代码后,将显示以下输出。

* 
AZ

ES6 - 数组

使用变量存储值存在以下限制:

  • 变量本质上是标量的。换句话说,变量声明一次只能包含一个值。这意味着要在程序中存储 n 个值,需要 n 个变量声明。因此,当需要存储更大的值集合时,使用变量是不可行的。

  • 程序中的变量以随机顺序分配内存,从而难以按声明顺序检索/读取值。

JavaScript 引入了数组的概念来解决这个问题。

数组是同构的值集合。简单来说,数组是相同数据类型值的集合。它是一种用户定义类型。

数组的特性

  • 数组声明分配连续的内存块。

  • 数组是静态的。这意味着一旦初始化,数组就不能调整大小。

  • 每个内存块代表一个数组元素。

  • 数组元素由一个唯一的整数标识,称为元素的下标/索引。

  • 数组也像变量一样,应该在使用前声明。

  • 数组初始化是指填充数组元素。

  • 数组元素的值可以更新或修改,但不能删除。

声明和初始化数组

要在 JavaScript 中声明和初始化数组,请使用以下语法:

var array_name; //declaration 
array_name = [val1,val2,valn..]   //initialization 
OR 
var array_name = [val1,val2…valn]

注意 - [] 对称为数组的维度。

例如,像这样的声明:var numlist = [2,4,6,8] 将创建一个如下图所示的数组。

Initializing Arrays

访问数组元素

数组名称后跟下标用于引用数组元素。

以下是该方法的语法。

array_name[subscript]

示例:简单数组

var alphas; 
alphas = ["1","2","3","4"] 
console.log(alphas[0]); 
console.log(alphas[1]);

执行上述代码后,将显示以下输出。

1 
2

示例:单语句声明和初始化

var nums = [1,2,3,3] 
console.log(nums[0]); 
console.log(nums[1]); 
console.log(nums[2]); 
console.log(nums[3]);

执行上述代码后,将显示以下输出。

1 
2 
3 
3

数组对象

也可以使用 Array 对象创建数组。Array 构造函数可以作为以下参数传递:

  • 表示数组大小的数值;或

  • 逗号分隔值的列表。

以下示例使用此方法创建数组。

示例

var arr_names = new Array(4)  
for(var i = 0;i<arr_names.length;i++) { 
   arr_names[i] = i * 2 
   console.log(arr_names[i]) 
}

执行上述代码后,将显示以下输出。

0 
2 
4 
6 

示例:Array 构造函数接受逗号分隔的值

var names = new Array("Mary","Tom","Jack","Jill") 
for(var i = 0;i<names.length;i++) { 
   console.log(names[i]) 
}

执行上述代码后,将显示以下输出。

Mary 
Tom 
Jack 
Jill

数组方法

以下是 Array 对象的方法列表及其描述。

序号 方法 & 描述
1 concat()

返回一个新数组,该数组由该数组与其他数组和/或值连接而成

2 every()

如果此数组中的每个元素都满足提供的测试函数,则返回 true。

3 filter()

创建一个新数组,其中包含此数组的所有元素,对于这些元素,提供的过滤函数返回 true。

4 forEach()

为数组中的每个元素调用一个函数。

5 indexOf()

返回数组中等于指定值的元素的第一个(最小)索引,如果未找到则返回 -1。

6 join()

将数组的所有元素连接到一个字符串中。

7 lastIndexOf()

返回数组中等于指定值的元素的最后一个(最大)索引,如果未找到则返回 -1。

8 map()

创建一个新数组,其中包含对该数组中每个元素调用提供的函数的结果。

9 pop()

删除数组中的最后一个元素并返回该元素。

10 push()

向数组末尾添加一个或多个元素,并返回数组的新长度。

11 reduce()

同时对数组的两个值(从左到右)应用函数,以将其简化为单个值。

12 reduceRight()

同时对数组的两个值(从右到左)应用函数,以将其简化为单个值。

13 reverse()

反转数组元素的顺序——第一个变为最后一个,最后一个变为第一个。

14 shift()

删除数组中的第一个元素并返回该元素 slice。

15 slice()

提取数组的一部分并返回一个新数组。

16 some()

如果此数组中的至少一个元素满足提供的测试函数,则返回 true。

17

toSource()

表示对象的源代码。

18 sort()

对数组的元素进行排序。

19 splice()

向数组添加和/或删除元素。

20 toString()

返回表示数组及其元素的字符串。

21 unshift()

向数组前面添加一个或多个元素,并返回数组的新长度。

ES6 - 数组方法

以下是 ES6 中引入的一些新的数组方法。

Array.prototype.find

find 允许你迭代数组并返回导致给定回调函数返回 true 的第一个元素。一旦找到元素,函数立即返回。这是一种有效的方法,可以获取与给定条件匹配的第一个项目。

示例

var numbers = [1, 2, 3]; 
var oddNumber = numbers.find((x) => x % 2 == 1); 
console.log(oddNumber); // 1

执行上述代码后,将显示以下输出。

1

注意 - ES5 的 filter() 和 ES6 的 find() 不是同义词。filter 总是返回匹配项的数组(并将返回多个匹配项),find 总是返回实际的元素。

Array.prototype.findIndex

findIndex 的行为类似于 find,但它不返回匹配的元素,而是返回该元素的索引。

var numbers = [1, 2, 3]; 
var oddNumber = numbers.findIndex((x) => x % 2 == 1); 
console.log(oddNumber); // 0 

上面的例子将返回值 1 的索引 (0) 作为输出。

Array.prototype.entries

entries 是一个函数,它返回一个 Array Iterator,可用于循环遍历数组的键和值。Entries 将返回一个数组的数组,其中每个子数组都是一个 [index, value] 数组。

var numbers = [1, 2, 3]; 
var val = numbers.entries(); 
console.log(val.next().value);  
console.log(val.next().value);  
console.log(val.next().value);

执行上述代码后,将显示以下输出。

[0,1] 
[1.2] 
[2,3]

或者,我们也可以使用扩展运算符一次性获得条目数组。

var numbers = [1, 2, 3]; 
var val= numbers.entries(); 
console.log([...val]);

执行上述代码后,将显示以下输出。

[[0,1],[1,2],[2,3]]

Array.from

Array.from() 能够根据类似数组的对象创建一个新数组。Array.from() 的基本功能是将两种值转换为数组:

  • 类似数组的值。

  • 可迭代的值,如 Set 和 Map。

示例

"use strict" 
for (let i of Array.from('hello')) { 
   console.log(i) 
}

执行上述代码后,将显示以下输出。

h                               
e                               
l                               
l                               
o

Array.prototype.keys()

此函数返回数组索引。

示例

console.log(Array.from(['a', 'b'].keys()))

执行上述代码后,将显示以下输出。

[ 0, 1 ] 

使用 for…in 循环遍历数组

可以使用 for…in 循环遍历数组。

"use strict" 
var nums = [1001,1002,1003,1004] 
for(let j in nums) { 
   console.log(nums[j]) 
}

循环执行基于索引的数组遍历。上述代码成功执行后将显示以下输出。

1001 
1002 
1003 
1004

JavaScript 中的数组

JavaScript 支持以下关于数组的概念:

序号 概念和描述
1 多维数组

JavaScript 支持多维数组。多维数组最简单的形式是二维数组

2 将数组传递给函数

你可以通过指定数组名称而不指定索引来将指向数组的指针传递给函数。

3 从函数返回数组

允许函数返回数组。

数组解构

解构是指将数组或对象中的各个值提取到不同的变量中。考虑一个需要将数组的值分配给各个变量的场景。传统的做法如下:

var a= array1[0]
var b= array1[1]
var c= array1[2]

解构有助于以简洁的方式实现相同的功能。

语法

//destructuring an array
let [variable1,variable2]=[item1,item2]
//destructuring an object
let {property1,property2} = {property1:value1,property2:value2}

示例

<script>
   let names = ['Mohtashim','Kannan','Kiran']
   let [n1,n2,n3] = names;
   console.log(n1)
   console.log(n2)
   console.log(n3);
   //rest operator with array destructuring
   let locations=['Mumbai','Hyderabad','Chennai']
   let [l1,...otherValues] =locations
   console.log(l1)
   console.log(otherValues)
   //variables already declared
   let name1,name2;
   [name1,name2] =names
   console.log(name1)
   console.log(name2)
   //swapping
   let first=10,second=20;
   [second,first] = [first,second]
   console.log("second is ",second) //10
   console.log("first is ",first) //20
</script>

上述代码的输出将如下所示:

Mohtashim
Kannan
Kiran
Mumbai
["Hyderabad", "Chennai"]
Mohtashim
Kannan
second is 10
first is 20

ES6 - 日期

Date 对象是 JavaScript 语言中内置的一种数据类型。Date 对象使用 new Date() 创建,如下面的语法所示。

创建 Date 对象后,许多方法允许你对其进行操作。大多数方法只需允许你获取和设置对象的年、月、日、时、分、秒和毫秒字段,使用本地时间或 UTC(通用时间或 GMT)时间。

ECMAScript 标准要求 Date 对象能够表示 1970 年 1 月 1 日之前或之后 1 亿天内的任何日期和时间,精确到毫秒。这是正负 273,785 年的范围,因此 JavaScript 可以表示到 275755 年的日期和时间。

你可以使用以下任何语法使用 Date() 构造函数创建 Date 对象。

new Date( ) 
new Date(milliseconds) 
new Date(datestring) 
new Date(year,month,date[,hour,minute,second,millisecond ])

注意 - 方括号中的参数始终是可选的。

Date 属性

以下是 Date 对象属性的列表及其描述。

序号 属性 & 描述
1 constructor

指定创建对象原型的函数

2 prototype

prototype 属性允许你向对象添加属性和方法

Date 方法

以下是不同日期方法的列表及其描述。

序号 方法 & 描述
1 Date()

返回今天的日期和时间

2 getDate()

根据本地时间返回指定日期的月份中的日期

3 getDay()

根据本地时间返回指定日期的一周中的日期

4 getFullYear()

根据本地时间返回指定日期的年份

5 getHours()

根据本地时间返回指定日期的小时

6 getMilliseconds()

根据本地时间返回指定日期的毫秒

7 getMinutes()

根据本地时间返回指定日期的分钟

8 getMonth()

根据本地时间返回指定日期的月份

9 getSeconds()

根据本地时间返回指定日期的秒数

10 getTime()

返回指定日期的数值,为自 1970 年 1 月 1 日 00:00:00 UTC 以来以毫秒表示的数字

11 getTimezoneOffset()

返回当前区域设置的时区偏移量(以分钟为单位)

12 getUTCDate()

根据世界协调时间返回指定日期的月份中的日期

13 getUTCDay()

根据世界协调时间返回指定日期的一周中的日期

14 getUTCFullYear()

根据世界协调时间返回指定日期的年份

15 getutcHours()

根据世界协调时间返回指定日期的小时

16 getUTCMilliseconds()

根据世界协调时间返回指定日期的毫秒

17 getUTCMinutes()

根据世界协调时间返回指定日期的分钟

18 getUTCMonth()

根据世界协调时间返回指定日期的月份

19 getUTCSeconds()

根据世界协调时间返回指定日期的秒数

20 setDate()

根据本地时间设置指定日期的月份中的日期

21 setFullYear()

根据本地时间设置指定日期的年份

22 setHours()

根据本地时间设置指定日期的小时

23 setMilliseconds()

根据本地时间设置指定日期的毫秒

24 setMinutes()

根据本地时间设置指定日期的分钟

25 setMonth()

根据本地时间设置指定日期的月份

26 setSeconds()

根据本地时间设置指定日期的秒数

27 setTime()

将 Date 对象设置为自 1970 年 1 月 1 日 00:00:00 UTC 以来以毫秒表示的时间

28 setUTCDate()

将 Date 对象设置为自 1970 年 1 月 1 日 00:00:00 UTC 以来以毫秒表示的时间

29 setUTCFullYear()

根据世界协调时间设置指定日期的年份

30 setUTCHours()

根据世界协调时间设置指定日期的小时

31 setUTCMilliseconds()

根据世界协调时间设置指定日期的毫秒

32 setUTCMinutes()

根据世界协调时间设置指定日期的分钟

33 setUTCMonth()

根据世界协调时间设置指定日期的月份

34 setUTCSeconds()

根据世界协调时间设置指定日期的秒数

35 toDateString()

将日期的“日期”部分作为人类可读的字符串返回

36 toLocaleDateString()

使用当前区域设置的约定将日期的“日期”部分作为字符串返回

37 toLocaleString()

使用当前区域设置的约定将日期转换为字符串

38 toLocaleTimeString()

使用当前区域设置的约定将日期的“时间”部分作为字符串返回

39 toString()

返回表示指定 Date 对象的字符串

40 toTimeString()

将日期的“时间”部分作为人类可读的字符串返回

41 toUTCString()

使用世界协调时间约定将日期转换为字符串

42 valueOf()

返回 Date 对象的原始值

ES6 - 数学对象

Math 对象为你提供数学常数和函数的属性和方法。与其他全局对象不同,Math 不是构造函数。Math 的所有属性和方法都是静态的,可以使用 Math 作为对象来调用,而无需创建它。

Math 属性

以下是所有 Math 属性及其描述的列表。

序号 属性 & 描述
1 E

欧拉常数和自然对数的底数,约为 2.718

2 LN2

2的自然对数,约等于0.693

3 LN10

10的自然对数,约等于2.302

4 LOG2E

E的以2为底的对数,约等于1.442

5 LOG10E

E的以10为底的对数,约等于0.434

6 PI

圆周率(圆周长与直径之比),约等于3.14159

7 SQRT1_2

1/2的平方根;等效于1除以2的平方根,约等于0.707

8 SQRT2

2的平方根,约等于1.414

指数函数

基本的指数函数是Math.pow(),并且还有用于平方根、立方根和e的幂的便捷函数,如下表所示。

序号 函数及描述
1 Math.pow(x, y)

返回xy次幂

2 Math.sqrt(x)

返回数字x的平方根

3 Math.cbrt(x)

此方法返回数字x的立方根

4 Math.exp(x)

等效于Math.pow(Math.E, x)

5 Math.expm1(x)

等效于Math.exp(x) – 1

6 Math.hypot(x1, x2,...)

返回参数之和的平方根

对数函数

基本的自然对数函数是Math.log()。在JavaScript中,“log”表示“自然对数”。ES6为了方便引入了Math.log10。

序号 函数及描述
1 Math.log(x)

x的自然对数

2 Math.log10(x)

x的以10为底的对数

3 Math.log2(x)

x的以2为底的对数

4 Math.log1p(x)

1 + x的自然对数

其他代数函数

以下是其他代数函数及其描述的列表。

序号 函数及描述
1 Math.abs(x)

x的绝对值

2 Math.sign(x)

x的符号:如果x为负数,则为-1;如果x为正数,则为1;如果x为0,则为0

3 Math.ceil(x)

x的向上取整:大于或等于x的最小整数

4 Math.floor(x)

x的向下取整:小于或等于x的最大整数

5 Math.trunc(x)

x的整数部分(所有小数位都被移除)

6 Math.round(x)

四舍五入到最接近的整数

7 Math.min(x1, x2,...)

返回最小参数

8 Math.max((x1, x2,...))

返回最小参数

三角函数

Math库中的所有三角函数都使用弧度,而不是角度。

序号 函数及描述
1 Math.sin(x)

x弧度的正弦值

2 Math.cos(x)

x弧度的余弦值

3 Math.tan(x)

x弧度的正切值

4 Math.asin(x)

x的反正弦(arcsin)(结果以弧度表示)

5 Math.acos(x)

x的反余弦(arccos)(结果以弧度表示)

6 Math.atan(x)

x的反正切(arctan)(结果以弧度表示)

7 Math.atan2(y, x0)

从x轴到点(x, y)的逆时针角度(以弧度表示)

Math.random()

Math.random()函数返回一个介于0(包含)和1(不包含)之间的伪随机数。

示例:伪随机数生成 (PRNG)

var value1 = Math.random();  
console.log("First Test Value : " + value1 ); 

var value2 = Math.random();  
console.log("Second Test Value : " + value2 ); 

var value3 = Math.random();  
console.log("Third Test Value : " + value3 ); 

var value4 = Math.random(); 
console.log("Fourth Test Value : " + value4 );

输出

First Test Value : 0.5782922627404332 
Second Test Value : 0.5624510529451072 
Third Test Value : 0.9336334094405174 
Fourth Test Value : 0.4002739654388279

ES6 - 正则表达式

正则表达式是一个描述字符模式的对象。正则表达式通常缩写为“regex”或“regexp”。

JavaScript的RegExp类表示正则表达式,String和RegExp都定义了使用正则表达式对文本执行强大的模式匹配和搜索替换功能的方法。

正则表达式可以定义为:

var pattern = new RegExp(pattern, attributes); 
OR 
var pattern = /pattern/attributes;

属性可以具有以下值的任何组合。

序号 属性及描述
1

G

全局匹配

2

I

忽略大小写

3

M

多行;将开头和结尾字符(^和$)视为作用于多行(即匹配每一行的开头或结尾(由\n或\r分隔),而不仅仅是整个输入字符串的开头或结尾)

4

U

Unicode;将模式视为Unicode代码点的序列

5

Y

粘性;仅匹配目标字符串中此正则表达式的lastIndex属性指示的索引(并且不尝试从任何后面的索引匹配)

构造正则表达式

Brackets

括号([])在正则表达式上下文中具有特殊含义。它们用于查找一系列字符。

序号 表达式及描述
1

[...]

括号内的任意一个字符

2

[^...]

括号外任意一个字符

3

[0-9]

匹配0到9之间的任何十进制数字

4

[a-z]

匹配从小写a到小写z的任何字符

5

[A-Z]

匹配从大写A到大写Z的任何字符

6

[a-Z]

匹配从小写a到大写Z的任何字符

上面显示的范围是一般的;您也可以使用范围[0-3]来匹配0到3之间的任何十进制数字,或者使用范围[b-v]来匹配从b到v之间的任何小写字符。

量词

括号字符序列和单个字符的频率或位置可以用特殊字符表示。每个特殊字符都有其特定的含义。+、*、?$标志都位于字符序列之后。

序号 表达式及描述
1

p+

匹配包含至少一个p的任何字符串。

2

p*

匹配包含零个或多个p的任何字符串

3

p?

匹配包含一个或多个p的任何字符串

4

p{N}

匹配包含Np序列的任何字符串

5

p{2,3}

匹配包含两个或三个p序列的任何字符串

6

p{2, }

匹配包含至少两个p序列的任何字符串

7

p$

匹配结尾为p的任何字符串

8

^p

匹配开头为p的任何字符串

9

[^a-zA-Z]

匹配不包含从az和从AZ的任何字符的任何字符串

10

p.p

匹配包含p,后跟任何字符,然后又是另一个p的任何字符串

11

^.{2}$

匹配包含恰好两个字符的任何字符串

12

<b>(.*)</b>

匹配包含在<b>和</b>之间的任何字符串

13

p(hp)*

匹配包含p后跟零个或多个hp序列的任何字符串

字面字符

序号 字符及描述
1

字母数字

自身

2

\0

空字符 (\u0000)

3

\t

制表符 (\u0009)

4

\n

换行符 (\u000A)

5

\v

垂直制表符 (\u000B)

6

\f

换页符 (\u000C)

7

\r

回车符 (\u000D)

8

\xnn

由十六进制数nn指定的拉丁字符;例如,\x0A与\n相同

9

\uxxxx

由十六进制数xxxx指定的Unicode字符;例如,\u0009与\t相同

10

\cX

控制字符^X;例如,\cJ相当于换行符\n

元字符

元字符只是一个以反斜杠开头的字母字符,它赋予组合特殊的含义。

例如,您可以使用'\d'元字符搜索一大笔钱:/([\d]+)000/。在这里,\d将搜索任何数字字符的字符串。

下表列出了一组可在PERL风格正则表达式中使用的元字符。

序号 字符及描述
1

.

单个字符

2

\s

空格字符(空格、制表符、换行符)

3

\S

非空格字符

4

\d

数字 (0-9)

5

\D

非数字

6

\w

单词字符 (a-z, A-Z, 0-9, _)

7

\W

非单词字符

8

[\b]

字面退格符(特殊情况)

9

[aeiou]

匹配给定集合中的单个字符

10

[^aeiou]

匹配给定集合外的单个字符

11

(foo|bar|baz)

匹配指定的任何备选方案

RegExp 属性

序号 属性及描述
1 RegExp.prototype.flags

包含RegExp对象的标志的字符串

2 RegExp.prototype.global

是否针对字符串中的所有可能匹配项测试正则表达式,还是仅针对第一个匹配项测试

3 RegExp.prototype.ignoreCase

在尝试匹配字符串时是否忽略大小写

4 RegExp.prototype.lastIndex

RegExp对象的读/写属性。

5 RegExp.prototype.multiline

是否在多行字符串中搜索

6 RegExp.prototype.source

模式文本

RegExp 方法

序号 方法 & 描述
1 RegExp.prototype.exec()

在其字符串参数中执行匹配搜索

2 RegExp.prototype.test()

测试其字符串参数中的匹配项

3 RegExp.prototype.match()

对给定字符串执行匹配并返回匹配结果

4 RegExp.prototype.replace()

将给定字符串中的匹配项替换为新的子字符串

5 RegExp.prototype.search()

搜索给定字符串中的匹配项并返回模式在字符串中找到的索引

6 RegExp.prototype.split()

通过将字符串分成子字符串来将给定字符串分割成数组

7 RegExp.prototype.toString()

返回表示指定对象的字符串。覆盖Object.prototype.toString()方法

ES6 - HTML DOM

每个网页都位于浏览器窗口内,可以将其视为一个对象。

文档对象表示显示在该窗口中的HTML文档。文档对象具有各种属性,这些属性引用其他对象,允许访问和修改文档内容。

访问和修改文档内容的方式称为文档对象模型DOM。对象按层次结构组织。这种层次结构适用于网页文档中对象的组织。

以下是一些重要对象的简单层次结构:

HTML DOM

存在多个DOM。以下各节将详细解释这些DOM中的每一个,并描述如何使用它们来访问和修改文档内容。

  • 传统DOM - 这是在早期版本的JavaScript语言中引入的模型。它受到所有浏览器的良好支持,但仅允许访问文档的某些关键部分,例如表单、表单元素和图像。

  • W3C DOM - 此文档对象模型允许访问和修改所有文档内容,并由万维网联盟 (W3C) 标准化。此模型几乎受到所有现代浏览器的支持。

  • IE4 DOM - 此文档对象模型是在Microsoft Internet Explorer浏览器的版本4中引入的。IE 5及更高版本包含对大多数基本W3C DOM功能的支持。

传统DOM

这是在早期版本的JavaScript语言中引入的模型。它受到所有浏览器的良好支持,但仅允许访问文档的某些关键部分,例如表单、表单元素和图像。

此模型提供了一些只读属性,例如title、URL和lastModified,这些属性提供有关整个文档的信息。除此之外,此模型还提供了各种方法,可用于设置和获取文档属性值。

传统DOM中的文档属性

以下是可以使用传统DOM访问的文档属性列表。

序号 属性 & 描述
1

alinkColor

已弃用 - 指定活动链接颜色的字符串。

示例:document.alinkColor

2

anchors[ ]

锚对象的数组,每个出现在文档中的锚点一个。

示例:document.anchors[0]、document.anchors[1]等等

3

applets[ ]

applet对象的数组,文档中出现的每个applet一个。

示例:document.applets[0]、document.applets[1]等等

4

bgColor

已弃用 - 指定文档背景颜色的字符串。

示例:document.bgColor

5

Cookie

具有特殊行为的字符串值属性,允许查询和设置与此文档关联的cookie。

示例:document.cookie

6

Domain

指定文档所属互联网域名的字符串。用于安全目的。

示例:document.domain

7

embeds[ ]

一个对象数组,表示文档中使用<embed>标签嵌入的数据。它是plugins[ ]的同义词。某些插件和ActiveX控件可以使用JavaScript代码进行控制。

示例:document.embeds[0],document.embeds[1] 等等

8

fgColor

指定文档默认文本颜色的字符串。

示例:document.fgColor

9

forms[ ]

一个表单对象数组,每个对象对应文档中出现的HTML表单。

示例:document.forms[0],document.forms[1] 等等

10

images[ ]

一个表单对象数组,每个对象对应文档中使用HTML <img> 标签出现的图像。

示例:document.forms[0],document.forms[1] 等等

11

lastModified

一个只读字符串,指定文档最近一次修改的日期。

示例:document.lastModified

12

linkColor

已弃用 - 指定未访问链接颜色的字符串。

示例:document.linkColor

13

links[ ]

这是一个文档链接数组。

示例:document.links[0],document.links[1] 等等

14

Location

文档的URL。已弃用,建议使用URL属性。

示例:document.location

15

plugins[ ]

embeds[ ] 的同义词。

示例:document.plugins[0],document.plugins[1] 等等

16

Referrer

一个只读字符串,包含当前文档链接到的文档(如果有)的URL。

示例:document.referrer

17

Title

<title>标签的文本内容。

示例:document.title

18

URL

一个只读字符串,指定文档的URL。

示例:document.URL

19

vlinkColor

已弃用 - 指定已访问链接颜色的字符串。

示例:document.vlinkColor

传统DOM中的文档方法

以下是传统DOM支持的方法列表。

序号 属性 & 描述
1

clear( )

已弃用 - 清除文档内容并返回空。

示例:document.clear( )

2

close( )

关闭使用open( )方法打开的文档流,并返回空。

3

open( )

删除现有文档内容并打开一个流,可以向其中写入新的文档内容。返回空。

示例:document.open( )

4

write( value, ...)

将指定的字符串插入到当前正在解析的文档中,或者追加到使用open( )打开的文档中。返回空。

示例:document.write( value, ...)

5

writeln( value, ...)

与write( )相同,只是它会在输出中追加一个换行符。返回空。

示例:document.writeln( value, ...)

我们可以使用HTML DOM在任何HTML文档中定位任何HTML元素。例如,如果一个网页文档包含一个表单元素,那么使用JavaScript,我们可以将其引用为document.forms[0]。如果您的网页文档包含两个表单元素,则第一个表单被称为document.forms[0],第二个被称为document.forms[1]。

使用上面给出的层次结构和属性,我们可以使用document.forms[0].elements[0]等等访问第一个表单元素。

示例

以下是如何使用传统DOM方法访问文档属性的示例。

<html> 
   <head> 
      <title> Document Title </title> 
      
      <script type = "text/javascript"> 
         <!--  
            function myFunc() {  
               var ret = document.title;  
               alert("Document Title : " + ret );  
               var ret = document.URL;  
               alert("Document URL : " + ret );  
               var ret = document.forms[0];  
               alert("Document First Form : " + ret );  
               var ret = document.forms[0].elements[1];  
               alert("Second element : " + ret );  
            } //
         --> 
      </script> 
   </head> 
   
   <body> 
      <h1 id = "title">This is main title</h1> 
      <p>Click the following to see the result:</p> 
      
      <form name = "FirstForm">
         <input type = "button" value = "Click Me" onclick = "myFunc();" /> 
         <input type = "button" value = "Cancel"> 
      </form> 

      <form name = "SecondForm"> 
         <input type = "button" value = "Don't ClickMe"/> 
      </form> 
   </body> 
   
</html> 

输出

执行上述代码后,将显示以下输出。

legacy dom method

注意 - 此示例返回表单和元素的对象。我们将必须使用在本教程中未讨论的对象属性来访问它们的值。

ES6 - 迭代器

迭代器简介

迭代器是一个对象,它允许我们一次访问一个对象集合。

以下内置类型默认情况下是可迭代的:

  • 字符串
  • 数组
  • 映射(Map)
  • 集合(Set)

如果对象实现了一个键为[Symbol.iterator]并返回迭代器的函数,则该对象被认为是可迭代的。可以使用for...of循环迭代集合。

示例

以下示例声明一个数组marks,并使用for..of循环对其进行迭代。

<script>
   let marks = [10,20,30]
   //check iterable using for..of
   for(let m of marks){
      console.log(m);
   }
</script>

上述代码的输出将如下所示:

10
20
30

示例

以下示例声明一个数组marks并检索一个迭代器对象。可以使用[Symbol.iterator]()检索迭代器对象。迭代器的next()方法返回一个具有'value''done'属性的对象。'done'是布尔值,在读取集合中的所有项目后返回true。

<script>
   let marks = [10,20,30]
   let iter = marks[Symbol.iterator]();
   console.log(iter.next())
   console.log(iter.next())
   console.log(iter.next())
   console.log(iter.next())
</script>

上述代码的输出将如下所示:

{value: 10, done: false}
{value: 20, done: false}
{value: 30, done: false}
{value: undefined, done: true}

自定义可迭代对象

JavaScript中某些类型是可迭代的(例如Array、Map等),而另一些则不是(例如类)。默认情况下不可迭代的JavaScript类型可以使用可迭代协议进行迭代。

以下示例定义一个名为CustomerList的类,该类将多个客户对象存储为数组。每个客户对象都具有firstName和lastName属性。

为了使此类可迭代,该类必须实现[Symbol.iterator]()函数。此函数返回一个迭代器对象。迭代器对象有一个函数next,它返回一个对象{value:'customer',done:true/false}

<script>
   //user defined iterable
   class CustomerList {
      constructor(customers){
         //adding customer objects to an array
         this.customers = [].concat(customers)
      }
      //implement iterator function
      [Symbol.iterator](){
         let count=0;
         let customers = this.customers
         return {
            next:function(){
            //retrieving a customer object from the array
               let customerVal = customers[count];
               count+=1;
               if(count<=customers.length){
                  return {
                     value:customerVal,
                     done:false
                  }
               }
               //return true if all customer objects are iterated
               return {done:true}
            }
         }
      }
   }
   //create customer objects
   let c1={
      firstName:'Sachin',
      lastName:'Tendulkar'
   }
   let c2={
      firstName:'Rahul',
      lastName:'Dravid'
   }
   //define a customer array and initialize it let customers=[c1,c2]
   //pass customers to the class' constructor
   let customersObj = new CustomerList(customers);
   //iterating using for..of
   for(let c of customersObj){
      console.log(c)
   }
   //iterating using the next() method
   let iter = customersObj[Symbol.iterator]();
   console.log(iter.next())
   console.log(iter.next())
   console.log(iter.next())
</script>

上述代码的输出如下:

{firstName: "Sachin", lastName: "Tendulkar"}
{firstName: "Rahul", lastName: "Dravid"}
{
   done: false
   value: {
      firstName: "Sachin",
      lastName: "Tendulkar"
   }
}
{
   done: false
   value: {
      firstName: "Rahul",
      lastName: "Dravid"
   }
}
{done: true}

生成器

在ES6之前,JavaScript中的函数遵循运行到完成模型。ES6引入了称为生成器的函数,这些函数可以中途停止,然后从停止的地方继续。

生成器在函数名前缀一个星号*字符,并包含一个或多个yield语句。yield关键字返回一个迭代器对象。

语法

function * generator_name() {
   yield value1
   ...
   yield valueN
}

示例

此示例定义了一个生成器函数getMarks,其中包含三个yield语句。与普通函数不同,生成器函数getMarks()在调用时不会执行函数,而是返回一个迭代器对象,该对象有助于执行生成器函数内的代码。

在第一次调用markIter.next()时,开始处的操作将运行,而yield语句会暂停生成器的执行。随后对markIter.next()的调用将恢复生成器函数,直到下一个yield表达式。

<script>
   //define generator function
   function * getMarks(){
      console.log("Step 1")
      yield 10
      console.log("Step 2")
      yield 20
      console.log("Step 3")
      yield 30
      console.log("End of function")
   }
   //return an iterator object
      let markIter = getMarks()
   //invoke statements until first yield
      console.log(markIter.next())
   //resume execution after the last yield until second yield expression
      console.log(markIter.next())
   //resume execution after last yield until third yield expression
      console.log(markIter.next())
      console.log(markIter.next()) // iteration is completed;no value is returned
</script>

上述代码的输出如下所示:

Step 1
{value: 10, done: false}
Step 2
{value: 20, done: false}
Step 3
{value: 30, done: false}
End of function
{value: undefined, done: true}

示例

以下示例通过

* evenNumberGenerator生成器函数创建一个无限的偶数序列。

我们可以使用next()或使用for of循环迭代所有偶数,如下所示

<script>
   function * evenNumberGenerator(){
      let num = 0;
      while(true){
         num+=2
         yield num
      }
   }
   // display first two elements
   let iter = evenNumberGenerator();
   console.log(iter.next())
   console.log(iter.next())
   //using for of to iterate till 12
   for(let n of evenNumberGenerator()){
      if(n==12)break;
      console.log(n);
   }
</script>

上述代码的输出如下:

{value: 2, done: false}
{value: 4, done: false}
2
4
6
8
10

ES6 - 集合

ES6引入了两种新的数据结构:Map和Set。

  • Map - 此数据结构允许将键映射到值。

  • Set - Set类似于数组。但是,Set不允许重复。

Map

Map对象是一个简单的键/值对。Map中的键和值可以是原始值或对象。

以下是该方法的语法。

new Map([iterable]) 

参数iterable表示任何可迭代的对象,其元素包含键/值对。Map是有序的,即它们按插入顺序遍历元素。

Map属性

序号 属性 & 描述
1 Map.prototype.size

此属性返回Map对象中键/值对的数量。

理解基本的Map操作

set()函数设置Map对象中键的值。set()函数接受两个参数,即键及其值。此函数返回Map对象。

has()函数返回一个布尔值,指示Map对象中是否存在指定的键。此函数接受一个键作为参数。

var map = new Map(); 
map.set('name','Tutorial Point'); 
map.get('name'); // Tutorial point

上面的示例创建一个map对象。该map只有一个元素。元素键用name表示。该键映射到值Tutorial point

注意 - Map区分类似的值,但具有不同的数据类型。换句话说,整数键1字符串键“1”被认为是不同的。考虑以下示例以更好地理解这个概念

var map = new Map(); 
map.set(1,true); 
console.log(map.has("1")); //false 
map.set("1",true); 
console.log(map.has("1")); //true

输出

false 
true 

set()方法也是可链的。考虑以下示例。

var roles = new Map(); 
roles.set('r1', 'User') 
.set('r2', 'Guest') 
.set('r3', 'Admin'); 
console.log(roles.has('r1'))

输出

True 

上面的示例定义了一个map对象。该示例链式调用set()函数来定义键/值对。

get()函数用于检索与指定键对应的值。

Map构造函数也可以传递一个数组。此外,map还支持使用扩展运算符来表示数组。

示例

var roles = new Map([ 
   ['r1', 'User'], 
   ['r2', 'Guest'], 
   ['r3', 'Admin'], 
]);  
console.log(roles.get('r2'))

执行上述代码后,将显示以下输出。

Guest

注意 - 如果Map中不存在指定的键,则get()函数返回undefined。

如果键已存在于map中,则set()会替换该键的值。考虑以下示例。

var roles = new Map([ 
   ['r1', 'User'], 
   ['r2', 'Guest'], 
   ['r3', 'Admin'], 
]);  
console.log(`value of key r1 before set(): ${roles.get('r1')}`) 
roles.set('r1','superUser') 
console.log(`value of key r1 after set(): ${roles.get('r1')}`)

执行上述代码后,将显示以下输出。

value of key r1 before set(): User 
value of key r1 after set(): superUser

Map方法

序号 方法 & 描述
1 Map.prototype.clear()

删除Map对象中的所有键/值对。

2 Map.prototype.delete(key)

删除与键关联的任何值,并返回Map.prototype.has(key)之前将返回的值。

Map.prototype.has(key)之后将返回false。

3 Map.prototype.entries()

返回一个新的迭代器对象,该对象包含Map对象中每个元素的[key, value]数组,顺序为插入顺序。

4 Map.prototype.forEach(callbackFn[, thisArg])

为Map对象中存在的每个键值对调用callbackFn一次,顺序为插入顺序。如果向forEach提供thisArg参数,则它将用作每个回调的“this”值。

5 Map.prototype.keys()

返回一个新的迭代器对象,该对象包含Map对象中每个元素的,顺序为插入顺序。

6 Map.prototype.values()

返回一个新的迭代器对象,该对象包含Map对象中每个元素的[key, value]数组,顺序为插入顺序。

for…of循环

以下示例演示了使用for…of循环遍历map。

'use strict' 
var roles = new Map([ 
   ['r1', 'User'], 
   ['r2', 'Guest'], 
   ['r3', 'Admin'], 
]);
for(let r of roles.entries()) 
console.log(`${r[0]}: ${r[1]}`);

执行上述代码后,将显示以下输出。

r1: User 
r2: Guest 
r3: Admin

弱Map(Weak Map)

弱Map与Map相同,但有以下例外:

  • 它的键必须是对象。

  • 弱Map中的键可以被垃圾回收。垃圾回收是清除程序中未引用对象占用的内存的过程。

  • 弱Map不能被迭代或清除。

示例:弱Map

'use strict' 
let weakMap = new WeakMap(); 
let obj = {}; 
console.log(weakMap.set(obj,"hello"));  
console.log(weakMap.has(obj));// true

执行上述代码后,将显示以下输出。

WeakMap {} 
true

Set

Set是ES6数据结构。它类似于数组,区别在于它不能包含重复项。换句话说,它允许您存储唯一的值。Set支持原始值和对象引用。

与Map一样,Set也是有序的,即元素按其插入顺序进行迭代。可以使用以下语法初始化Set。

Set属性

序号 属性 & 描述
1 Set.prototype.size

返回Set对象中的值的数量。

Set方法

序号 方法 & 描述
1 Set.prototype.add(value)

将一个具有给定值的新元素添加到Set对象中。返回Set对象。

2 Set.prototype.clear()

删除Set对象中的所有元素。

3 Set.prototype.delete(value)

删除与值关联的元素。

4 Set.prototype.entries()

返回一个新的迭代器对象,该对象包含Set对象中每个元素的[value, value]数组,顺序为插入顺序。这与Map对象保持一致,因此每个条目的键和值在此处具有相同的值。

5 Set.prototype.forEach(callbackFn[, thisArg])

为Set对象中存在的每个值调用callbackFn一次,顺序为插入顺序。如果向forEach提供athisArg参数,则它将用作每个回调的“this”值。

6 Set.prototype.has(value)

返回一个布尔值,用于断言Set对象中是否存在具有给定值或不存在的元素。

7 Set.prototype.values()

返回一个新的迭代器对象,该对象包含Set对象中每个元素的,顺序为插入顺序。

弱Set(Weak Set)

弱Set只能包含对象,并且它们包含的对象可以被垃圾回收。与弱Map一样,弱Set也不能被迭代。

示例:使用弱Set

'use strict' 
   let weakSet = new WeakSet();  
   let obj = {msg:"hello"}; 
   weakSet.add(obj); 
   console.log(weakSet.has(obj)); 
   weakSet.delete(obj); 
   console.log(weakSet.has(obj));

执行上述代码后,将显示以下输出。

true 
false

迭代器

迭代器是一个对象,它允许一次访问一个对象集合。Set和Map都具有返回迭代器的方法。

迭代器是具有next()方法的对象。当调用next()方法时,它会返回一个包含'value''done'属性的对象。'done'是布尔值,在读取集合中的所有项目后将返回true。

示例1:集合和迭代器

var  set = new Set(['a','b','c','d','e']);  
var iterator = set.entries(); 
console.log(iterator.next())

执行上述代码后,将显示以下输出。

{ value: [ 'a', 'a' ], done: false } 

由于集合不存储键/值对,因此值数组包含相似的键和值。done 将为 false,因为还有更多元素需要读取。

示例2:集合和迭代器

var  set = new Set(['a','b','c','d','e']);  
var iterator = set.values(); 
console.log(iterator.next());

执行上述代码后,将显示以下输出。

{ value: 'a', done: false }  

示例3:集合和迭代器

var  set = new Set(['a','b','c','d','e']);  
var iterator = set.keys(); 
console.log(iterator.next()); 

执行上述代码后,将显示以下输出。

{ value: 'a', done: false }  

示例4:映射和迭代器

var map = new Map([[1,'one'],[2,'two'],[3,'three']]); 
var iterator = map.entries(); 
console.log(iterator.next()); 

执行上述代码后,将显示以下输出。

{ value: [ 1, 'one' ], done: false }  

示例5:映射和迭代器

var map = new Map([[1,'one'],[2,'two'],[3,'three']]); 
var iterator = map.values(); 
console.log(iterator.next());  

执行上述代码后,将显示以下输出。

{value: "one", done: false} 

示例6:映射和迭代器

var map = new Map([[1,'one'],[2,'two'],[3,'three']]); 
var iterator = map.keys(); 
console.log(iterator.next());  

执行上述代码后,将显示以下输出。

{value: 1, done: false} 

ES6 - 类

面向对象是一种遵循现实世界建模的软件开发范式。面向对象将程序视为通过称为方法的机制相互通信的对象集合。ES6 也支持这些面向对象的组件。

面向对象编程概念

首先,让我们了解

  • 对象- 对象是任何实体的实时表示。根据 Grady Brooch 的说法,每个对象据说具有 3 个特征:

    • 状态- 由对象的属性描述。

    • 行为- 描述对象将如何行动。

    • 标识- 一个唯一值,将对象与一组类似的对象区分开来。

  • - 在 OOP 中,类是创建对象的蓝图。类封装了对象的数据。

  • 方法- 方法促进对象之间的通信。

让我们将这些面向对象的概念转化为现实世界中的概念。例如:汽车是一个对象,它具有数据(制造商、型号、车门数量、车辆号码等)和功能(加速、换挡、打开车门、打开车灯等)。

在 ES6 之前,创建类是一件麻烦事。在 ES6 中,可以使用 class 关键字创建类。

类可以通过声明它们或使用类表达式包含在代码中。

语法:声明类

class Class_name {  
}

语法:类表达式

var var_name = new Class_name {  
} 

class 关键字后跟类名。命名类时必须考虑标识符规则(已讨论)。

类定义可以包含以下内容:

  • 构造函数- 负责为类的对象分配内存。

  • 函数- 函数表示对象可以执行的操作。它们有时也称为方法。

这些组件组合在一起被称为类的成员数据。

注意- 类体只能包含方法,不能包含数据属性。

示例:声明一个类

class Polygon { 
   constructor(height, width) { 
      this.height = height; 
      this.width = width; 
   } 
}

示例:类表达式

var Polygon = class { 
   constructor(height, width) { 
      this.height = height; 
      this.width = width; 
   } 
}

上面的代码片段表示一个未命名的类表达式。命名的类表达式可以写成。

var Polygon = class Polygon { 
   constructor(height, width) { 
      this.height = height; 
      this.width = width; 
   } 
}

注意- 与变量和函数不同,类不能提升。

创建对象

要创建类的实例,请使用 new 关键字后跟类名。以下是相同的语法。

var object_name= new class_name([ arguments ]) 

其中,

  • new 关键字负责实例化。

  • 表达式的右侧调用构造函数。如果构造函数是参数化的,则应向其传递值。

示例:实例化一个类

var obj = new Polygon(10,12)

访问函数

可以通过对象访问类的属性和函数。使用“.”点表示法(称为句点)来访问类的成员数据。

//accessing a function 
obj.function_name()

示例:将它们放在一起

'use strict' 
class Polygon { 
   constructor(height, width) { 
      this.h = height; 
      this.w = width;
   } 
   test() { 
      console.log("The height of the polygon: ", this.h) 
      console.log("The width of the polygon: ",this. w) 
   } 
} 

//creating an instance  
var polyObj = new Polygon(10,20); 
polyObj.test();      

上面给出的示例声明了一个名为“Polygon”的类。该类的构造函数接受两个参数 - 高度和宽度。'this'关键字指的是类的当前实例。换句话说,上面的构造函数使用传递给构造函数的参数值初始化两个变量 h 和 w。类中的test()函数打印高度和宽度的值。

为了使脚本正常工作,创建了 Polygon 类的对象。该对象由polyObj变量引用。然后通过此对象调用该函数。

执行上述代码后,将显示以下输出。

The height of the polygon:  10 
The width of the polygon:  20 

设置器和获取器

设置器

当尝试设置属性的值时,将调用 setter 函数。set 关键字用于定义 setter 函数。定义 setter 函数的语法如下:

{set prop(val) { . . . }}
{set [expression](val) { . . . }}

prop是要绑定到给定函数的属性的名称。val是持有尝试分配给属性的值的变量的别名。ES6 中的表达式可以用作要绑定到给定函数的属性名。

示例

<script>
   class Student {
      constructor(rno,fname,lname){
         this.rno = rno
         this.fname = fname
         this.lname = lname
         console.log('inside constructor')
      }
      set rollno(newRollno){
         console.log("inside setter")
         this.rno = newRollno
      }
   }
   let s1 = new Student(101,'Sachin','Tendulkar')
   console.log(s1)
   //setter is called
   s1.rollno = 201
   console.log(s1)
</script>

上面的示例定义了一个名为 Student 的类,它具有三个属性,即rno、fname 和 lname。setter 函数rollno()用于设置 rno 属性的值。

上述代码的输出将如下所示:

inside constructor
Student {rno: 101, fname: "Sachin", lname: "Tendulkar"}
inside setter
Student {rno: 201, fname: "Sachin", lname: "Tendulkar"}

示例

以下示例显示了如何使用表达式作为具有setter 函数的属性名。

<script>
   let expr = 'name';
      let obj = {
      fname: 'Sachin',
      set [expr](v) { this.fname = v; }
   };
   console.log(obj.fname);
   obj.name = 'John';
   console.log(obj.fname);
</script>

上述代码的输出如下所示:

Sachin
John

获取器

当尝试获取属性的值时,将调用getter 函数get 关键字用于定义 getter 函数。定义 getter 函数的语法如下:

{get prop() { ... } }
{get [expression]() { ... } }

prop是要绑定到给定函数的属性的名称。

表达式- 从 ES6 开始,您还可以使用表达式作为属性名来绑定到给定函数。

示例

<script>
   class Student {
      constructor(rno,fname,lname){
         this.rno = rno
         this.fname = fname
         this.lname = lname
         console.log('inside constructor')
      }
      get fullName(){
         console.log('inside getter')
         return this.fname + " - "+this.lname
      }
   }
   let s1 = new Student(101,'Sachin','Tendulkar')
   console.log(s1)
   //getter is called
   console.log(s1.fullName)
</script>

上面的示例定义了一个名为 Student 的类,它具有三个属性,即rno、fname 和 lname。getter 函数fullName()连接fnamelname并返回一个新字符串。

上述代码的输出将如下所示:

inside constructor
Student {rno: 101, fname: "Sachin", lname: "Tendulkar"}
inside getter
Sachin - Tendulkar

示例

以下示例显示了如何使用表达式作为具有 getter 函数的属性名:

<script>
   let expr = 'name';
   let obj = {
      get [expr]() { return 'Sachin'; }
   };
   console.log(obj.name);
</script>

上述代码的输出如下所示:

Sachin

static 关键字

static 关键字可以应用于类中的函数。静态成员由类名引用。

示例

'use strict' 
class StaticMem { 
   static disp() { 
      console.log("Static Function called") 
   } 
} 
StaticMem.disp() //invoke the static metho

注意- 不必须包含构造函数定义。每个类默认都有一个构造函数。

执行上述代码后,将显示以下输出。

Static Function called

instanceof 运算符

如果对象属于指定的类型,则 instanceof 运算符返回 true。

示例

'use strict' 
class Person{ } 
var obj = new Person() 
var isPerson = obj instanceof Person; 
console.log(" obj is an instance of Person " + isPerson); 

执行上述代码后,将显示以下输出。

obj is an instance of Person True 

类继承

ES6 支持继承的概念。继承是程序从现有实体(此处为类)创建新实体的能力。扩展以创建新类的类称为父类/超类。新创建的类称为子类/子类

类使用“extends”关键字从另一个类继承。子类继承父类中的所有属性和方法,除了构造函数。

以下是该方法的语法。

class child_class_name extends parent_class_name

示例:类继承

'use strict' 
class Shape { 
   constructor(a) { 
      this.Area = a
   } 
} 
class Circle extends Shape { 
   disp() { 
      console.log("Area of the circle:  "+this.Area) 
   } 
} 
var obj = new Circle(223); 
obj.disp() 

上面的示例声明了一个名为 Shape 的类。Circle 类扩展了该类。由于类之间存在继承关系,因此子类,即 Circle 类,可以隐式访问其父类的属性,即 area。

执行上述代码后,将显示以下输出。

Area of Circle: 223

继承可以分类为:

  • 单一继承- 每个类最多可以从一个父类继承。

  • 多重继承- 一个类可以从多个类继承。ES6 不支持多重继承。

  • 多层继承- 考虑以下示例。

'use strict' 
class Root { 
   test() { 
      console.log("call from parent class") 
   } 
} 
class Child extends Root {} 
class Leaf extends Child   

//indirectly inherits from Root by virtue of inheritance {} 
var obj = new Leaf();
obj.test() 

Leaf 类通过多层继承从 Root 类和 Child 类派生属性。

执行上述代码后,将显示以下输出。

call from parent class

类继承和方法覆盖

方法覆盖是一种机制,子类通过该机制重新定义超类方法。以下示例说明了这一点:

'use strict' ;
class PrinterClass { 
   doPrint() { 
      console.log("doPrint() from Parent called… ");
   }
}
class StringPrinter extends PrinterClass { 
   doPrint() { 
      console.log("doPrint() is printing a string…"); 
   } 
} 
var obj = new StringPrinter(); 
obj.doPrint();

在上面的示例中,子类更改了超类函数的实现。

执行上述代码后,将显示以下输出。

doPrint() is printing a string… 

super 关键字

ES6 使子类能够调用其父类的成员数据。这是通过使用super关键字实现的。super 关键字用于引用类的直接父类。

考虑以下示例:

'use strict' 
class PrinterClass { 
   doPrint() {
      console.log("doPrint() from Parent called…") 
   } 
}  
class StringPrinter extends PrinterClass { 
   doPrint() { 
      super.doPrint() 
      console.log("doPrint() is printing a string…") 
   } 
} 
var obj = new StringPrinter() 
obj.doPrint()

StringWriter 类中的doPrint()重新定义调用其父类版本。换句话说,super 关键字用于调用父类(PrinterClass)中的 doPrint() 函数定义。

执行上述代码后,将显示以下输出。

doPrint() from Parent called. 
doPrint() is printing a string. 

ES6 - 映射和集合

ES6 引入了两种新的数据结构:映射集合。让我们详细了解它们。

Map

映射是有序的键值对集合。映射类似于对象。但是,映射和对象之间有一些区别。这些列在下面:

序号 对象 映射(Map)
1 键不能是对象类型 键可以是任何类型
2 键无序 键有序
3 不可迭代 可迭代

语法

Map 的语法如下:

let map = new Map([iterable])
let map = new Map()

示例

以下示例使用可迭代构造函数创建映射:

<script>
   let andy = {ename:"Andrel"},
      varun = {ename:"Varun"},
      prijin = {ename:"Prijin"}
   let empJobs = new Map([
   [andy,'Software Architect'],
   [varun,'Developer']]
   );
   console.log(empJobs)
</script>

上述代码的输出如下所示:

{{…} => "Software Architect", {…} => "Developer"}

检查映射的大小

size 属性可用于确定映射中存储的值的数量。

语法

检查映射大小的语法如下:

map_name.size

示例

<script>
   let daysMap = new Map();
   daysMap.set('1', 'Monday');
   daysMap.set('2', 'Tuesday');
   daysMap.set('3', 'Wednesday');
   console.log(daysMap.size);
</script>

上述代码的输出如下所示:

3

以下是一些可用于操作映射的常用方法:

序号 对象和映射
1 set(key,value)

将键和值添加到映射

2 get(key)

如果键匹配,则返回值

3 has(key)

如果存在具有指定键的元素,则返回 true;否则返回 false

4 keys()

返回一个迭代器,其中包含映射对象中每个元素的键

5 values()

返回一个迭代器,其中包含映射对象中每个元素的值

6 entries()

返回一个迭代器,其中包含 Map 中每个元素的键值对

7 delete(key)

从 Map 对象中删除指定的元素

WeakMap

WeakMap 是 map 的一个小的子集。键是弱引用的,因此它只能是非原语的。如果没有对对象键的引用,它将被垃圾回收。

  • 不可迭代
  • 每个键都是对象类型

如果键没有引用,WeakMap 将允许垃圾回收。

语法

WeakMap 的语法如下:

new WeakMap([iterable])

示例 1

<script>
   let emp = new WeakMap();
   emp.set(10,'Sachin');// TypeError as keys should be object
</script>

示例 2

<script>
   let empMap = new WeakMap();
   // emp.set(10,'Sachin');// Error as keys should be object
   let e1= {ename:'Kiran'},
      e2 = {ename:'Kannan'},
      e3 = {ename:'Mohtashim'}

   empMap.set(e1,1001);
   empMap.set(e2,1002);
   empMap.set(e3,1003);

   console.log(empMap)
   console.log(empMap.get(e2))
   console.log(empMap.has(e2))
   empMap.delete(e1)
   console.log(empMap)
</script>

上面代码的输出如下:

{{…} => 1002, {…} => 1003, {…} => 1001}
1002
true
{{…} => 1002, {…} => 1003}

集合(Set)

集合是唯一值的无序集合。此数据结构可以包含原始值和对象类型的值。

语法

Set 的语法如下:

new Set([iterable])
new Set()

示例

<script>
   let names = new Set(['A','B','C','D']);
   console.log(names)
</script>

上面代码的输出如下:

{"A", "B", "C", "D"}

检查集合的大小

Set 对象的 size 属性可用于查询 Set 中的元素数量。

语法

检查集合大小的语法如下:

set.size

示例

<script>
   let names = new Set(['A','B','C','D']);
   console.log(names.size)
</script>

上面代码的输出如下:

4

迭代集合

我们可以使用forEachfor..of循环来迭代 Set。这在下面的示例中显示:

示例

<script>
   let names= new Set(['A','B','C','D']);
   //iterate using forEach
   console.log('forEach')
   names.forEach(n=>console.log(n))
   
   console.log('for of..')
   
   //iterate using for..of
   for(let n of names){
      console.log(n)
   }
</script>  

上面代码的输出如下:

forEach
A
B
C
D
for of..
A
B
C
D

以下方法可用于操作集合:

序号 对象和映射
1 add(element)

向集合添加元素

2 has(element)

如果找到元素则返回 true;否则返回 false

3 delete(element)

从集合中删除特定元素

4 clear()

清除集合中的所有元素

WeakSet

Weakset 弱持有对象,这意味着如果对象没有被引用,则存储在 WeakSet 中的对象将被垃圾回收。WeakSet 不可迭代并且没有get方法。

<script>

   let e1 = {ename:'A'}
   let e2 ={ename:'B'}
   let e3 ={ename:'C'}

   let emps = new WeakSet();
   emps.add(e1);
   emps.add(e2)
   .add(e3);

   console.log(emps)
   console.log(emps.has(e1))
   emps.delete(e1);
   console.log(emps)
</script>

上述代码的输出如下所示:

WeakSet {{…}, {…}, {…}}
true
WeakSet {{…}, {…}}

ES6 - Promise

Promise 语法

下面提到了与 Promise 相关的语法,其中,p 是 Promise 对象,resolve 是 Promise 成功执行时应调用的函数,reject 是 Promise 遇到错误时应调用的函数。

let p = new Promise(function(resolve,reject){
   let workDone = true; // some time consuming work
      if(workDone){
      //invoke resolve function passed
      
	  resolve('success promise completed')
   }
   else{
      reject('ERROR , work could not be completed')
   }
})

示例

下面的示例展示了一个函数 add_positivenos_async(),它异步地将两个数字相加。如果传递正值,则 Promise 被 resolve;如果传递负值,则 Promise 被 reject。

<script>   
   function add_positivenos_async(n1, n2) {
      let p = new Promise(function (resolve, reject) {
         if (n1 >= 0 && n2 >= 0) {
            //do some complex time consuming work
            resolve(n1 + n2)
         }
         else
            reject('NOT_Postive_Number_Passed') 
         })
         return p;
   }

   add_positivenos_async(10, 20)
      .then(successHandler) // if promise resolved
      .catch(errorHandler);// if promise rejected

   add_positivenos_async(-10, -20)
      .then(successHandler) // if promise resolved
      .catch(errorHandler);// if promise rejected

   function errorHandler(err) {
      console.log('Handling error', err)
   }
   function successHandler(result) {
      console.log('Handling success', result)
   }

   console.log('end')
</script> 

上述代码的输出如下所示:

end
Handling success 30
Handling error NOT_Postive_Number_Passed

Promise 链式调用

当我们需要按顺序执行一系列异步任务时,可以使用Promise 链式调用。当一个 Promise 依赖于另一个 Promise 的结果时,就会进行 Promise 链式调用。这在下面的示例中有所体现。

示例

在下面的示例中,add_positivenos_async() 函数异步地将两个数字相加,如果传递负值则被 reject。当前异步函数调用的结果作为参数传递给后续的函数调用。注意每个then()方法都有一个 return 语句。

<script>   
   function add_positivenos_async(n1, n2) {
      let p = new Promise(function (resolve, reject) {
         if (n1 >= 0 && n2 >= 0) {
            //do some complex time consuming work
            resolve(n1 + n2)
         }
         else
            reject('NOT_Postive_Number_Passed')
      })
      return p;
   }

   add_positivenos_async(10,20)
   .then(function(result){
      console.log("first result",result)
      return add_positivenos_async(result,result)
   }).then(function(result){
   console.log("second result",result)
      return add_positivenos_async(result,result)
   }).then(function(result){
      console.log("third result",result)
   })

   console.log('end')
</script> 

上述代码的输出将如下所示:

end
first result 30
second result 60
third result 120

下面详细讨论 Promise 对象的一些常用方法:

promise.all()

此方法可用于聚合多个 Promise 的结果。

语法

promise.all() 方法的语法如下所示,其中,iterable 是一个可迭代对象,例如数组。

Promise.all(iterable);

示例

下面的示例执行一系列异步操作 [add_positivenos_async(10,20),add_positivenos_async(30,40),add_positivenos_async(50,60)]。当所有操作完成后,Promise 完全 resolve。

<script>   
   function add_positivenos_async(n1, n2) {
      let p = new Promise(function (resolve, reject) {
         if (n1 >= 0 && n2 >= 0) {
            //do some complex time consuming work
            resolve(n1 + n2)
         }
         else
            reject('NOT_Postive_Number_Passed')
      })

      return p;
   }
   //Promise.all(iterable)

Promise.all([add_positivenos_async(10,20),add_positivenos_async(30,40),add_positivenos_async(50,60)])
   .then(function(resolveValue){
      console.log(resolveValue[0])
      console.log(resolveValue[1])
      console.log(resolveValue[2])
      console.log('all add operations done')
   })
   .catch(function(err){
      console.log('Error',err)
   })
   console.log('end')
</script> 

上述代码的输出如下:

end
30
70
110
all add operations done

promise.race()

此函数接受一个 Promise 数组,并返回第一个完成的 Promise。

语法

promise.race() 函数的语法如下所示,其中,iterable 是一个可迭代对象,例如数组。

Promise.race(iterable)

示例

下面的示例接受一个异步操作数组 [add_positivenos_async(10,20),add_positivenos_async(30,40)]

只要任何一个加法操作完成,Promise 就会 resolve。Promise 不会等待其他异步操作完成。

<script>   
   function add_positivenos_async(n1, n2) {
      let p = new Promise(function (resolve, reject) {
         if (n1 >= 0 && n2 >= 0) {
            //do some complex time consuming work
            resolve(n1 + n2)
         } else
            reject('NOT_Postive_Number_Passed')
      })

      return p;
   }

   //Promise.race(iterable)
   Promise.race([add_positivenos_async(10,20),add_positivenos_async(30,40)])
   .then(function(resolveValue){
      console.log('one of them is done')
      console.log(resolveValue)
   }).catch(function(err){
      console.log("Error",err)
   })

   console.log('end')
</script> 

上述代码的输出如下:

end
one of them is done
30

Promise 是在 JavaScript 中实现异步编程的一种简洁方法(ES6 的新特性)。在 Promise 之前,使用回调函数来实现异步编程。让我们首先了解什么是异步编程及其使用回调函数的实现。

理解回调函数

一个函数可以作为参数传递给另一个函数。这种机制被称为回调函数。回调函数在事件处理中很有用。

以下示例将帮助我们更好地理解这个概念。

<script>   
   function notifyAll(fnSms, fnEmail) {   
      console.log('starting notification process');   
      fnSms();   
      fnEmail();   
   }   
   notifyAll(function() {   
      console.log("Sms send ..");   
   }, 
   function() {   
      console.log("email send ..");   
   });   
   console.log("End of script"); 
   //executes last or blocked by other methods   
</script> 

在上例所示的notifyAll() 方法中,通知是通过发送短信和发送电子邮件来实现的。因此,notifyAll 方法的调用者必须传递两个函数作为参数。每个函数承担单一职责,例如发送短信和发送电子邮件。

执行上述代码后,将显示以下输出。

starting notification process 
Sms send .. 
Email send .. 
End of script 

在上述代码中,函数调用是同步的。这意味着 UI 线程将等待整个通知过程完成。同步调用会变成阻塞调用。现在让我们了解非阻塞或异步调用。

理解异步回调

考虑上面的例子。

为了启用脚本,对 notifyAll() 方法执行异步或非阻塞调用。我们将使用 JavaScript 的setTimeout() 方法。此方法默认情况下是异步的。

setTimeout() 方法接受两个参数:

  • 一个回调函数。

  • 调用方法后的秒数。

在这种情况下,通知过程已被包装在超时中。因此,它将延迟两秒钟,由代码设置。notifyAll() 将被调用,主线程继续执行其他方法。因此,通知过程不会阻塞主 JavaScript 线程。

<script>   
   function notifyAll(fnSms, fnEmail) {   
      setTimeout(function() {   
         console.log('starting notification process');   
         fnSms();   
         fnEmail();   
      }, 2000);   
   }   
   notifyAll(function() {   
      console.log("Sms send ..");   
   },  
   function() {   
      console.log("email send ..");   
   });   
   console.log("End of script"); //executes first or not blocked by others   
</script>

执行上述代码后,将显示以下输出。

End of script 
starting notification process 
Sms send .. 
Email send .. 

如果有多个回调函数,代码看起来会很吓人。

<script>   
   setTimeout(function() {   
      console.log("one");   
      setTimeout(function() {   
         console.log("two");   
         setTimeout(function() {   
            console.log("three");   
         }, 1000);   
      }, 1000);   
   }, 1000);   
</script>

ES6 通过引入 Promise 的概念来解决这个问题。Promise 是“延续事件”,它们帮助你以更简洁的代码风格一起执行多个异步操作。

示例

让我们用一个例子来理解这一点。以下是相同的语法。

var promise = new Promise(function(resolve , reject) {    
   // do a thing, possibly async , then..  
   if(/*everthing turned out fine */)    resolve("stuff worked");  
   else     
   reject(Error("It broke"));  
});  
return promise;
// Give this to someone

实现 Promise 的第一步是创建一个将使用 Promise 的方法。假设在这个例子中,getSum() 方法是异步的,即它的操作不应该阻塞其他方法的执行。一旦此操作完成,它稍后将通知调用者。

以下示例(步骤 1)声明了一个 Promise 对象“var promise”。Promise 构造函数首先接收两个函数,一个是用于工作成功完成,另一个是用于发生错误。

Promise 通过使用 resolve 回调并传入结果(即 n1+n2)来返回计算结果。

步骤 1 − resolve(n1 + n2);

如果 getSum() 遇到错误或意外情况,它将调用 Promise 中的 reject 回调方法,并将错误信息传递给调用者。

步骤 2 − reject(Error("Negatives not supported"));

方法实现如下代码所示(步骤 1)。

function getSum(n1, n2) {   
   varisAnyNegative = function() {   
      return n1 < 0 || n2 < 0;   
   }   
   var promise = new Promise(function(resolve, reject) {   
      if (isAnyNegative()) {   
         reject(Error("Negatives not supported"));   
      }   
      resolve(n1 + n2)
   });   
   return promise;   
} 

第二步详细介绍了调用者的实现(步骤 2)。

调用者应该使用“then”方法,该方法接受两个回调方法——第一个用于成功,第二个用于失败。每个方法都接受一个参数,如下代码所示。

getSum(5, 6)   
.then(function (result) {   
   console.log(result);   
},   
function (error) {   
   console.log(error);   
});

执行上述代码后,将显示以下输出。

11 

由于 getSum() 的返回类型是 Promise,我们实际上可以有多个“then”语句。第一个“then”将有一个 return 语句。

getSum(5, 6)   
.then(function(result) {   
   console.log(result);   
   returngetSum(10, 20); 
   // this returns another promise   
},   
function(error) {   
   console.log(error);   
})   
.then(function(result) {   
   console.log(result);   
}, 
function(error) {   
   console.log(error);
});    

执行上述代码后,将显示以下输出。

11
30

以下示例使用 getSum() 方法发出三个 then() 调用。

<script>   
   function getSum(n1, n2) {   
      varisAnyNegative = function() {   
         return n1 < 0 || n2 < 0;   
      }   
      var promise = new Promise(function(resolve, reject) {   
         if (isAnyNegative()) {   
            reject(Error("Negatives not supported"));   
         }   
         resolve(n1 + n2);   
      });   
      return promise;   
   }   
   getSum(5, 6)   
   .then(function(result) {   
      console.log(result);   
      returngetSum(10, 20); 
      //this returns another Promise   
   },   
   function(error) {   
      console.log(error);   
   })
   .then(function(result) {   
      console.log(result);   
      returngetSum(30, 40); 
      //this returns another Promise   
   }, 
   function(error) {   
      console.log(error);   
   })   
   .then(function(result) {   
      console.log(result);   
   }, 
   function(error) {         
      console.log(error);   
   });   
   console.log("End of script ");   
</script> 

执行上述代码后,将显示以下输出。

程序首先显示“脚本结束”,然后逐个显示调用 getSum() 方法的结果。

End of script  
11 
30 
70

这表明 getSum() 是以异步方式或非阻塞方式调用的。Promise 提供了一种简洁有效的方法来处理回调函数。

ES6 - 模块

介绍

考虑这样一种情况:需要重用 JavaScript 代码的部分。ES6 通过模块的概念来解决这个问题。

模块组织了一组相关的 JavaScript 代码。模块可以包含变量和函数。模块只不过是一个文件中编写的 JavaScript 代码块。默认情况下,模块的变量和函数不可用。模块中的变量和函数应该导出,以便可以从其他文件中访问它们。ES6 中的模块仅在严格模式下工作。这意味着在模块中声明的变量或函数将不会全局可用。

导出模块

export 关键字可以用来导出模块中的组件。模块中的导出可以分为以下几类:

  • 命名导出
  • 默认导出

命名导出

命名导出由它们的名称区分。一个模块中可以有多个命名导出。模块可以使用以下语法导出选定的组件:

语法 1

//using multiple export keyword
export component1
export component2
...
...
export componentN

语法 2

或者,模块中的组件也可以使用单个 export 关键字和 {} 绑定语法导出,如下所示:

//using single export keyword

export {component1,component2,....,componentN}

默认导出

只需要导出单个值的模块可以使用默认导出。每个模块只能有一个默认导出。

语法

export default component_name

但是,一个模块可以同时具有默认导出和多个命名导出。

导入模块

为了能够使用模块,可以使用import 关键字。一个模块可以有多个import 语句

导入命名导出

导入命名导出时,相应组件的名称必须匹配。

语法

import {component1,component2..componentN} from module_name

但是,导入命名导出时,可以使用 as 关键字重命名它们。使用以下语法:

import {original_component_name as new_component_name }

可以使用星号 * 运算符将所有命名导出导入到一个对象中。

import * as variable_name from module_name

导入默认导出

与命名导出不同,默认导出可以使用任何名称导入。

语法

import any_variable_name from module_name

示例:命名导出

步骤 1 − 创建一个文件 company1.js 并添加以下代码:

let company = "TutorialsPoint"

let getCompany = function(){
   return company.toUpperCase()
}

let setCompany = function(newValue){
   company = newValue
}

export {company,getCompany,setCompany}

步骤 2 − 创建一个文件 company2.js。此文件使用 company1.js 文件中定义的组件。可以使用以下任何一种方法导入模块。

方法 1

import {company,getCompany} from './company1.js'

console.log(company)
console.log(getCompany())

方法 2

import {company as x, getCompany as y} from './company1.js'

console.log(x)
console.log(y())

方法 3

import * as myCompany from './company1.js'

console.log(myCompany.getCompany())
console.log(myCompany.company)

步骤 3 − 使用 HTML 文件执行模块

为了执行这两个模块,我们需要创建一个如下所示的 html 文件,并在活动服务器上运行它。注意,我们应该在 script 标签中使用属性 type="module"

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <meta http-equiv="X-UA-Compatible" content="ie=edge">
   <title>Document</title>
</head>
<body>
   <script src="./company2.js" type="module"></script>
</body>
</html>

上述代码的输出将如下所示:

TutorialsPoint
TUTORIALSPOINT

默认导出

步骤 1 − 创建一个文件company1.js 并添加以下代码:

let name = 'TutorialsPoint'

let company = {
   getName:function(){
      return name
   },
   setName:function(newName){
      name = newName
   }
}

export default company

步骤 2 − 创建一个文件company2.js。此文件使用 company1.js 文件中定义的组件。

import c from './company1.js'
console.log(c.getName())
c.setName('Google Inc')
console.log(c.getName())

步骤 3 − 使用HTML 文件执行模块

为了执行这两个模块,我们需要创建一个如下所示的 html 文件,并在活动服务器上运行它。注意,我们应该在 script 标签中使用属性 type="module"

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <meta http-equiv="X-UA-Compatible" content="ie=edge">
   <title>Document</title>
</head>
<body>
   <script src="./company2.js" type="module"></script>
</body>
</html>

上述代码的输出如下所示:

TutorialsPoint
Google Inc

示例:组合默认导出和命名导出

步骤 1 − 创建一个文件company1.js 并添加以下代码:

//named export
export let name = 'TutorialsPoint'

let company = {
   getName:function(){
      return name
   },
   setName:function(newName){
      name =newName
   }
}
//default export
export default company

步骤 2 − 创建一个文件company2.js。此文件使用company1.js文件中定义的组件。先导入默认导出,然后导入命名导出。

import c, {name} from './company1.js'

console.log(name)
console.log(c.getName())
c.setName("Mohtashim")
console.log(c.getName())

步骤 3 − 使用 HTML 文件执行模块

<!DOCTYPE html>
<html lang="en">
   <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
   </head>
   <body>
      <script src="company2.js" type="module"></script>
   </body>
</html>

上述代码的输出将如下所示:

TutorialsPoint
TutorialsPoint
Mohtashim

ES6 - 错误处理

编程中有三种类型的错误:语法错误、运行时错误和逻辑错误。

语法错误

语法错误,也称为解析错误,在传统的编程语言中发生在编译时,在 JavaScript 中发生在解释时。当 JavaScript 中发生语法错误时,只有与语法错误位于同一线程中的代码受影响,其他线程中的其余代码将继续执行,假设它们不依赖于包含错误的代码。

运行时错误

运行时错误,也称为异常,发生在执行期间(编译/解释之后)。异常也会影响发生它们的线程,允许其他 JavaScript 线程继续正常的执行。

逻辑错误

逻辑错误可能是最难追踪的错误类型。这些错误不是语法错误或运行时错误的结果。相反,当你在驱动脚本的逻辑中犯错并且没有得到预期的结果时,就会发生这些错误。

你无法捕获这些错误,因为这取决于你的业务需求,你想要在程序中使用哪种逻辑。

当发生运行时错误时,JavaScript 会抛出 Error 对象的实例。下表列出了 Error 对象的预定义类型。

序号 Error 对象和描述
1

EvalError

创建一个实例,表示关于全局函数eval()发生的错误。

2

RangeError

创建一个实例,表示当数值变量或参数超出其有效范围时发生的错误。

3

ReferenceError

创建一个实例,表示取消引用无效引用时发生的错误。

4

SyntaxError

创建一个实例,表示在解析代码时发生的语法错误。

5

TypeError

创建一个实例,表示当变量或参数类型无效时发生的错误。

6

URIError

创建一个实例,表示当encodeURI()decodeURI() 传递无效参数时发生的错误。

抛出异常

可以使用throw 语句引发错误(预定义或用户定义)。稍后可以捕获这些异常,并采取相应的措施。以下是相同的语法。

语法:抛出通用异常

throw new Error([message]) 
OR 
throw([message])

语法:抛出特定异常

throw new Error_name([message]) 

异常处理

异常处理通过try...catch 语句完成。当程序遇到异常时,程序将以不友好的方式终止。为了防止这种意外错误,我们可以将代码包装在 try...catch 语句中。

try 块必须后跟一个 catch 块或一个 finally 块(或两者都有)。当 try 块中发生异常时,异常将放入 e 中,并执行 catch 块。可选的 finally 块在 try/catch 后无条件执行。

以下是该方法的语法。

try {  
   // Code to run  
   [break;]  
} catch ( e ) {  
   // Code to run if an exception occurs
   [break;]  
}[ finally {  
   // Code that is always executed regardless of  
   // an exception occurring  
}]  

示例

var a = 100; 
var b = 0; 
try { 
   if (b == 0 ) { 
      throw(“Divide by zero error.”); 
   } else { 
      var c = a / b; 
   } 
} 
catch( e ) { 
   console.log("Error: " + e ); 
}

输出

执行上述代码后,将显示以下输出。

Error: Divide by zero error

注意 − 注意:你可以在一个函数中引发异常,然后可以使用try...catch 块在同一个函数或调用函数中捕获该异常。

onerror() 方法

onerror 事件处理程序是 JavaScript 中第一个用于处理错误的功能。每当页面上发生异常时,就会在 window 对象上触发 error 事件。

示例

<html> 
   <head> 
      <script type = "text/javascript"> 
         window.onerror  =  function () {  
            document.write ("An error occurred.");  
         } 
      </script> 
   </head> 

   <body> 
      <p>Click the following to see the result:</p> 
      <form> 
         <input type = "button" value = "Click Me" onclick = "myFunc();" /> 
      </form> 
   </body> 
</html> 

输出

执行上述代码后,将显示以下输出。

one error method

onerror 事件处理程序提供三条信息来识别错误的确切性质:

  • 错误信息 − 浏览器为给定错误显示的相同消息。

  • URL − 发生错误的文件。

  • 行号 − 给定 URL 中导致错误的行号。

以下示例显示如何提取此信息。

示例

<html> 
   <head> 
      <script type = "text/javascript"> 
         window.onerror  =  function (msg, url, line) {  
            document.write ("Message : " + msg );  
            document.write ("url : " + url );  
            document.write ("Line number : " + line );  
         } 
      </script> 
   </head> 

   <body> 
      <p>Click the following to see the result:</p> 
      <form> 
         <input type = "button" value = "Click Me" onclick = "myFunc();" /> 
      </form> 
   </body> 
</html> 

自定义错误

JavaScript 支持自定义错误的概念。以下示例说明了这一点。

示例 1:带有默认消息的自定义错误

function MyError(message) { 
   this.name = 'CustomError'; 
   this.message = message || 'Error raised with default message'; 
} 
try { 
   throw new MyError(); 
} catch (e) {  
   console.log(e.name);      
   console.log(e.message);  // 'Default Message' 
}

执行上述代码后,将显示以下输出。

CustomError 
Error raised with default message

示例 2:带有用户定义错误消息的自定义错误

function MyError(message) { 
   this.name = 'CustomError'; 
   this.message = message || 'Default Error Message';  
} try { 
   throw new MyError('Printing Custom Error message'); 
} 
catch (e) { 
   console.log(e.name);      
   console.log(e.message);  
}

执行上述代码后,将显示以下输出。

CustomError 
Printing Custom Error message

ES6 - 对象扩展

字符串扩展

ES6 中添加到 String 对象的一些常用方法:

序号 方法 & 描述
1 str.startsWith(searchString[, position])

确定字符串是否以指定字符串的字符开头。返回 true 或 false。

2 str.endsWith(searchString[, length])

确定字符串是否以指定字符串的字符结尾。返回 true/false。

3 str.includes(searchString[, position])

确定一个字符串是否可以在另一个字符串中找到。

4 str.repeat(count)

构造并返回一个新字符串,该字符串包含调用它的字符串的指定数量的副本,连接在一起。

正则表达式扩展

例如,在正则表达式/[A-Z]/g中,开头和结尾的 / 称为定界符。结束定界符后的任何内容都称为修饰符。ES6 添加了一个新的修饰符/g,其中g代表全局。这将匹配字符串中模式的所有实例,而不仅仅是一个。

示例

以下示例搜索并返回字符串中的所有大写字符。

<script>
   let str = 'JJavascript is Fun to Work , very Fun '
   let regex = /[A-Z]/g // g stands for global matches
   let result = str.match(regex);
   console.log(result)
</script>

上述代码的输出将如下所示:

["J", "J", "F", "W", "F"]

正则表达式搜索区分大小写。要关闭区分大小写,请使用/i 修饰符。

示例

以下示例执行不区分大小写的全局匹配。该示例将fun替换为enjoyable

<script>
   // /gi global match ignore case

   let str = 'Javascript is fun to Work , very Fun '
   let regex = /Fun/gi;
   console.log(str.replace(regex,'enjoyable'));
   console.log(str)
   console.log(str.search(regex))
</script>

上述代码的输出将如下所示:

Javascript is enjoyable to Work , very enjoyable
Javascript is fun to Work , very Fun
15

数字

ES6 中添加到Number 对象的一些常用方法:

序号 方法 & 描述
1 Number.isFinite(value)

方法确定传递的值是否为有限数字。返回 true/false。

2 Number.isNaN(value)

如果给定值为 NaN 且其类型为 Number,则返回 true;否则返回 false。

3 Number.parseFloat(string)

从给定值解析的浮点数。如果该值无法转换为数字,则返回 NaN。

4 Number.parseInt(string,[ radix])

方法解析字符串参数并返回指定基数或基数的整数。

Math

ES6 中添加到Math 对象的一些常用方法:

序号 方法 & 描述
1 Math.sign()

函数返回数字的符号,指示数字是正数、负数还是零。

2 Math.trunc()

函数通过删除任何小数位来返回数字的整数部分。

ES6 中 Array 的方法

下表重点介绍了 ES6 中的不同数组方法及其描述。

序号 方法 & 描述
1 copyWithin()

将数组的一部分浅复制到同一数组中的另一个位置,并返回它,而不会修改其长度。

2 entries()

方法返回一个新的 Array Iterator 对象,其中包含数组中每个索引的键/值对。

3 find()

方法返回数组中第一个满足提供的测试函数的元素的值。否则返回 undefined。

4 fill()

方法使用静态值填充数组从起始索引到结束索引的所有元素。它返回修改后的数组。

5 Array.of()

方法根据参数的数量和类型,从可变数量的参数创建一个新的 Array 实例。

6 Array.from()

方法从类似数组或可迭代对象创建浅拷贝。

对象

与 Object 函数相关的方法如下表所示,以及相应的描述。

序号 方法 & 描述
1 Object.is()

方法确定两个值是否相同。

2 Object.setPrototypeOf()

方法将指定对象的原型设置为另一个对象或 null。

3 Object.assign()

方法用于将一个或多个源对象的所有可枚举自身属性的值复制到目标对象。它将返回目标对象。

ES6 - Reflect API

ES6 引入了围绕元编程的新功能,元编程涉及检查或修改程序的结构,或更改语言本身的工作方式。

以下是元编程的三种形式:

  • 自省 − 自省是指程序收集有关自身的信息。一些用于自省的 JavaScript 运算符示例是typeof、instanceof等。

  • 自我修改 − 自我修改是指在运行时修改程序的结构。它涉及在运行时访问或创建新属性。换句话说,自我修改是指某些代码修改自身。

  • 拦截 − 指的是代码修改编程语言的默认行为。拦截涉及修改编程语言的语义或在运行时向程序添加新的构造。

ES6 引入了支持元编程的 Reflect 应用程序编程接口 (Reflect API) 和 Proxy API。

使用 Reflect API 进行元编程

ES6 中的 Reflect API 允许我们在运行时检查或修改程序的类、对象、属性和方法。Reflect API 提供全局 Reflect 对象,该对象具有可用于自省的静态方法。这些方法用于发现有关代码的底层信息。Reflect API 可用于构建在运行时检查和自省程序的自动化测试框架。

下面给出 Reflect 对象的一些常用方法:

序号 方法 & 描述
1 Reflect.apply()

使用 args 参数中指定的参数调用目标函数。

2 Reflect.construct()

等效于调用 new target(...args) 类对象。

3 Reflect.get()

返回属性值的函数。

4 Reflect.set()

为属性赋值的函数。返回一个布尔值,如果更新成功则为 true。

5 Reflect.has()

in 运算符作为函数。返回一个布尔值,指示是否存在自身或继承的属性。

ES6 - Proxy API

ES6 使用 Proxy 实现拦截形式的元编程。与 ReflectAPI 类似,Proxy API 是在 ES6 中实现元编程的另一种方法。Proxy 对象用于为基本操作定义自定义行为。代理对象代表实际对象执行某些操作。

下面给出与 ES6 代理相关的各种术语。

序号 方法 & 描述
1

handler

包含陷阱的占位符对象。

2

traps

提供属性访问的方法。这类似于操作系统中陷阱的概念。

1

target

代理虚拟化的对象。它通常用作代理的后端存储。

语法

下面是 Proxy API 的语法,其中,target可以是任何类型的对象,如数组、函数或另一个代理,而handler是一个其属性为函数的对象。这定义了代理的行为。

const proxy = new Proxy(target,handler)

Handler 方法

handler 对象包含 Proxy 的陷阱。所有陷阱都是可选的。如果未定义陷阱,则默认行为是将操作转发到目标。一些常见的处理程序方法如下:

序号 方法 & 描述
1 handler.apply()

函数调用的陷阱。

2 handler.construct()

new 运算符的陷阱。

3 handler.get()

获取属性值的陷阱。

4 handler.set()

设置属性值的陷阱。

5 handler.has()

in 运算符的陷阱。

ES6 - 数据验证

表单验证通常发生在服务器端,在客户端输入所有必要数据并按下“提交”按钮之后。如果客户端输入的数据不正确或丢失,服务器必须将所有数据发送回客户端,并请求使用正确的信息重新提交表单。这是一个非常冗长的过程,它会给服务器带来很大的负担。

JavaScript 提供了一种在将表单数据发送到 Web 服务器之前验证客户端计算机上表单数据的方法。表单验证通常执行两个功能。

  • 基本验证 − 首先,必须检查表单以确保所有必填字段都已填写。这只需要循环遍历表单中的每个字段并检查数据。

  • 数据格式验证 − 其次,必须检查输入数据的正确格式和值。你的代码必须包含适当的逻辑来测试数据的正确性。

示例

我们将通过一个示例来了解验证过程。这是一个简单的 html 格式表单。

<html>
 
   <head> 
      <title>Form Validation</title> 
      <script type = "text/javascript"> 
         <!--  
            // Form validation code will come here.  
            //
         --> 
      </script> 
   </head> 

   <body> 
      <form action = "/cgi-bin/test.cgi" name = "myForm" onsubmit = "return(validate());"> 
         <table cellspacing = "2" cellpadding = "2" border = "1"> 
            <tr> 
               <td align = "right">Name</td> 
               <td><input type = "text" name = "Name" /></td>
            </tr> 
            <tr> 
               <td align = "right">EMail</td> 
               <td><input type = "text" name = "EMail" /></td> 
            </tr> 
            <tr> 
               <td align = "right">Zip Code</td> 
               <td><input type = "text" name = "Zip" /></td> 
            </tr> 
            <tr> 
               <td align = "right">Country</td> 
               <td> 
                  <select name = "Country"> 
                     <option value = "-1" selected>[choose yours]</option> 
                     <option value = "1">USA</option> 
                     <option value = "2">UK</option> 
                     <option value = "3">INDIA</option> 
                  </select> 
               </td> 
            </tr> 
            <tr> 
               <td align = "right"></td> 
               <td><input type = "submit" value = "Submit" /></td> 
            </tr> 
         </table> 
      </form> 
   </body> 
   
</html> 

输出

执行上述代码后,将显示以下输出。

form validation

基本表单验证

首先让我们看看如何进行基本的表单验证。在上表中,我们在发生onsubmit事件时调用validate()来验证数据。以下代码显示了此 validate() 函数的实现。

<script type = "text/javascript"> 
   <!--  
      // Form validation code will come here. function validate() {    
         if( document.myForm.Name.value == "" ) {  
            alert( "Please provide your name!" );      
            document.myForm.Name.focus() ;      
            return false;  
         }  
         if( document.myForm.EMail.value == "" ) {  
            alert( "Please provide your Email!" );      
            document.myForm.EMail.focus() ;      
            return false; 
         }  
         if( document.myForm.Zip.value == "" ||            
         isNaN( document.myForm.Zip.value ) ||            
         document.myForm.Zip.value.length != 5 ) {  
            alert( "Please provide a zip in the format #####." );      
            document.myForm.Zip.focus() ;      
            return false;  
         }  
         if( document.myForm.Country.value == "-1" ) {  
            alert( "Please provide your country!" );      
            return false;  
         }  
         return( true );  
      }  
      //
   --> 
</script>

数据格式验证

现在我们将看到如何在将其提交到 Web 服务器之前验证输入的表单数据。

以下示例显示如何验证输入的电子邮件地址。电子邮件地址必须至少包含一个“@”符号和一个点(.)。此外,“@”不能是电子邮件地址的第一个字符,最后一个点必须至少在“@”符号之后一个字符。

示例

尝试以下用于电子邮件验证的代码。

<script type = "text/javascript"> 
   <!--  
      function validateEmail() { 
         var emailID = document.myForm.EMail.value;    
         atpos = emailID.indexOf("@");    
         dotpos = emailID.lastIndexOf(".");    
         
         if (atpos < 1 || ( dotpos - atpos < 2 )) {       
            alert("Please enter correct email ID")         
            document.myForm.EMail.focus() ;         
            return false;    
         }     
         return( true );  
      } 
      //
   --< 
</script>

ES6 - 动画

您可以使用 JavaScript 创建一个复杂的动画,其中包括但不限于以下元素:

  • 烟火
  • 淡出效果
  • 淡入或淡出
  • 页面淡入或页面淡出
  • 对象移动

在本章中,我们将了解如何使用 JavaScript 创建动画。

JavaScript 可用于根据逻辑方程或函数确定的某种模式,在页面周围移动多个 DOM 元素(<img />、<div>或任何其他 HTML 元素)。

JavaScript 提供以下函数,这些函数经常用于动画程序中。

  • setTimeout(function, duration) − 此函数在从现在起 duration 毫秒后调用该函数。

  • setInterval(function, duration) − 此函数每隔 duration 毫秒调用一次该函数。

  • clearTimeout(setTimeout_variable) − 此函数清除由 setTimeout() 函数设置的任何计时器。

JavaScript 还可以设置 DOM 对象的许多属性,包括其在屏幕上的位置。您可以设置对象的 top 和 left 属性以将其放置在屏幕上的任何位置。以下是相同的语法。

// Set distance from left edge of the screen.  
object.style.left = distance in pixels or points;    
or  
// Set distance from top edge of the screen.  
object.style.top = distance in pixels or points;

手动动画

因此,让我们使用 DOM 对象属性和 JavaScript 函数实现一个简单的动画,如下所示。以下列表包含不同的 DOM 方法。

  • 我们使用 JavaScript 函数 getElementById() 获取 DOM 对象,然后将其赋值给全局变量 imgObj

  • 我们定义了一个初始化函数 init() 来初始化 imgObj,在其中我们设置了它的 position 和 left 属性。

  • 我们在窗口加载时调用初始化函数。

  • 我们调用 moveRight() 函数将左侧距离增加 10 像素。您也可以将其设置为负值以将其移动到左侧。

示例

尝试以下示例

<html> 
   <head> 
      <title>JavaScript Animation</title> 
      <script type = "text/javascript"> 
         <!--  
            var imgObj = null; function init(){  
               imgObj = document.getElementById('myImage');
               imgObj.style.position = 'relative';     
               imgObj.style.left = '0px';   
            }     
            function moveRight(){  
               imgObj.style.left = parseInt(
               imgObj.style.left) + 10 + 'px';  
            }  
            window.onload = init;  
            //
         --> 
      </script> 
   </head> 
   
   <body> 
      <form> 
         <img id = "myImage" src = "/images/html.gif" /> 
         <p>Click button below to move the image to right</p> 
         <input type = "button" value = "Click Me" onclick = "moveRight();" /> 
      </form>
   </body>
   
</html>

自动动画

在上面的示例中,我们看到了图像如何通过每次点击向右移动。我们可以使用 JavaScript 函数 setTimeout() 自动执行此过程,如下所示。

这里我们添加了更多方法。所以,让我们看看这里有什么新内容。

  • moveRight() 函数调用 setTimeout() 函数来设置 imgObj 的位置。

  • 我们添加了一个新函数 stop() 来清除由 setTimeout() 函数设置的计时器,并将对象设置在其初始位置。

示例

尝试以下示例代码。

<html> 
   <head> 
      <title>JavaScript Animation</title> 
      <script type = "text/javascript"> 
         <!--  
            var imgObj = null; var animate ; function init(){  
               imgObj = document.getElementById('myImage');     
               imgObj.style.position = 'relative';    
               imgObj.style.left = '0px'; 
            }  
            function moveRight(){  
               imgObj.style.left = parseInt(imgObj.style.left) + 10 + 'px';    
               animate = setTimeout(moveRight,20); 
               // call moveRight in 20msec  
            }  
            function stop() {     
               clearTimeout(animate);    
               imgObj.style.left = '0px';   
            }  
            window.onload = init;  
            //
         --> 
      </script> 
   </head> 

   <body> 
      <form> 
         <img id = "myImage" src = "/images/html.gif" /> 
         <p>Click the buttons below to handle animation</p> 
         <input type="button" value="Start" onclick = "moveRight();" /> 
         <input type = "button" value="Stop" onclick = "stop();" /> 
      </form>    
   </body> 
</html>

鼠标事件的悬停效果

这是一个简单的示例,显示了鼠标事件的图像悬停效果。

让我们看看我们在以下示例中使用了什么 -

  • 加载此页面时,“if”语句检查图像对象是否存在。如果图像对象不可用,则不会执行此代码块。

  • Image() 构造函数创建并预加载一个名为 image1 的新图像对象。

  • src 属性被赋值为名为 /images/html.gif 的外部图像文件的名称。

  • 类似地,我们创建了 image2 对象,并在该对象中赋值了 /images/http.gif

  • #(井号)禁用链接,以便浏览器在单击时不会尝试转到 URL。此链接是一个图像。

  • 当用户的鼠标移动到链接上时,将触发 onMouseOver 事件处理程序;当用户的鼠标移开链接(图像)时,将触发 onMouseOut 事件处理程序。

  • 当鼠标移到图像上时,HTTP 图像会从第一张图像更改为第二张图像。当鼠标移开图像时,将显示原始图像。

  • 当鼠标移开链接时,初始图像 html.gif 将重新出现在屏幕上。

<html> 
   <head> 
      <title>Rollover with a Mouse Events</title> 
      <script type = "text/javascript"> 
         <!--  
            if(document.images) {  
               var image1 = new Image();       
               // Preload an image image1.src = "/images/html.gif";  
                  
               var image2 = new Image();       
               // Preload second image image2.src = "/images/http.gif";  
            }  
            //
         -->
      </script> 
   </head> 

   <body> 
      <p>Move your mouse over the image to see the result</p>
      <a href = "#" onMouseOver = "document.myImage.src = image2.src;"      
         onMouseOut = "document.myImage.src = image1.src;"> 
         <img name = "myImage" src = "/images/html.gif" /> 
      </a> 
   </body>
   
</html>

ES6 - 多媒体

JavaScript navigator 对象包含一个名为 plugins 的子对象。此对象是一个数组,每个安装在浏览器上的插件都有一个条目。navigator.plugins 对象仅受 Netscape、Firefox 和 Mozilla 支持。

示例

以下示例显示了如何列出安装在浏览器中的所有插件。

<html> 
   <head> 
      <title>List of Plug-Ins</title> 
   </head> 
   <body> 
      <table border = "1"> 
         <tr>
            <th>Plug-in Name</th>
            <th>Filename</th>
            <th>Description</th>
         </tr> 
         <script LANGUAGE = "JavaScript" type = "text/javascript"> 
            for (i = 0; i<navigator.plugins.length; i++) {    
               document.write("<tr><td>");  
               document.write(navigator.plugins[i].name);    
               document.write("</td><td>");  
               document.write(navigator.plugins[i].filename); 
               document.write("</td><td>");  
               document.write(navigator.plugins[i].description);    
               document.write("</td></tr>");  
            }  
         </script> 
      </table> 
   </body>
   
</html>

输出

执行上述代码后,将显示以下输出。

pluggins list

检查插件

每个插件在数组中都有一个条目。每个条目都有以下属性 -

  • name − 插件的名称。

  • filename − 加载以安装插件的可执行文件。

  • description − 开发人员提供的插件说明。

  • mimeTypes − 一个数组,其中包含插件支持的每个 MIME 类型的一个条目。

您可以在脚本中使用这些属性来查找已安装的插件,然后使用 JavaScript 播放相应的媒体文件。查看以下代码。

<html> 
   <head> 
      <title>Using Plug-Ins</title> 
   </head> 
   
   <body> 
      <script language = "JavaScript" type = "text/javascript"> 
         media  =  navigator.mimeTypes["video/quicktime"]; if (media) {  
            document.write("<embed src = 'quick.mov' height = 100 width = 100>");  
         } else {  
            document.write("<img src = 'quick.gif' height = 100 width = 100>");  
         }  
      </script> 
   </body>
</html>

注意 − 在这里,我们使用 HTML <embed> 标签来嵌入多媒体文件。

控制多媒体

让我们来看一个几乎在所有浏览器中都能工作的实际示例。

<html> 
   <head> 
      <title>Using Embeded Object</title> 
      
      <script type = "text/javascript"> 
         <!--  
            function play() {  
               if (!document.demo.IsPlaying()) {      
                  document.demo.Play();  
               }  
            }  
            function stop() {  
               if (document.demo.IsPlaying()){      
                  document.demo.StopPlay();  
               }  
            }  
            function rewind() { 
               if (document.demo.IsPlaying()){      
                  document.demo.StopPlay();  
               }  
               document.demo.Rewind();  
            } 
            //
         --> 
      </script> 
   </head> 
   <body> 
      <embed id = "demo" name = "demo"
         src = "http://www.amrood.com/games/kumite.swf" 
         width = "318" height = "300" play = "false" loop = "false"     
         pluginspage = "http://www.macromedia.com/go/getflashplayer"     
         swliveconnect = "true"> 
      </embed> 
      
      <form name = "form" id = "form" action = "#" method = "get"> 
         <input type = "button" value = "Start" onclick = "play();" /> 
         <input type = "button" value = "Stop" onclick = "stop();" /> 
         <input type = "button" value = "Rewind" onclick = "rewind();" /> 
      </form>
   </body> 
</html>

ES6 - 调试

开发人员在编码时偶尔会犯错误。程序或脚本中的错误称为bug(错误)。

查找和修复错误的过程称为debugging(调试),是开发过程的正常部分。本章介绍可以帮助您进行调试任务的工具和技术。

IE 中的错误消息

跟踪错误的最基本方法是在浏览器中打开错误信息。默认情况下,当页面上发生错误时,Internet Explorer 会在状态栏中显示一个错误图标。

Error Icon

双击此图标将带您进入一个对话框,其中显示有关已发生特定错误的信息。

由于此图标很容易被忽略,因此 Internet Explorer 提供了在每次发生错误时自动显示错误对话框的选项。

要启用此选项,请选择工具→Internet 选项→高级选项卡,然后最后选中“显示每个脚本错误的通知”复选框选项,如下面的屏幕截图所示。

Internet Options

Firefox 或 Mozilla 中的错误消息

其他浏览器(如 Firefox、Netscape 和 Mozilla)会将错误消息发送到一个名为JavaScript 控制台错误控制台的特殊窗口。要查看控制台,请选择工具→错误控制台或Web 开发

不幸的是,由于这些浏览器在发生错误时不会提供任何视觉指示,因此您必须保持控制台打开并监视脚本执行期间的错误。

Error Console

错误通知

在控制台或通过 Internet Explorer 对话框显示的错误通知是语法错误和运行时错误的结果。这些错误通知包括发生错误的行号。

如果您使用的是 Firefox,则可以单击错误控制台中提供的错误以转到脚本中包含错误的确切行。

调试脚本

有多种方法可以调试 JavaScript。以下是一些方法。

使用 JavaScript 验证器

检查 JavaScript 代码中是否存在奇怪错误的一种方法是,将其运行通过一个程序进行检查,以确保其有效且遵循该语言的官方语法规则。这些程序称为验证解析器或简称验证器,通常包含在商业 HTML 和 JavaScript 编辑器中。

JavaScript 最方便的验证器是 Douglas Crockford 的 JavaScript Lint,可在 Douglas Crockford 的 JavaScript Lint 免费获得。

只需访问网页,将您的 JavaScript(仅 JavaScript)代码粘贴到提供的文本区域中,然后单击jslint按钮。此程序将解析您的 JavaScript 代码,确保所有变量和函数定义都遵循正确的语法。它还将检查 JavaScript 语句(例如 if 和 while),以确保它们也遵循正确的格式。

向程序添加调试代码

您可以在程序中使用alert()document.write()方法来调试代码。例如,您可以编写如下内容 -

var debugging = true; var whichImage = "widget"; 
if( debugging )  
   alert( "Calls swapImage() with argument: " + whichImage ); 
   var swapStatus = swapImage( whichImage ); 
if( debugging )  
alert( "Exits swapImage() with swapStatus=" + swapStatus ); 

通过检查 alert() 的内容和顺序,您可以很容易地检查程序的运行状况。

使用 JavaScript 调试器

调试器是一个应用程序,它将脚本执行的所有方面都置于程序员的控制之下。调试器通过一个界面提供对脚本状态的细粒度控制,允许您检查和设置值以及控制执行流程。

将脚本加载到调试器后,可以逐行运行它,或者指示它在某些断点处停止。一旦执行停止,程序员就可以检查脚本及其变量的状态,以确定是否存在问题。您还可以监视变量的变化。

适用于 Mozilla 和 Netscape 浏览器的最新版 Mozilla JavaScript 调试器(代号为 Venkman)可从以下网址下载:www.hacksrus.com/~ginda/venkman

开发人员的实用技巧

您可以记住以下技巧,以减少脚本中的错误数量并简化调试过程 -

  • 使用大量的注释。注释使您可以解释编写脚本的方式以及解释代码的难点部分。

  • 始终使用缩进使代码易于阅读。缩进语句还可以使您更轻松地匹配起始和结束标签、花括号和其他 HTML 和脚本元素。

  • 编写模块化代码。尽可能将语句分组到函数中。函数允许您对相关语句进行分组,并轻松测试和重用代码部分。

  • 命名变量和函数的方式要一致。尝试使用足够长的名称,这些名称要有意义并且描述变量的内容或函数的目的。

  • 命名变量和函数时使用一致的语法。换句话说,全部小写或全部大写;如果您更喜欢 Camel-Back 表示法,则始终如一地使用它。

  • 以模块化方式测试长脚本。换句话说,不要尝试在测试任何部分之前编写整个脚本。编写一部分并使其工作,然后再添加下一部分代码。

  • 使用描述性的变量和函数名称,避免使用单字符名称。

  • 注意您的引号。请记住,引号成对地用于字符串周围,并且两个引号必须是相同风格的(单引号或双引号)。

  • 注意您的等号。不应将单个 = 用于比较目的。

  • 使用var关键字显式声明变量。

使用 Node.js 进行调试

Node.js 包含一个功能齐全的调试实用程序。要使用它,请使用 debug 参数启动 Node.js,后跟要调试的脚本的路径。

node debug test.js

将启动一个指示调试器已成功启动的提示。

要在指定位置应用断点,请在源代码中调用调试器,如下面的代码所示。

// myscript.js 
x = 5; 
setTimeout(() => { 
   debugger; 
   console.log('world'); 
}, 1000); 
console.log('hello'); 

以下是一组可以使用 Node 的单步执行命令。

序号 单步执行命令和说明
1

cont,c

继续

2

next,n

下一页

3

step,s

单步进入

4

out,o

单步跳出

5

pause

暂停代码。类似于开发者工具中的暂停

Node 的所有调试命令列表可以在此处找到 − https://node.org.cn/api/debugger.html.

Visual Studio Code 和调试

Visual Studio Code 的关键特性之一就是其强大的内置 Node.js 运行时调试支持。对于其他语言的代码调试,它提供了调试器扩展。

App Ts

调试器提供了许多功能,允许我们启动配置文件,应用/删除/禁用和启用断点、变量或启用数据检查等。

使用 VS Code 进行调试的详细指南可以在此处找到 − https://vscode.js.cn/docs/editor/debugging

ES6 - 图片地图

您可以使用 JavaScript 创建客户端图像映射。客户端图像映射通过 <img /> 标签的 usemap 属性启用,并由特殊的 <map> 和 <area> 扩展标签定义。

构成地图的图像像往常一样使用 <img /> 元素插入到页面中,只是它带有一个额外的属性 usemap。usemap 属性的值是 <map> 元素的 name 属性的值,前面带有井号或磅字符。

<map> 元素实际上创建图像的地图,通常紧跟在 <img /> 元素之后。它充当 <area /> 元素的容器,这些元素实际上定义了可点击的热点。<map> 元素只有一个属性,即 name 属性,它是标识地图的名称。这就是 <img /> 元素知道使用哪个 <map> 元素的方式。

<area> 元素指定定义每个可点击热点边界的形状和坐标。

以下代码将图像映射和 JavaScript 结合起来,当鼠标移动到图像的不同部分时,在文本框中显示消息。

<html> 
   <head> 
      <title>Using JavaScript Image Map</title>
      
      <script type="text/javascript"> 
         <!--  
            function showTutorial(name) {  
               document.myform.stage.value = name  
            }  
            //
         --> 
      </script> 
   </head> 

   <body> 
      <form name = "myform"> 
         <input type = "text" name = "stage" size = "20" /> 
      </form> 
      
      <!-- Create  Mappings --> 
      <img src = "//images/usemap.gif" alt = "HTML Map" 
         border = "0" usemap = "#tutorials"/> 
      <map name = "tutorials"> 
         <area shape = "poly" 
            coords = "74,0,113,29,98,72,52,72,38,27" 
            href = "/perl/index.htm" alt = "Perl Tutorial" 
            target = "_self" 
            onMouseOver = "showTutorial('perl')" 
            onMouseOut = "showTutorial('')"/>
         <area shape = "rect"   
            coords = "22,83,126,125"  
            href = "/html/index.htm" alt = "HTML Tutorial" target = "_self"   
            onMouseOver = "showTutorial('html')"         
            onMouseOut = "showTutorial('')"/>  
         <area shape = "circle"  coords = "73,168,32"  
            href = "/php/index.htm" alt = "PHP Tutorial" target = "_self"   
            onMouseOver = "showTutorial('php')"       
            onMouseOut = "showTutorial('')"/> 
      </map> 
   </body>
   
</html>

成功执行上述代码后将显示以下输出。您可以将鼠标光标放在图像对象上来感受地图的概念。

image map

ES6 - 浏览器兼容性

了解不同浏览器之间的差异以按照预期的方式处理每个浏览器非常重要。因此,了解您的网页正在运行的浏览器非常重要。要获取有关网页当前正在运行的浏览器的信息,请使用内置的 navigator 对象。

Navigator 属性

您可以在网页中使用多个与 Navigator 相关的属性。以下是名称及其说明的列表。

序号 属性 & 描述
1

appCodeName

此属性是一个字符串,包含浏览器的代码名称,Netscape 用于 Netscape,Microsoft Internet Explorer 用于 Internet Explorer。

2

appVersion

此属性是一个字符串,包含浏览器的版本以及其他有用信息,例如其语言和兼容性。

3

language

此属性包含浏览器使用的语言的两位字母缩写。仅限 Netscape。

4

mimTypes[]

此属性是一个数组,包含客户端支持的所有 MIME 类型。仅限 Netscape。

5

platform[]

此属性是一个字符串,包含为其编译浏览器的平台。“Win32”用于 32 位 Windows 操作系统。

6

plugins[]

此属性是一个数组,包含已安装在客户端上的所有插件。仅限 Netscape。

7

userAgent[]

此属性是一个字符串,包含浏览器的代码名称和版本。此值将发送到源服务器以识别客户端。

Navigator 方法

有几种特定于 Navigator 的方法。以下是它们的名称和说明的列表。

序号 方法和说明
1

javaEnabled()

此方法确定 JavaScript 是否在客户端启用。如果启用了 JavaScript,则此方法返回 true;否则,返回 false。

2

plugings.refresh

此方法使新安装的插件可用,并使用所有新的插件名称填充 plugins 数组。仅限 Netscape

3

preference(name,value)

此方法允许签名脚本获取和设置一些 Netscape 首选项。如果省略第二个参数,则此方法将返回指定首选项的值;否则,它将设置该值。仅限 Netscape

4

taintEnabled()

如果启用了数据污染,此方法返回 true;否则返回 false

浏览器检测

以下 JavaScript 代码可用于找出浏览器的名称,然后相应地向用户提供 HTML 页面。

<html> 
   <head> 
      <title>Browser Detection Example</title> 
   </head> 

   <body> 
      <script type = "text/javascript"> 
         <!--  
            var userAgent   = navigator.userAgent;  
            var opera       = (userAgent.indexOf('Opera') 
            ! = -1); var ie          = (userAgent.indexOf('MSIE') 
            != -1); var gecko        = (userAgent.indexOf('Gecko') 
            ! = -1); var netscape    = (userAgent.indexOf('Mozilla') 
            ! = -1); var version     = navigator.appVersion;  

            if (opera) {  
               document.write("Opera based browser");    
               // Keep your opera specific URL here.  
            } else if (gecko) {
               document.write("Mozilla based browser");   
               // Keep your gecko specific URL here.  
            } else if (ie) {   
               document.write("IE based browser");    
               // Keep your IE specific URL here.  
            } else if (netscape) {  
               document.write("Netscape based browser");    
               // Keep your Netscape specific URL here.  
            } else {  
               document.write("Unknown browser");  
            }   
            // You can include version to along with any above condition. 
            document.write("<br /> Browser version info : " + version );  
            //
         --> 
      </script> 
   </body> 
   
</html>

执行上述代码后,将显示以下输出。

Mozilla based browser  
Browser version info : 5.0 

(Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36

ES7 - 新特性

本章介绍 ES7 的新特性。

指数运算符

ES7 引入了一种新的数学运算符,称为指数运算符。此运算符类似于使用 Math.pow() 方法。指数运算符由双星号 ** 表示。此运算符只能与数值一起使用。使用指数运算符的语法如下所示 −

语法

指数运算符的语法如下所示 −

base_value ** exponent_value

示例

以下示例使用 Math.pow() 方法和 指数运算符计算数字的指数。

<script>
   let base = 2
   let exponent = 3
   console.log('using Math.pow()',Math.pow(base,exponent))
   console.log('using exponentiation operator',base**exponent)
</script>

上述代码片段的输出如下所示 −

using Math.pow() 8
using exponentiation operator 8

Array Includes

ES7 中引入的 Array.includes() 方法有助于检查数组中是否存在元素。在 ES7 之前,可以使用 Array 类的 indexof() 方法来验证数组中是否存在值。如果找到数据,indexof() 返回数组中元素第一次出现的索引,否则如果数据不存在,则返回 -1。

Array.includes() 方法接受一个参数,检查作为参数传递的值是否存在于数组中。如果找到该值,此方法返回 true,否则如果该值不存在,则返回 false。使用 Array.includes() 方法的语法如下所示 −

语法

Array.includes(value)

Array.includes(value,start_index)

第二种语法检查值是否存在于指定的索引中。

示例

以下示例声明一个数组 marks 并使用 Array.includes() 方法来验证数组中是否存在值。

<script>
   let marks = [50,60,70,80]
   //check if 50 is included in array
   if(marks.includes(50)){
      console.log('found element in array')
   }else{
      console.log('could not find element')
   }

   // check if 50 is found from index 1
   if(marks.includes(50,1)){ //search from index 1
      console.log('found element in array')
   }else{
      console.log('could not find element')
   }

   //check Not a Number(NaN) in an array
   console.log([NaN].includes(NaN))

   //create an object array
   let user1 = {name:'kannan'},
   user2 = {name:'varun'},
   user3={name:'prijin'}
   let users = [user1,user2]

   //check object is available in array
   console.log(users.includes(user1))
   console.log(users.includes(user3))
</script>

上述代码的输出将如下所示:

found element in array
could not find element
true
true
false

ES8 - 新特性

本章重点介绍 ES8 的新特性。

填充字符串

ES8 引入了两个字符串处理函数来填充字符串。这些函数可用于在字符串值的开头和结尾添加空格或任何所需的字符集。

String.padStart()

此函数使用给定的输入字符串从开头重复填充当前字符串,直到当前字符串达到给定的长度。padStart() 函数的语法如下所示 −

语法

string_value.padStart(targetLength [, padString])

padStart() 函数接受两个参数,如下所示 −

  • targetLength − 一个数值,表示填充后字符串的目标长度。如果此参数的值小于或等于字符串的现有长度,则按原样返回字符串值。

  • padString − 这是一个可选参数。此参数指定应使用哪些字符来填充字符串。如果未将任何值传递给此参数,则字符串值将用空格填充。

示例

以下示例声明一个字符串变量 product_cost。该变量将从左侧用零填充,直到字符串的总长度为七。该示例还说明了如果未将任何值传递给第二个参数,padStart() 函数的行为。

<script>

   //pad the String with 0
   let product_cost = '1699'.padStart(7,0)
   console.log(product_cost)
   console.log(product_cost.length)

   //pad the String with blank spaces
   let product_cost1 = '1699'.padStart(7)
   console.log(product_cost1)
   console.log(product_cost1.length)
</script>

上述代码的输出将如下所示:

0001699
7
1699
7

String.padEnd()

此函数使用给定的输入字符串从结尾重复填充当前字符串,直到当前字符串达到指定的长度。

padEnd() 函数的语法如下所示 −

语法

string_value.padEnd(targetLength [, padString])

padEnd() 函数接受两个参数 −

  • targetLength − 一个数值,表示填充后字符串的目标长度。如果此参数的值小于或等于字符串的现有长度,则按原样返回字符串值。

  • padString − 这是一个可选参数。此参数指定应使用哪些字符来填充字符串。如果未将任何值传递给此参数,则字符串值将用空格填充。

示例

以下示例声明一个字符串变量 product_cost。该变量将从右侧用零填充,直到字符串的总长度为七。该示例还说明了如果未将任何值传递给第二个参数,padStart() 函数的行为。

<script>

   //pad the string with x
   let product_cost = '1699'.padEnd(7,'x')
   console.log(product_cost)
   console.log(product_cost.length)
   
   //pad the string with spaces
   let product_cost1 = '1699'.padEnd(7)
   console.log(product_cost1)
   console.log(product_cost1.length)
</script>

上述代码的输出如下所示:

1699xxx
7
1699
7

尾随逗号

尾随逗号只是列表中最后一项后的逗号。尾随逗号也称为最终逗号。

尾随逗号和数组

使用 Array.prototype.forEach 循环时,将跳过数组中的尾随逗号。

示例

以下示例使用 foreach 循环迭代带有尾随逗号的数组。

<script>

   let marks = [100,90,80,,]
   console.log(marks.length)
   console.log(marks)
   marks.forEach(function(e){ //ignores empty value in array
      console.log(e)
   })
</script>

上述代码的输出将如下所示:

4
[100, 90, 80, empty]
100
90
80

尾随逗号和函数调用

在定义或调用函数时,作为参数传递的尾随逗号将被 JavaScript 运行时引擎忽略。但是,有两个例外 −

  • 仅包含逗号的函数定义或调用将导致 SyntaxError。例如,以下代码段将引发错误 −

function test(,){} // SyntaxError: missing formal parameter
(,)=>{}; //SyntaxError: expected expression, got ','
test(,) //SyntaxError: expected expression, got ','
  • 尾随逗号不能与 rest 参数一起使用。

function test(...arg1,){} // SyntaxError: parameter after rest parameter
(...arg1,)=>{} // SyntaxError: expected closing parenthesis, got ','

示例

以下示例声明一个在参数列表中带有尾随逗号的函数。

<script>

   function sumOfMarks(marks,){ // trailing commas are ignored
      let sum=0;
      marks.forEach(function(e){
         sum+=e;
      })
      return sum;
   }

   console.log(sumOfMarks([10,20,30]))
   console.log(sumOfMarks([1,2,3],))// trailing comma is ignored
</script>

上述代码的输出如下所示 −

60
6

Object:entries() 和 values()

ES8 向内置 Object 类型引入了以下新方法 −

  • Object.entries − Object.entries() 方法可用于访问对象的全部属性。

  • Object.values() − Object.values() 方法可用于访问对象所有属性的值。

  • Object.getOwnPropertyDescriptors() − 此方法返回一个对象,其中包含对象的全部自有属性描述符。如果对象没有任何属性,则可能会返回一个空对象。

示例

<script>
   const student ={
      firstName:'Kannan',
      lastName:'Sudhakaran'
   }
   console.log(Object.entries(student))
   console.log(Object.values(student))
</script>

上述代码的输出如下:

[
["firstName", "Kannan"],
["lastName", "Sudhakaran"],
]
["Kannan", "Sudhakaran"]

示例

<script>
   const marks = [10,20,30,40]
   console.log(Object.entries(marks))
   console.log(Object.values(marks))
</script>

上述代码的输出将如下所示:

["0", 10],
["1", 20],
["2", 30],
["3", 40]
]
[10, 20, 30, 40]

示例

<script>
   const student = {
      firstName : 'Mohtashim',
      lastName: 'Mohammad',
      get fullName(){
         return this.firstName + ':'+ this.lastName
      }
   }
   console.log(Object.getOwnPropertyDescriptors(student))
</script>

上述代码的输出如下所示:

{firstName: {value: "Mohtashim", writable: true, enumerable: true, configurable: true}
fullName: {get: ƒ, set: undefined, enumerable: true, configurable: true}
lastName: {value: "Mohammad", writable: true, enumerable: true, configurable: true}
}

Async 和 Await

Async/Await 是 ES8 中一项非常重要的特性。它是 JavaScript 中 Promise 的语法糖。await 关键字与 promise 一起使用。此关键字可用于暂停函数的执行,直到 promise 完成为止。如果 promise 已解决,则 await 关键字返回 promise 的值,而如果 promise 已拒绝,则抛出错误。await 函数只能在标记为 async 的函数内使用。使用 async 关键字声明的函数始终返回一个 promise。

语法

带有 await 的 async 函数的语法如下所示 −

async function function_name(){
   let result_of_functionCall = await longRunningMethod();
}
//invoking async function

function_name().then(()=>{})
   .catch(()=>{})

考虑一个示例,该示例具有一个异步函数,该函数需要两秒钟才能执行并返回一个字符串值。该函数可以通过两种方式调用,如下所示

  • 使用 promise.then()
  • 使用 aync/await。

以下代码显示了使用传统的 ES6 语法 - promise.then() 调用异步函数

<script>
   function fnTimeConsumingWork(){
      return new Promise((resolve,reject)=>{
         setTimeout(() => {
            resolve('response is:2 seconds have passed')
         }, 2000);
      })
   }

   fnTimeConsumingWork().then(resp=>{
      console.log(resp)
   })
   console.log('end of script')
</script>

上述代码的输出如下:

end of script
response is:2 seconds have passed

以下代码显示了使用 ES8 语法 - async/await 调用异步函数的更清晰的方法

<script>
   function fnTimeConsumingWork(){
      return new Promise((resolve,reject)=>{
         setTimeout(() => {
            resolve('response is:2 seconds have passed')
         }, 2000);
      })
   }
   async function my_AsyncFunc(){
      console.log('inside my_AsyncFunc')
      const response = await fnTimeConsumingWork();// clean and readable
      console.log(response)
   }
   my_AsyncFunc();
   console.log("end of script")
</script>

上述代码的输出如下所示:

inside my_AsyncFunc
end of script
response is:2 seconds have passed

使用 Async/await 进行 Promise 链式调用

以下示例使用 async/await 语法实现 Promise 链式调用。

在此示例中,add_positivenos_async() 函数异步添加两个数字,如果传递负值则拒绝。当前异步函数调用的结果将作为参数传递给后续的函数调用。

<script>
   function add_positivenos_async(n1, n2) {
      let p = new Promise(function (resolve, reject) {
         if (n1 >= 0 && n2 >= 0) {
            //do some complex time consuming work
            resolve(n1 + n2)
         } else
            reject('NOT_Postive_Number_Passed')
      })
      return p;
   }
   async function addInSequence() {
      let r1 = await add_positivenos_async(10, 20)
      console.log("first result", r1);
      let r2 = await add_positivenos_async(r1, r1);
      console.log("second result", r2)
      let r3 = await add_positivenos_async(r2, r2);
      console.log("third result", r3)
      return "Done Sequence"
   }
   addInSequence().then((r)=>console.log("Async :",r));
   console.log('end')
</script>

上述代码的输出将如下所示 −

end
first result 30
second result 60
third result 120
Async : Done Sequence

ES9 - 新特性

在这里,我们将学习 ES9 的新特性。让我们从了解异步生成器开始。

异步生成器和迭代

可以使用 async 关键字使异步生成器变为异步。定义异步生成器的 语法如下所示 −

async function* generator_name() {
   //statements
}

示例

以下示例显示了一个异步生成器,它在每次调用生成器的 next() 方法时返回 Promise。

<script>
   async function* load(){
      yield await Promise.resolve(1);
      yield await Promise.resolve(2);
      yield await Promise.resolve(3);
   }
   
   let l = load();
   l.next().then(r=>console.log(r))
   l.next().then(r=>console.log(r))
   l.next().then(r=>console.log(r))
   l.next().then(r=>console.log(r))
</script>

上述代码的输出如下:

{value: 1, done: false}
{value: 2, done: false}
{value: 3, done: false}
{value: undefined, done: true}

for await of 循环

异步迭代器不能使用传统的 for..of 循环语法进行迭代,因为它们返回 promise。ES9 引入了 for await of 循环来支持 异步迭代

for await of 循环的语法如下所示:

  • 每次迭代,一个不同属性的值都会赋值给变量,并且可以使用 const、let 或 var 声明变量。

  • iterable − 要迭代其可迭代属性的对象。
for await (variable of iterable) {
   statement
}

示例

以下示例演示了如何使用 for await of 循环迭代异步生成器。

<script>
   async function* load(){
      yield await Promise.resolve(1);
      yield await Promise.resolve(2);
      yield await Promise.resolve(3);
   }

   async function test(){
      for await (const val of load()){
         console.log(val)
      }
   }
   test();
   console.log('end of script')
</script>

上述代码的输出将如下所示:

end of script
1
2
3

示例

以下示例使用 for await of 循环迭代数组。

<script>
   async function fntest(){
      for await (const val of [10,20,30,40]){
         console.log(val)
      }
   }
   fntest();
   console.log('end of script')
</script>

上述代码的输出如下:

end of script
10
20
30
40

剩余/展开属性

ES9 支持在对象中使用剩余和展开运算符。

示例:对象和剩余运算符

以下示例演示了如何在对象中使用剩余运算符。student 对象的 age 属性的值被复制到 age 变量中,而其余属性的值使用剩余语法 `...` 复制到 other 变量中。

<script>
   const student = {
      age:10,
      height:5,
      weight:50
   }
   const {age,...other} = student;
   console.log(age)
   console.log(other)
</script>

上述代码的输出将如下所示:

10
{height: 5, weight: 50}

示例:对象和展开运算符

展开运算符可以用于组合多个对象或克隆对象。以下示例对此进行了演示。

<script>
   //spread operator
   const obj1 = {a:10,b:20}
   const obj2={c:30}
   //clone obj1
   const clone_obj={...obj1}
   //combine obj1 and obj2
   const obj3 = {...obj1,...obj2}
   console.log(clone_obj)
   console.log(obj3)
</script>

上述代码的输出将如下所示:

{a: 10, b: 20}
{a: 10, b: 20, c: 30}

Promise: finally()

无论 Promise 的结果如何,finally() 都会在 Promise 完成时执行。此函数返回一个 Promise。它可以用于避免在 Promise 的 then()catch() 处理程序中重复代码。

语法

以下是 finally() 函数的语法。

promise.finally(function() {
});
promise.finally(()=> {
});

示例

以下示例声明了一个异步函数,该函数在延迟 3 秒后返回正数的平方。如果传递负数,则该函数会抛出错误。无论 Promise 被拒绝还是已解决,finally 块中的语句都会执行。

<script>
   let asyncSquareFn = function(n1){
      return new Promise((resolve,reject)=>{
         setTimeout(()=>{
            if(n1>=0){
               resolve(n1*n1)
            }
            else reject('NOT_POSITIVE_NO')
         },3000)
      })
   }
   console.log('Start')

   asyncSquareFn(10)//modify to add -10
   .then(result=>{
      console.log("result is",result)
   }).catch(error=>console.log(error))
   .finally(() =>{
      console.log("inside finally")
      console.log("executes all the time")
   })

   console.log("End");
</script>

以上代码的输出将如下所示

Start
End
//after 3 seconds
result is 100
inside finally
executes all the time

模板字面量修订

从 ES7 开始,标记模板符合以下转义序列的规则:

  • Unicode 转义序列使用 "\u" 表示,例如 \u2764\uFE0F

  • Unicode 代码点转义序列使用 "\u{}" 表示,例如 \u{2F}

  • 十六进制转义序列使用 "\x" 表示,例如 \xA8

  • 八进制字面量转义序列使用 "" 表示,后跟一个或多个数字,例如 \125

在 ES2016 及更早版本中,如果带标记函数使用无效的转义序列,则会抛出语法错误,如下所示:

//tagged function with an invalid unicode sequence
myTagFn`\unicode1`
// SyntaxError: malformed Unicode character escape sequence

但是,与早期版本不同,ES9 将无效的 Unicode 序列解析为 undefined,并且不会抛出错误。以下示例对此进行了演示:

<script>
   function myTagFn(str) {
      return { "parsed": str[0] }
   }
   let result1 =myTagFn`\unicode1` //invalid unicode character
   console.log(result1)
   let result2 =myTagFn`\u2764\uFE0F`//valid unicode
   console.log(result2)
</script>

上述代码的输出将如下所示:

{parsed: undefined}
{parsed: "❤️"}

原始字符串

ES9 引入了一个特殊属性 raw,它在标记函数的第一个参数中可用。此属性允许您访问原始字符串,就像输入时一样,无需处理转义序列。

示例

<script>
   function myTagFn(str) {
      return { "Parsed": str[0], "Raw": str.raw[0] }
   }
   let result1 =myTagFn`\unicode`
   console.log(result1)

   let result2 =myTagFn`\u2764\uFE0F`
   console.log(result2)
</script>

上述代码的输出如下:

{Parsed: undefined, Raw: "\unicode"}
{Parsed: "❤️", Raw: "\u2764\uFE0F"}

正则表达式特性

在正则表达式中,点运算符或句点用于匹配单个字符。. 点运算符跳过换行符,例如 \n、\r,如下例所示:

console.log(/Tutorials.Point/.test('Tutorials_Point')); //true
console.log(/Tutorials.Point/.test('Tutorials\nPoint')); //false
console.log(/Tutorials.Point/.test('Tutorials\rPoint')); //false

正则表达式模式表示为 / regular_expression /。test() 方法采用字符串参数并搜索正则表达式模式。在上面的示例中,test() 方法搜索以 Tutorials 开头、后跟任何单个字符并以 Point 结尾的模式。如果我们在 Tutorials 和 Point 之间的输入字符串中使用 \n\r,则 test() 方法将返回 false。

true
false
false

ES9 引入了一个新的标志 - DotAllFlag (\s),可与 Regex 一起使用以匹配行终止符和表情符号。以下示例对此进行了演示:

console.log(/Tutorials.Point/s.test('Tutorials\nPoint'));
console.log(/Tutorials.Point/s.test('Tutorials\rPoint'));

上述代码的输出如下所示:

true
true

命名捕获组

在 ES9 之前,捕获组是通过索引访问的。ES9 允许我们为捕获组分配名称。其语法如下所示:

(?<Name1>pattern1)

示例

const birthDatePattern = /(?<myYear>[0-9]{4})-(?<myMonth>[0-9]{2})/;
const birthDate = birthDatePattern.exec('1999-04');
console.log(birthDate.groups.myYear);
console.log(birthDate.groups.myMonth);

上述代码的输出如下所示:

1999
04
广告