跳至主要内容

JavaScript从零开始——入门(2)

 书接上文,来看看JavaScript的基本语法:

1 语句

和大部分的解释性语言(比如Python)一致,JavaScript也是以行(line)为执行单位的,也就是一行一行的执行,一般情况下,一行就是一个语句(statement)。

语句是指为了完成某种任务而进行的操作,如下:

let a = 2 + 2;

这里使用了let声明变量a,然后将2 + 2的运算结果赋值到变量a

2 + 2是表达式(expression),就是一个为了得到返回值的计算式(数学意义上的算式)。

语句和表达式的区别即:

  • 语句主要为了进行某种操作,一般不需要返回值;
  • 表达式则是为了得到返回值,一定会返回一个值——凡是JavaScript预期为值的地方,都可以使用表达式

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

let a = 2 + 2; let b = 'abc';

分号前如果没有任何内容,JavaScript引擎也会认为其生效,即空语句:

;;;

纯表达式不需要分号结尾,一旦添加,JavaScript引擎会将表达式识别为语句,这样会产生一些没有任何意义的语句:

2 + 2;
'abc';

如上只能单纯产生2个值,由于没有任何变量可供承载这些值,故而并没有任何意义。


2 变量

2.1 概念

变量是对值的显性引用:变量即为值起名,然后引用这个名字就等于引用这个值,这个名字也就是变量名:

let a = 0;

这里let是声明变量的命令,与其有类似功能的有varconstconstlet是在ECMAScript 6才引入的命令,目的是为了减少原来只有一个var声明变量而产生的诸多问题,具体区别可以后文再说,这里只需要知道在基础环境下,varlet是可以互换使用的,而const则是声明常量——即不可再次修改的变量——的命令。

上面的语句表示先声明变量a,并在变量名a和数值0之间建立引用关系,称为将数值0赋值给变量a

和Python相同,JavaScript的变量名是区分大小写的,也即aA是两个完全不同的变量。

变量的声明和赋值其实是分开的两个步骤,上面的代码其实际的步骤如下:

let a;
a = 0;

如果仅仅声明变量但没有赋值,则该变量的值是undefined——这是JavaScript特有的值,表示“未定义”。

打开任意一个桌面浏览器,按键盘上的“F12”,打开开发者工具,切换到console标签,试着输入如下两条语句,看看结果:

let a;
a

结果如图:

Chrome的开发者工具截图,其中a的返回值是undefined

留意:如果声明变量的时候忘记写varlet或者const,直接赋值的话也是有效的:

b = 0;
// 基本等同于
let b = 0;

但这里有两点考虑:

  1. 不写声明命令的做法,不利于表达意图
  2. 所创建的变量往往是全局变量,容易污染整个代码环境

所以建议一定使用声明命令来声明变量

可以使用同一个声明命令来声明多个变量:

let a, b, x, y;

由于JavaScript是动态类型语言,所以其变量的类型并没有限制,可以虽然更改类型;比如声明时是文本,之后可以根据需要直接修改为数值,如下:

let a = 'test';
a = 1;

同一个变量名只可以声明一次,如果使用let进行声明,这种重复声明会报错,可参考下面的截图;而使用var进行声明则不会报错,单纯声明将没有作用,但是声明的同时赋值则会赋值成功:

let x = 1;
// 这里会报错
let x;
let x = 5;

var x = 1;
// 这里不会报错
var x;
var x = 5;
x // 5

如下两图:

2.2 变量提升

*如果使用let或者const进行变量声明,不会存在变量提升的现象,一旦采取下文当中的方式,将会报错。

当使用var进行变量声明时,JavaScript引擎的工作方式:

  1. 先解析代码,获取所有被声明的变量;
  2. 然后一行一行的运行;

这样,所有变量的声明语句,都会被提升到代码的头部,就是所谓的变量提升(hoisting)——如下述代码:

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

结果:

实际执行步骤等同于:

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

因为变量提升的原因,在控制台记录a这个变量的时候并没有赋值,故此结果是undefined

由于IE并不支持采用ECMAScript 6的let和const进行变量声明,建议一定要先进行变量声明,避免变量提升的现象。


3 标识符

标识符(identifier)也就是用来识别各种值的合法名称。最常见的就是变量名,以及后面会提到的函数名;它对大小写敏感。

标识符的命名规则如下:

  1. 首字符可以是任意Unicode字符以及美元符号$下划线_;
  2. 之后的字符除了上述字符,还可以使用数字0-9。

故此下面都是合法标识符:

  • test
  • _temp
  • $mine
  • über0
  • 变量1

这些则是非法标识符:

  • 1a
  • *test
  • x+b
  • -temp

同时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

4 注释

代码中被JavaScript引擎忽视的部分就是注释,一般用来对代码进行解释;现在也有很多通过识别注释生成API文档的工具,所以良好的开发习惯就是一定要合理的使用注释,可以降低后续开发工作量。

JavaScript提供两种注释的写法:

// 单行注释

/* 这是
多行
注释
*/

此外,由于JavaScript曾经需要兼容HTML的注释,所以目前为止,HTML的注释方式也是合法的单行注释:

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

如上,只有 x = 1会执行,其他的部分都被注释掉了:

其中-->只有在行首才会被当作单行注释,否则会被当作正常运算,如下:

代码当中的n --> 0实际上变成了n-- > 0,因此变成了自减是否大于0的检测,则可以输出倒数结果。


5 区块

使用大括号将多个相关语句组合到一起,被称为区块(block)。

对于变量声明命令var来说,区块不构成单独的作用域(scope);而let则只会在区块中生效,在区块外部不存在,如下图:

在 JavaScript 语言中,单独使用区块并不常见,区块往往用来构成其他更复杂的语法结构,比如for、if、while、function等。

如图:


6 条件语句

JavaScript提供ifswitch结构用来进行条件判断,即只有满足预设的条件才会执行对应的语句:

6.1 if结构

if结构先判断一个表达式的布尔值(boolean),然后根据布尔值的真伪执行不同的语句。

布尔值就是各种开发语言当中通用的两个特殊值,在JavaScript当中,使用true表示真,false表示伪。

if结构的基本形式包括两种:

  • 单语句执行判断:
// if (布尔值) 语句;
if (x > 0) console.log(x);
  • 多语句执行判断:
/* if (布尔值) {
      语句区块;
   }
*/
if (x > 0) {
    let y = x + 1;
    console.log(y);
}

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

6.2 if...else结构

if代码区块的后面,还可以使用else区块,表示不满足条件时需要执行的代码:

/* if () {
      满足条件的语句;
   } else {
      不满足条件的语句;
   }
*/
if (x > 0) {
    let y = x + 1;
    console.log(y);
} else {
    console.log(x);
}

也可以通过将多个if...else语句连写在一起,进行更复杂的判断,如下:

let x, y, z;
/*
一些其他的代码……
*/
if (x > 0 && z === 5) {
    y = x + 1;
} else if (x === 0 && z < 5){
    y = z - 1;
} else {
    y = x + z;
}
console.log(y);

6.3 switch结构

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

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

上面的代码根据变量fruit的值来选择执行对应的case;如果所有的case不符合,则执行最后的default部分。其中break是指代在执行完当前case代码块之后跳出switch结构,如果没有则会顺序执行而不跳出。

6.4 三元运算符? :

开发语言中通用的三元预算符JavaScript也是可以使用的,即:

// 条件? 表达式1 : 表达式2;
let n = 10;
let even = (n % 2 === 0) ? true : false;

上面这段代码等同于:

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

也就是说,三元运算符可以看作是if...else的简写形式。


7 循环语句

循环语句用于重复执行某个操作,有如下形式:

7.1 while循环

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

/* while (条件) {
      语句;
   }
*/
let i = 0;
while (i < 100) {
    console.log(i);
    i += 1;
}

7.2 for循环

for语句是另一种形式,可以指定循环的起点、终点和终止条件:

/* for (初始表达式; 条件表达式; 递增/递减表达式) {
      语句;
   }
*/
for (let i = 0; i < 100; i++) {
    console.log(i);
}
  • 初始表达式(initialize):确定循环变量的初始值,只在循环开始时执行一次。
  • 条件表达式(test):每轮循环开始时,都要执行这个条件表达式,只有值为真,才继续进行循环。
  • 递增/递减表达式(increment):每轮循环的最后一个操作,通常用来递增/递减循环变量。

7.3 do...while循环

do...while循环和while循环类似,但它会先运行一次循环体,然后判断循环条件,确认是否继续执行下去:

/* do {
      语句;
   } while (条件);
*/
let i = 0;
do {
    console.log(i);
    i++;
} while (i < 100);

7.4 break和continue语句

break语句用于跳出代码块或循环,如下,当i等于10就立刻跳出循环。

let i = 0;
while (i < 100) {
    console.log(i);
    i++;
    if (i === 10) break;
}

continue语句用于立即中止本轮循环,返回循环结构的头部开始下一轮循环,如下只有i为奇数时才会输出,如果为偶数则直接进入下一轮循环。

let i = 0;
while (i < 100) {
    i++;
    if (i % 2 === 0) continue;
    console.log(i);
}

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

7.5 标签(label)

JavaScript 语言允许语句的前面有标签(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);
    }
  }

这是一个双重循环,在break后面加上了top,表示满足条件时,直接跳出双层循环。

执行结果如图:

与continue配合则是如图效果:

8 其他

在接下来的部分当中,会着重使用ECMAScript(后文简称ES)6以上的版本特性,而需要考虑IE或者旧版本ES5的时候会单独提出。

评论

此博客中的热门博文

Node.js从零开始——事件、系统和流

毕竟不是一个真正的教程,这里主要还是以普及和介绍为主,所以这一部分就是 Node.js 的其他部分介绍了,主要也就是事件触发、操作系统以及流的知识。 1 事件触发器 因为我们之前在浏览器中使用 JavaScript ,所以知道 JS 通过事件处理了许多用户的交互:鼠标的单击、键盘按钮的按下、对鼠标移动的反应等等。 在后端, Node.js 也提供了使用 events 模块 构建类似系统的选项。 具体上,此模块提供了 EventEmitter 类,用于处理事件。 使用以下代码进行初始化: const EventEmitter = require ( 'events' ); const eventEmitter = new EventEmitter (); 该对象公开了 on 和 emit 方法: emit 用于触发事件 on 用于添加回调函数(会在事件被触发时执行) 例如,创建 start 事件,并提供一个示例,通过记录到控制台进行交互: eventEmitter . on ( 'start' , () => { console . log ( '开始' ); }); 当运行以下代码时: eventEmitter . emit ( 'start' ); 事件处理函数会被触发,且获得控制台日志。 可以通过将参数作为额外参数传给 emit() 来将参数传给事件处理程序: eventEmitter . on ( 'start' , number => { console . log ( `开始 ${ number } ` ); }); eventEmitter . emit ( 'start' , 23 ); 多个参数: eventEmitter . on ( 'start' , ( start , end ) => { console . log ( `从 ${ start } 到 ${ end } ` ); }); eventEmitter . emit ( 'start' ,

Node.js从零开始——HTTP 服务器

其实 Node.js 最初的目的,就是实现一个完全可以由 JavaScript 来进行开发的服务器端,所以归根到底,它的后端能力之一就是实现一个 HTTP 服务器,这里我们来看看它。 1 搭建 HTTP 服务器 其实前面我们已经看过了一个例子,不过这里再来看一个 HTTP web 服务器的例子: const http = require ( 'http' ); const port = 3000 ; const server = http . createServer (( req , res ) => { res . statusCode = 200 ; res . setHeader ( 'Content-Type' , 'text/plain' ); res . end ( '你好世界\n' ); }) server . listen ( port , () => { console . log ( `服务器运行在 http:// ${ hostname } : ${ port } /` ); }); 简要分析一下: 这里引入了 ref=" http:// nodejs.cn/api/http.html ">http 模块:使用该模块来创建 HTTP 服务器 服务器被设置为在指定的 3000 端口上进行监听, 当服务器就绪时,则 listen 回调函数会被调用 传入的回调函数会在每次接收到请求时被执行, 每当接收到新的请求时, "http://nodejs.cn/api/http.html#http_event_request">request 事件 会被调用,并提供两个对象:一个请求( http.IncomingMessage 对象)和一个响应( http.ServerResponse 对象) request 提供了请求的详细信息, 通过它可以访问请求头和请求的数据, response 用于构造要返回给客户端的数据;在此示例中: res . statusCode = 200 ; 设置 status

Web API从零开始——SVG

SVG 是我基本没有用过的知识块,所以这里也是边分享边学习,尽量在我自己理解的基础上来分享。 1 概念 SVG 是一种基于 XML 语法的图像格式,全称是可缩放矢量图(Scalable Vector Graphics);其他图像格式都是基于像素处理的, SVG 则是属于对图像的形状描述,所以它本质上是文本文件,体积较小,且不管放大多少倍都不会失真。 SVG 文件可以直接插入网页,成为 DOM 的一部分,然后用 JavaScript 和 CSS 进行操作。 上面是 SVG 代码直接插入网页的例子。 SVG 代码也可以写在一个独立文件中,然后用 、 、 、 等标签插入网页: < img src = "circle.svg" > < object id = "object" data = "circle.svg" type = "image/svg+xml" ></</span> object > < embed id = "embed" src = "icon.svg" type = "image/svg+xml" > < iframe id = "iframe" src = "icon.svg" ></</span> iframe > CSS 也可以使用 SVG 文件: . logo { background : url ( icon.svg ); } SVG 文件还可以转为 BASE64 编码,然后作为 Data URI 写入网页: < img src = "data:image/svg+xml;base64,[data]" > 2 语法 2.1 标签 我们可以把 SVG 代码都放在顶层标签 之中,下面是一个例子: < svg width = "100%" height = "100%" >