其他分享
首页 > 其他分享> > js前置知识

js前置知识

作者:互联网

什么是 JavaScript 语言?

JavaScript 是一种轻量级的脚本语言。所谓“脚本语言”(script language),指的是它不具备开发操作系统的能力,而是只用来编写控制其他大型应用程序(比如浏览器)的“脚本”。

JavaScript 也是一种嵌入式(embedded)语言。它本身提供的核心语法不算很多,只能用来做一些数学和逻辑运算。JavaScript 本身不提供任何与 I/O(输入/输出)相关的 API,都要靠宿主环境(host)提供,所以 JavaScript 只合适嵌入更大型的应用程序环境,去调用宿主环境提供的底层 API。

目前,已经嵌入 JavaScript 的宿主环境有多种,最常见的环境就是浏览器,另外还有服务器环境,也就是 Node 项目。

从语法角度看,JavaScript 语言是一种“对象模型”语言。各种宿主环境通过这个模型,描述自己的功能和操作接口,从而通过 JavaScript 控制这些功能。但是,JavaScript 并不是纯粹的“面向对象语言”,还支持其他编程范式(比如函数式编程)。这导致几乎任何一个问题,JavaScript 都有多种解决方法。阅读本书的过程中,你会诧异于 JavaScript 语法的灵活性。

JavaScript 的核心语法部分相当精简,只包括两个部分:基本的语法构造(比如操作符、控制结构、语句)和标准库(就是一系列具有各种功能的对象比如ArrayDateMath等)。除此之外,各种宿主环境提供额外的 API(即只能在该环境使用的接口),以便 JavaScript 调用。以浏览器为例,它提供的额外 API 可以分成三大类。

如果宿主环境是服务器,则会提供各种操作系统的 API,比如文件操作 API、网络通信 API等等。这些你都可以在 Node 环境中找到。

本书主要介绍 JavaScript 核心语法和浏览器网页开发的基本知识,不涉及 Node。全书可以分成以下四大部分。

为什么学习 JavaScript?

JavaScript 语言有一些显著特点,使得它非常值得学习。它既适合作为学习编程的入门语言,也适合当作日常开发的工作语言。它是目前最有希望、前途最光明的计算机语言之一。

操控浏览器的能力

JavaScript 的发明目的,就是作为浏览器的内置脚本语言,为网页开发者提供操控浏览器的能力。它是目前唯一一种通用的浏览器脚本语言,所有浏览器都支持。它可以让网页呈现各种特殊效果,为用户提供良好的互动体验。

目前,全世界几乎所有网页都使用 JavaScript。如果不用,网站的易用性和使用效率将大打折扣,无法成为操作便利、对用户友好的网站。

对于一个互联网开发者来说,如果你想提供漂亮的网页、令用户满意的上网体验、各种基于浏览器的便捷功能、前后端之间紧密高效的联系,JavaScript 是必不可少的工具。

广泛的使用领域

近年来,JavaScript 的使用范围,慢慢超越了浏览器,正在向通用的系统语言发展。

(1)浏览器的平台化

随着 HTML5 的出现,浏览器本身的功能越来越强,不再仅仅能浏览网页,而是越来越像一个平台,JavaScript 因此得以调用许多系统功能,比如操作本地文件、操作图片、调用摄像头和麦克风等等。这使得 JavaScript 可以完成许多以前无法想象的事情。

(2)Node

Node 项目使得 JavaScript 可以用于开发服务器端的大型项目,网站的前后端都用 JavaScript 开发已经成为了现实。有些嵌入式平台(Raspberry Pi)能够安装 Node,于是 JavaScript 就能为这些平台开发应用程序。

(3)数据库操作

JavaScript 甚至也可以用来操作数据库。NoSQL 数据库这个概念,本身就是在 JSON(JavaScript Object Notation)格式的基础上诞生的,大部分 NoSQL 数据库允许 JavaScript 直接操作。基于 SQL 语言的开源数据库 PostgreSQL 支持 JavaScript 作为操作语言,可以部分取代 SQL 查询语言。

(4)移动平台开发

JavaScript 也正在成为手机应用的开发语言。一般来说,安卓平台使用 Java 语言开发,iOS 平台使用 Objective-C 或 Swift 语言开发。许多人正在努力,让 JavaScript 成为各个平台的通用开发语言。

PhoneGap 项目就是将 JavaScript 和 HTML5 打包在一个容器之中,使得它能同时在 iOS 和安卓上运行。Facebook 公司的 React Native 项目则是将 JavaScript 写的组件,编译成原生组件,从而使它们具备优秀的性能。

Mozilla 基金会的手机操作系统 Firefox OS,更是直接将 JavaScript 作为操作系统的平台语言,但是很可惜这个项目没有成功。

(5)内嵌脚本语言

越来越多的应用程序,将 JavaScript 作为内嵌的脚本语言,比如 Adobe 公司的著名 PDF 阅读器 Acrobat、Linux 桌面环境 GNOME 3。

(6)跨平台的桌面应用程序

Chromium OS、Windows 8 等操作系统直接支持 JavaScript 编写应用程序。Mozilla 的 Open Web Apps 项目、Google 的 Chrome App 项目、GitHub 的 Electron 项目、以及 TideSDK 项目,都可以用来编写运行于 Windows、Mac OS 和 Android 等多个桌面平台的程序,不依赖浏览器。

易学性

相比学习其他语言,学习 JavaScript 有一些有利条件。

(1)学习环境无处不在

只要有浏览器,就能运行 JavaScript 程序;只要有文本编辑器,就能编写 JavaScript 程序。这意味着,几乎所有电脑都原生提供 JavaScript 学习环境,不用另行安装复杂的 IDE(集成开发环境)和编译器。

(2)简单性

相比其他脚本语言(比如 Python 或 Ruby),JavaScript 的语法相对简单一些,本身的语法特性并不是特别多。而且,那些语法中的复杂部分,也不是必需要学会。你完全可以只用简单命令,完成大部分的操作。

(3)与主流语言的相似性

JavaScript 的语法很类似 C/C++ 和 Java,如果学过这些语言(事实上大多数学校都教),JavaScript 的入门会非常容易。

必须说明的是,虽然核心语法不难,但是 JavaScript 的复杂性体现在另外两个方面。

首先,它涉及大量的外部 API。JavaScript 要发挥作用,必须与其他组件配合,这些外部组件五花八门,数量极其庞大,几乎涉及网络应用的各个方面,掌握它们绝非易事。

其次,JavaScript 语言有一些设计缺陷。某些地方相当不合理,另一些地方则会出现怪异的运行结果。学习 JavaScript,很大一部分时间是用来搞清楚哪些地方有陷阱。Douglas Crockford 写过一本有名的书,名字就叫《JavaScript: The Good Parts》,言下之意就是这门语言不好的地方很多,必须写一本书才能讲清楚。另外一些程序员则感到,为了更合理地编写 JavaScript 程序,就不能用 JavaScript 来写,而必须发明新的语言,比如 CoffeeScript、TypeScript、Dart 这些新语言的发明目的,多多少少都有这个因素。

尽管如此,目前看来,JavaScript 的地位还是无法动摇。加之,语言标准的快速进化,使得 JavaScript 功能日益增强,而语法缺陷和怪异之处得到了弥补。所以,JavaScript 还是值得学习,况且它的入门真的不难。

强大的性能

JavaScript 的性能优势体现在以下方面。

(1)灵活的语法,表达力强。

JavaScript 既支持类似 C 语言清晰的过程式编程,也支持灵活的函数式编程,可以用来写并发处理(concurrent)。这些语法特性已经被证明非常强大,可以用于许多场合,尤其适用异步编程。

JavaScript 的所有值都是对象,这为程序员提供了灵活性和便利性。因为你可以很方便地、按照需要随时创造数据结构,不用进行麻烦的预定义。

JavaScript 的标准还在快速进化中,并不断合理化,添加更适用的语法特性。

(2)支持编译运行。

JavaScript 语言本身,虽然是一种解释型语言,但是在现代浏览器中,JavaScript 都是编译后运行。程序会被高度优化,运行效率接近二进制程序。而且,JavaScript 引擎正在快速发展,性能将越来越好。

此外,还有一种 WebAssembly 格式,它是 JavaScript 引擎的中间码格式,全部都是二进制代码。由于跳过了编译步骤,可以达到接近原生二进制代码的运行速度。各种语言(主要是 C 和 C++)通过编译成 WebAssembly,就可以在浏览器里面运行。

(3)事件驱动和非阻塞式设计。

JavaScript 程序可以采用事件驱动(event-driven)和非阻塞式(non-blocking)设计,在服务器端适合高并发环境,普通的硬件就可以承受很大的访问量。

JavaScript 的基本语法

语句

JavaScript 程序的执行单位为行(line),也就是一行一行地执行。一般情况下,每一行就是一个语句。

语句(statement)是为了完成某种任务而进行的操作,比如下面就是一行赋值语句。

var a = 1 + 3;

这条语句先用var命令,声明了变量a,然后将1 + 3的运算结果赋值给变量a

1 + 3叫做表达式(expression),指一个为了得到返回值的计算式。语句和表达式的区别在于,前者主要为了进行某种操作,一般情况下不需要返回值;后者则是为了得到返回值,一定会返回一个值。凡是 JavaScript 语言中预期为值的地方,都可以使用表达式。比如,赋值语句的等号右边,预期是一个值,因此可以放置各种表达式。

语句以分号结尾,一个分号就表示一个语句结束。多个语句可以写在一行内。

var a = 1 + 3 ; var b = 'abc';

分号前面可以没有任何内容,JavaScript 引擎将其视为空语句。

;;;

上面的代码就表示3个空语句。

表达式不需要分号结尾。一旦在表达式后面添加分号,则 JavaScript 引擎就将表达式视为语句,这样会产生一些没有任何意义的语句。

1 + 3;
'abc';

上面两行语句只是单纯地产生一个值,并没有任何实际的意义。

变量

概念

变量是对“值”的具名引用。变量就是为“值”起名,然后引用这个名字,就等同于引用这个值。变量的名字就是变量名。

var a = 1;

上面的代码先声明变量a,然后在变量a与数值1之间建立引用关系,称为将数值1“赋值”给变量a。以后,引用变量名a就会得到数值1。最前面的var,是变量声明命令。它表示通知解释引擎,要创建一个变量a

注意,JavaScript 的变量名区分大小写,Aa是两个不同的变量。

变量的声明和赋值,是分开的两个步骤,上面的代码将它们合在了一起,实际的步骤是下面这样。

var a;
a = 1;

如果只是声明变量而没有赋值,则该变量的值是undefinedundefined是一个特殊的值,表示“无定义”。

var a;
a // undefined

如果变量赋值的时候,忘了写var命令,这条语句也是有效的。

var a = 1;
// 基本等同
a = 1;

但是,不写var的做法,不利于表达意图,而且容易不知不觉地创建全局变量,所以建议总是使用var命令声明变量。

如果一个变量没有声明就直接使用,JavaScript 会报错,告诉你变量未定义。

x// ReferenceError: x is not defined

上面代码直接使用变量x,系统就报错,告诉你变量x没有声明。

可以在同一条var命令中声明多个变量。

var a, b;

JavaScript 是一种动态类型语言,也就是说,变量的类型没有限制,变量可以随时更改类型。

var a = 1;a = 'hello';php/python/js 灵活的动态语言(java/c++静态语言)

上面代码中,变量a起先被赋值为一个数值,后来又被重新赋值为一个字符串。第二次赋值的时候,因为变量a已经存在,所以不需要使用var命令。

如果使用var重新声明一个已经存在的变量,是无效的。

var x = 1;var x;x // 1

上面代码中,变量x声明了两次,第二次声明是无效的。

但是,如果第二次声明的时候还进行了赋值,则会覆盖掉前面的值。

var x = 1;var x = 2;// 等同于var x = 1;var x;x = 2;

变量提升

JavaScript 引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成的结果,就是所有的变量的声明语句,都会被提升到代码的头部,这就叫做变量提升(hoisting)。

var a;console.log(a);a = 1

上面代码首先使用console.log方法,在控制台(console)显示变量a的值。这时变量a还没有声明和赋值,所以这是一种错误的做法,但是实际上不会报错。因为存在变量提升,真正运行的是下面的代码。

var a;console.log(a);a = 1;

最后的结果是显示undefined,表示变量a已声明,但还未赋值。

标识符

标识符(identifier)指的是用来识别各种值的合法名称。最常见的标识符就是变量名,以及后面要提到的函数名。JavaScript 语言的标识符对大小写敏感,所以aA是两个不同的标识符。

标识符有一套命名规则,不符合规则的就是非法标识符。JavaScript 引擎遇到非法标识符,就会报错。

简单说,标识符命名规则如下。

下面这些都是合法的标识符。

arg0_tmp$elemπ

下面这些则是不合法的标识符。

1a  // 第一个字符不能是数字23  // 同上***  // 标识符不能包含星号a+b  // 标识符不能包含加号-d  // 标识符不能包含减号或连词线

中文是合法的标识符,可以用作变量名。

var 临时变量 = 1;

JavaScript 有一些保留字,不能用作标识符:arguments、break、case、catch、class、const、continue、debugger、default、delete、do、else、enum、eval、export、extends、false、finally、for、function、if、implements、import、in、instanceof、interface、let、new、null、package、private、protected、public、return、static、super、switch、this、throw、true、try、typeof、var、void、while、with、yield。

注释

源码中被 JavaScript 引擎忽略的部分就叫做注释,它的作用是对代码进行解释。JavaScript 提供两种注释的写法:一种是单行注释,用//起头;另一种是多行注释,放在/**/之间。

// 这是单行注释/* 这是 多行 注释*/

此外,由于历史上 JavaScript 可以兼容 HTML 代码的注释,所以<!---->也被视为合法的单行注释。

x = 1; <!-- x = 2;--> x = 3;

上面代码中,只有x = 1会执行,其他的部分都被注释掉了。

需要注意的是,-->只有在行首,才会被当成单行注释,否则会当作正常的运算。

function countdown(n) {  while (n --> 0) console.log(n);}countdown(3)// 2// 1// 0

上面代码中,n --> 0实际上会当作n-- > 0,因此输出2、1、0。

区块

JavaScript 使用大括号,将多个相关的语句组合在一起,称为“区块”(block)。

对于var命令来说,JavaScript 的区块不构成单独的作用域(scope)。

{  var a = 1;}a // 1

上面代码在区块内部,使用var命令声明并赋值了变量a,然后在区块外部,变量a依然有效,区块对于var命令不构成单独的作用域,与不使用区块的情况没有任何区别。在 JavaScript 语言中,单独使用区块并不常见,区块往往用来构成其他更复杂的语法结构,比如forifwhilefunction等。

条件语句

JavaScript 提供if结构和switch结构,完成条件判断,即只有满足预设的条件,才会执行相应的语句。

if 结构

if结构先判断一个表达式的布尔值,然后根据布尔值的真伪,执行不同的语句。所谓布尔值,指的是 JavaScript 的两个特殊值,true表示“真”,false表示“伪”。

if (布尔值)  语句;// 或者if (布尔值) 语句;

上面是if结构的基本形式。需要注意的是,“布尔值”往往由一个条件表达式产生的,必须放在圆括号中,表示对表达式求值。如果表达式的求值结果为true,就执行紧跟在后面的语句;如果结果为false,则跳过紧跟在后面的语句。

if (m === 3)  m = m + 1;

上面代码表示,只有在m等于3时,才会将其值加上1。

这种写法要求条件表达式后面只能有一个语句。如果想执行多个语句,必须在if的条件判断之后,加上大括号,表示代码块(多个语句合并成一个语句)。

if (m === 3) {  m += 1;}

建议总是在if语句中使用大括号,因为这样方便插入语句。

注意,if后面的表达式之中,不要混淆赋值表达式(=)、严格相等运算符(===)和相等运算符(==)。尤其是赋值表达式不具有比较作用。

var x = 1;var y = 2;if (x === y) {  console.log(x);}// "2"

上面代码的原意是,当x等于y的时候,才执行相关语句。但是,不小心将严格相等运算符写成赋值表达式,结果变成了将y赋值给变量x,再判断变量x的值(等于2)的布尔值(结果为true)。

这种错误可以正常生成一个布尔值,因而不会报错。为了避免这种情况,有些开发者习惯将常量写在运算符的左边,这样的话,一旦不小心将相等运算符写成赋值运算符,就会报错,因为常量不能被赋值。

if (x = 2) { // 不报错if (2 = x) { // 报错

至于为什么优先采用“严格相等运算符”(===),而不是“相等运算符”(==),请参考《运算符》章节。

if…else 结构

if代码块后面,还可以跟一个else代码块,表示不满足条件时,所要执行的代码。

if (m === 3) {  // 满足条件时,执行的语句} else {  // 不满足条件时,执行的语句}

上面代码判断变量m是否等于3,如果等于就执行if代码块,否则执行else代码块。

对同一个变量进行多次判断时,多个if...else语句可以连写在一起。

if (m === 0) {  // ...} else if (m === 1) {  // ...} else if (m === 2) {  // ...} else {  // ...}

else代码块总是与离自己最近的那个if语句配对。

var m = 1;var n = 2;if (m !== 1)if (n === 2) console.log('hello');else console.log('world');

上面代码不会有任何输出,else代码块不会得到执行,因为它跟着的是最近的那个if语句,相当于下面这样。

if (m !== 1) {  if (n === 2) {    console.log('hello');  } else {    console.log('world');  }}

如果想让else代码块跟随最上面的那个if语句,就要改变大括号的位置。

if (m !== 1) {  if (n === 2) {    console.log('hello');  }} else {  console.log('world');}// world

switch 结构

多个if...else连在一起使用的时候,可以转为使用更方便的switch结构。

switch (fruit) {  case "banana":    // ...    break;  case "apple":    // ...    break;  default:    // ...}

上面代码根据变量fruit的值,选择执行相应的case。如果所有case都不符合,则执行最后的default部分。需要注意的是,每个case代码块内部的break语句不能少,否则会接下去执行下一个case代码块,而不是跳出switch结构。

var x = 2;switch (x) {  case 1:    console.log('x 等于1');  case 2:    console.log('x 等于2');  default:    console.log('x 等于其他值');}// x等于1// x等于2// x等于其他值

上面代码中,case代码块之中没有break语句,导致不会跳出switch结构,而会一直执行下去。正确的写法是像下面这样。

switch (x) {  case 1:    console.log('x 等于1');    break;  case 2:    console.log('x 等于2');    break;  default:    console.log('x 等于其他值');}

switch语句部分和case语句部分,都可以使用表达式。

switch (1 + 3) {  case 2 + 2:    f();    break;  default:    neverHappens();}

上面代码的default部分,是永远不会执行到的。

需要注意的是,switch语句后面的表达式,与case语句后面的表示式比较运行结果时,采用的是严格相等运算符(===),而不是相等运算符(==),这意味着比较时不会发生类型转换。

var x = 1;switch (x) {  case true:    console.log('x 发生类型转换');    break;  default:    console.log('x 没有发生类型转换');}// x 没有发生类型转换

上面代码中,由于变量x没有发生类型转换,所以不会执行case true的情况。这表明,switch语句内部采用的是“严格相等运算符”,详细解释请参考《运算符》一节。

三元运算符 ?:

JavaScript 还有一个三元运算符(即该运算符需要三个运算子)?:,也可以用于逻辑判断。

(条件) ? 表达式1 : 表达式2

上面代码中,如果“条件”为true,则返回“表达式1”的值,否则返回“表达式2”的值。

var even = (n % 2 === 0) ? true : false;

上面代码中,如果n可以被2整除,则even等于true,否则等于false。它等同于下面的形式。

var even;if (n % 2 === 0) {  even = true;} else {  even = false;}

这个三元运算符可以被视为if...else...的简写形式,因此可以用于多种场合。

var myVar;console.log(  myVar ?  'myVar has a value' :  'myVar does not have a value')// myVar does not have a value

上面代码利用三元运算符,输出相应的提示。

var msg = '数字' + n + '是' + (n % 2 === 0 ? '偶数' : '奇数');

上面代码利用三元运算符,在字符串之中插入不同的值。

循环语句

循环语句用于重复执行某个操作,它有多种形式。

while 循环

While语句包括一个循环条件和一段代码块,只要条件为真,就不断循环执行代码块。

while (条件)  语句;// 或者while (条件) 语句;

while语句的循环条件是一个表达式,必须放在圆括号中。代码块部分,如果只有一条语句,可以省略大括号,否则就必须加上大括号。

while (条件) {  语句;}

下面是while语句的一个例子。

var i = 0;while (i < 100) {  console.log('i 当前为:' + i);  i = i + 1;}

上面的代码将循环100次,直到i等于100为止。

下面的例子是一个无限循环,因为循环条件总是为真。

while (true) {  console.log('Hello, world');}

for 循环

for语句是循环命令的另一种形式,可以指定循环的起点、终点和终止条件。它的格式如下。

for (初始化表达式; 条件; 递增表达式)  语句// 或者for (初始化表达式; 条件; 递增表达式) {  语句}

for语句后面的括号里面,有三个表达式。

下面是一个例子。

var x = 3;for (var i = 0; i < x; i++) {  console.log(i);}// 0// 1// 2

上面代码中,初始化表达式是var i = 0,即初始化一个变量i;测试表达式是i < x,即只要i小于x,就会执行循环;递增表达式是i++,即每次循环结束后,i增大1。

所有for循环,都可以改写成while循环。上面的例子改为while循环,代码如下。

var x = 3;var i = 0;while (i < x) {  console.log(i);  i++;}

for语句的三个部分(initialize、test、increment),可以省略任何一个,也可以全部省略。

for ( ; ; ){  console.log('Hello World');}

上面代码省略了for语句表达式的三个部分,结果就导致了一个无限循环。

do…while 循环

do...while循环与while循环类似,唯一的区别就是先运行一次循环体,然后判断循环条件。

do  语句while (条件);// 或者do {  语句} while (条件);

不管条件是否为真,do...while循环至少运行一次,这是这种结构最大的特点。另外,while语句后面的分号注意不要省略。

下面是一个例子。

var x = 3;var i = 0;do {  console.log(i);  i++;} while(i < x);

break 语句和 continue 语句

break语句和continue语句都具有跳转作用,可以让代码不按既有的顺序执行。

break语句用于跳出代码块或循环。

var i = 0;while(i < 100) {  console.log('i 当前为:' + i);  i++;  if (i === 10) break;}

上面代码只会执行10次循环,一旦i等于10,就会跳出循环。

for循环也可以使用break语句跳出循环。

for (var i = 0; i < 5; i++) {  console.log(i);  if (i === 3)    break;}// 0// 1// 2// 3

上面代码执行到i等于3,就会跳出循环。

continue语句用于立即终止本轮循环,返回循环结构的头部,开始下一轮循环。

var i = 0;while (i < 100){  i++;  if (i % 2 === 0) continue;  console.log('i 当前为:' + i);}

上面代码只有在i为奇数时,才会输出i的值。如果i为偶数,则直接进入下一轮循环。

如果存在多重循环,不带参数的break语句和continue语句都只针对最内层循环。

标签(label)

JavaScript 语言允许,语句的前面有标签(label),相当于定位符,用于跳转到程序的任意位置,标签的格式如下。

label:  语句

标签可以是任意的标识符,但不能是保留字,语句部分可以是任意语句。

标签通常与break语句和continue语句配合使用,跳出特定的循环。

top:  for (var i = 0; i < 3; i++){    for (var j = 0; j < 3; j++){      if (i === 1 && j === 1) break top;      console.log('i=' + i + ', j=' + j);    }  }// i=0, j=0// i=0, j=1// i=0, j=2// i=1, j=0

上面代码为一个双重循环区块,break命令后面加上了top标签(注意,top不用加引号),满足条件时,直接跳出双层循环。如果break语句后面不使用标签,则只能跳出内层循环,进入下一次的外层循环。

标签也可以用于跳出代码块。

foo: {  console.log(1);  break foo;  console.log('本行不会输出');}console.log(2);// 1// 2

上面代码执行到break foo,就会跳出区块。

continue语句也可以与标签配合使用。

top:  for (var i = 0; i < 3; i++){    for (var j = 0; j < 3; j++){      if (i === 1 && j === 1) continue top;      console.log('i=' + i + ', j=' + j);    }  }// i=0, j=0// i=0, j=1// i=0, j=2// i=1, j=0// i=2, j=0// i=2, j=1// i=2, j=2

上面代码中,continue命令后面有一个标签名,满足条件时,会跳过当前循环,直接进入下一轮外层循环。如果continue语句后面不使用标签,则只能进入下一轮的内层循环。

标签:语句,JavaScript,console,log,代码,前置,知识,js,var
来源: https://blog.csdn.net/weixin_54337936/article/details/122385728