JS
有3种书写位置,分别为行内、内嵌和外部。行内式写法如下:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JS的书写位置title>
head>
<body>
<input type="button" value="点我试试" onclick="alert('Hello World')">
body>
html>
JS
代码写在 HTML
标签的事件属性中(以 on
开头的属性) 如:onclickhtml
中编写 JS
大量代码时,不方便阅读内嵌式写法如下:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JS的书写位置title>
head>
<body>
body>
html>
<script>
alert("Hello World");
script>
JS
代码写到 script
标签中JS
是学习时常用的方式外部JS文件写法如下,先新建一个外部的 JS
文件,并在其中编写 JS
代码,然后在 HTML
中进行引入:
引入的 HTML
代码如下:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JS的书写位置title>
head>
<body>
body>
html>
<script src="test.js">script>
HTML
页面代码结构化,把大段 JS
代码独立到 HTML
页面之外,既美观,也方便文件级别的复用JS
文件的 script
标签中间不可以写代码JS
代码量比较大的情况为了提高代码的可读性,JS
与 HTML/CSS
一样,也提供了注释功能。JS中的注释主要有两种,分别是 单行注释
和 多行注释
。示例代码如下:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JS中的注释title>
head>
<body>
body>
html>
<script>
// 单行注释的注释方式如下:
// 我是Amo 不想被js引擎执行 注释起来 //用来注释单行文字
// 一般单行注释的快捷键为: ctrl/command + /
console.log(1111); //控制台输出打印
// 多行注释的注释方式如下:
// 一般多行注释的快捷键为: ctrl/command + shift + / 不同的编辑器快捷键不同
/* 1.发送请求获取响应
2.判断请求是否成功 如果成功 解析数据
* */
script>
为了方便信息的输入输出,JS
中提供了一些输入输出语句,其常用的语句如下:
方法 | 说明 | 归属 |
---|---|---|
alert(msg) | 浏览器弹出警示框 | 浏览器 |
console.log(msg) | 浏览器控制台打印输出信息 | 浏览器 |
prompt(info) | 浏览器弹出输入框,用户可以输入 | 浏览器 |
示例代码如下:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JS中的输入输出语句title>
head>
<body>
body>
html>
<script>
alert("Hello World");
console.log("Hello World");
// 可以使用一个变量来存储用户录入的值
idCard = prompt("请输入您的身份证号码:");
console.log(idCard);
script>
变量就是一个装东西的盒子。变量是用于存放数据的容器。 我们通过 变量名
获取数据,甚至数据可以修改。
本质:变量是程序在内存中申请的一块用来存放数据的空间。类似我们酒店的房间,一个房间就可以看做是一个变量。为了节省空间,笔者后续给出的示例代码都将省略 HTML/CSS
的代码,变量的使用如下:
<script>
//var是一个JS关键字,用来声明变量。使用该关键字声明变量后,计算机会自动为变量分配内存空间
//第一种方式: 先声明 后赋值
var age; //age 定义的变量名 要符合一定的规则 ==> 教室的门牌号
age = 10; //赋值 ==>教室中的同学 通过age找到同学
age = 20; //更新变量 即age被重新赋值
//第二种: 变量的初始化 即声明变量的同时给它赋值
var name = "Amo";
//第三种: 同时声明多个变量
var school = "重庆大学", address = "重庆市沙坪坝区";
</script>
变量命名规范:
(A-Za-z)
、数字 (0-9)
、下划线 (_)
、美元符号 ( $ )
组成,如:usrAge, num01, _name18age
是错误的ES6
新增了 let
命令,用于声明变量。其用法类似于 var
,但是所声明的变量只在 let
命令所在的代码块内有效。示例代码如下:
<script>
//{}表示代码块
{
var a = 1;
let b = 2;
}
console.log(a);
console.log(b);
</script>
上述代码执行结果如下:
for
循环的计数器就非常适合 let
命令,示例代码如下:
<script>
var arr1 = [];
for (var i = 0; i < 10; i++) {
arr1[i] = function () {
return i;
}
}
/*
上述代码中 变量i是var声明的 即全局范围内有效,每一次循环i的值都会发生改变
而循环内 被赋值给数组a的函数内部的i指向全局的i 所有数组a的成员中的i指向
的都是同一个i 导致运行时输出的是最后一轮的i值也就是10。
*/
console.log(arr1[2]());//10
var arr2 = [];
for (let i = 0; i < 10; i++) {
arr2[i] = function () {
return i;
}
}
/*
上面的代码中,变量i是let声明的,当前的i只在本轮循环有效。所以每一次
循环的i其实都是一个新的变量,于是最后输出的是6。 JavaScript引擎内部
会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行
计算。
*/
console.log(arr2[2]());//2
</script>
上述代码执行结果如下:
另外,for
循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。示例代码如下:
<script>
for (let i = 0; i < 3; i++) {
let i = "abc";
console.log(i)
}
</script>
上述代码执行结果如下:
正确运行以上代码将输出 3次abc
。这表明函数内部的变量 i
与循环变量 i
不在同一个作用域,而是有各自单独的作用域。let
声明变量不存在变量提升,示例代码如下:
<script>
console.log(foo); //输出undefined
var foo = 2;
//let的情况
console.log(bar);
let bar = 2;
</script>
上述代码执行结果如下:
只要块级作用域内存在 let
命令,它所声明的变量就 绑定(binding)
这个区域,不再受外部的影响。示例代码如下:
<script>
var temp = 123;
if(true){
temp = "abc";
let temp;
}
</script>
上述代码运行结果如下:
上面的代码中存在全局变量 temp
,但是块级作用域内 let
又声明了一个全局变量 temp
,导致后者绑定这个块级作用域,所以在 let
声明变量前,对 temp
赋值会报错。ES6
明确规定,如果区块中存在 let
和 const
命令,则这个区块对这些命令声明的变量从一开始就形成封闭作用域。只要在声明之前就使用这些变量,就会报错。总之,在代码块中,使用 let
命令声明变量之前,该变量都是不可用的。这在语法上称为 暂时性死区(temporal dead zone)
,简称 TDZ
。在看看下面这个例子:
<script>
console.log(typeof y); //undefined
console.log(typeof x);
let x;
</script>
上述代码执行结果如下:
上面的代码中,变量 x
使用 let
命令声明,所以在声明之前都属于 x
的 死区
,只要用到该变量就会报错。因此 typeof
运行时就会抛出一个 ReferenceError
。作为比较,如果一个变量根本没有被声明,使用 typeof
反而不会报错。这样的设计是为了让大家养成良好的编程习惯,变量一定要在声明之后使用,否则就会报错。有些 死区
比较隐蔽,不太容易发现。示例代码如下:
<script>
function bar(x = y, y = 2) {
return [x, y];
}
bar();//报错
</script>
上述代码执行结果如下:
上面的代码中,调用 bar
函数之所以报错(某些实现可能不报错),是因为参数 x
的默认值等于另一个参数 y
,而此时 y
还没有声明,属于 死区
。如果 y
的默认值是 x
,就不会报错,因为此时 x
已经声明。另外下面的代码也会报错,与 var
的行为不同。
<script>
var x = x;
console.log(x)
let y = y;
console.log(y);
</script>
上述代码执行结果如下:
以上代码出错也是因为暂时性死区,使用 let
声明变量时,只要变量在还没有声明前使用,就会报错。let
不允许在相同作用域内重复声明同一个变量。示例代码如下:
<script>
var a = 10;
var a = 20; // 可以重复声明不报错
let x = 1;
let x = 2; //报错
</script>
上述代码执行结果如下:
const
声明一个只读的常量。一旦声明,常量的值就不能改变。注意 const
具备上面 let
所述的所有特性,如下图所示:
const
实际上保证的并不是变量的值不得改动,而是变量指向的那个内存地址不得改动。对于简单类型的数据(数值、字符串、布尔值) 而言,值就保存在变量指向的内存地址中。因此等同于常量。但对于复合类型的数据(主要是对象和数组)而言,变量指向的内存地址保存的只是一个指针(引用),const
只能保证这个指针是固定的,至于它指向的数据结构是不是可变的,这完全不能控制。示例代码如下:
<script>
const person = {};
// 为foo添加一个属性
person.name = "Amo";
console.log(person.name);
// 将person指向另一个对象 就会报错
person = {};
</script>
上述代码执行结果如下:
补充一点,let
声明变量不会污染全局变量,示例代码如下:
<script>
// console.log(window.a)
//let RegExp = 2;
//console.log(RegExp) // 2
//console.log(window.RegExp) // ƒ RegExp() { [native code] }
var RegExp = 3;
console.log(RegExp) // 3
console.log(window.RegExp) // 3
</script>
上面补充的关于一些 ES6
的新特性,参考阮一峰 ES6标准入门
一书,一些解释性文字就直接拿过来了,当作学习使用,如有侵权,请联系笔者删除。如果是刚学习 JS
的读者可以先跳过这部分的学习。
在计算机中,不同的数据所需占用的存储空间是不同的,为了便于把数据分成所需内存大小不同的数据,充分利用存储空间,于是定义了不同的数据类型。简单来说,数据类型就是数据的类别型号。比如姓名 张三
,年龄 18
,这些数据的类型是不一样的。JS
把数据类型分为两类:
<script>
//JS弱类型语言(动态语言) 自动根据=右边变量值的数据类型来判断
var age = 21; //整数 默认为十进制
var height = 18;//小数
console.log(Number.MAX_VALUE) //JS中数值的最大值
console.log(Number.MIN_VALUE) //JS中数值的最小值
//数字型三个特殊值
console.log(1 / 0); //Infinity: 代表无穷大,大于任何数值
console.log(-1 / 0); // -Infinity: 代表无穷小,小于任何数值
// isNaN: 非数字返回true 数字返回false
console.log(isNaN(age)); // false
//字符串 用双引号或者单引号即可
var name = "Amo"; // 'Amo'
console.log(name.length); // 输出字符串长度 3
var address = "重庆市'沙坪坝区'" // 注意:JS外双内单 外单内双 否则会报错
var sex = '我是"男"的'
//字符串拼接 常用到
var personInfo = "Amo" + "--" + "好帅~"
console.log(personInfo); //Amo--好帅~ +用来连接
var num1 = 10;
console.log("10" + 100); //10100
//布尔值 要么是true 要么是false 即非真就假
console.log(true);
console.log(true + 1);//1 true在参与运算的时候会转换为1 false转换为0
//一个声明后没有被赋值的变量会有一个默认值undefined
var company;
console.log(company); //undefined
console.log(company + 11);//NaN
//一个声明变量给null值,里面存的值为空 后续深入讲解
console.log(11 + null) //null参与运算时转换为0
</script>
typeof
可用来获取检测变量的数据类型,示例代码如下:
<script>
var age = 18;
console.log(typeof age); //number
</script>
使用表单、prompt
获取过来的数据默认是字符串类型的,此时就不能直接简单的进行加法运算,而需要转换变量的数据类型。通俗来说,就是把一种数据类型的变量转换成另一种数据类型,通常会实现 3
种方式的转换:
转换为字符串类型
转换为数字型
转换为布尔型
转换为字符串,如下图所示:
隐式转换是我们在进行算数运算的时候,JS
自动转换了数据类型。转换为数字型(重点),如下图所示:
转换为布尔型,如下图所示:
代表空、否定的值会被转换为false
,如 0/NaN/null/undefined
其余值都会被转换为 true
。
模板字符串(template string)
是增强版的字符串,用反引号( `)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。示例代码如下:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>模板字符串title>
head>
<body>
<div id="box">div>
body>
html>
<script>
// 需求: 现在我想要将ul>li 标签写入id为box的盒子中
const oBox = document.querySelector("#box")
let id = "desc";
let desc = "Amo so cool~";
// 传统的方法字符串拼接 一旦拼接字符串太长多 容易乱
//oBox.innerHTML = "- " + desc + "
"
// 使用模板字符串拼接
oBox.innerHTML = `
- ${id}
">${desc}
`;
let x = 1;
let y = 2
//大括号内可以放入任意的JS表达式 可以进行计算以及引用对象属性。
console.log(`${x} + ${y * 2} = ${x + y * 2}`);
script>
上述代码执行结果如下:
关于 模板字符串
还有一些更复杂的操作,可以参考阮一峰的ES6 标准入门
一书。
运算符(operator)
也被称为操作符,是用于实现赋值、比较和执行算数运算等功能的符号。JavaScript
中常用的运算符有:
算术运算使用的符号,用于执行两个变量或值的算术运算。
要注意的一个点是 浮点数的精度问题
,浮点数值的最高精度是 17
位小数,但在进行算术计算时其精确度远远不如整数。示例代码如下:
<script>
let result = 0.1 + 0.2;
console.log(result);
console.log(0.07 * 100);
</script>
上述代码执行结果如下:
所以:不要直接判断两个浮点数是否相等 !
如果需要反复给数字变量 添加或减去1
,可以使用 递增(++)
和 递减(--)
运算符来完成。在 JavaScript
中,递增(++)
和 递减(--)
既可以放在变量前面,也可以放在变量后面。放在变量前面时,我们可以称为 前置递增(递减)
运算符,放在变量后面时,我们可以称为 后置递增(递减)
运算符。注意:递增和递减运算符必须和变量配合使用。 示例代码如下:
<script>
// 1.前置递增运算符和后置递增运算符单独参与运算的时候无差别
let num1 = 1;
num1++;
console.log(num1);//2
let num2 = 1;
++num2;
console.log(num2);//2
//2.参与复合运算的时候
let num3 = 10;
//先自+1 在求和 ==> num3=10+1 ==> num3+10 ==>21
console.log(++num3 + 10);//21
let num4 = 10;
//先返回原值求和 后自加 ==> num4+10 ==> 20 最后结果
// 后自增: num4=10+1=11 但是这个值已经不参与运算了
console.log(num4++ + 10); //20
</script>
比较运算符(关系运算符) 是两个数据进行比较时所使用的运算符,比较运算后,会返回一个布尔值 true/false
作为比较运算的结果。
等号的比较要特别注意,如下图所示:
示例代码如下:
<script>
console.log(18 == "18"); //true
console.log(18 === "18"); // false
</script>
逻辑运算符是用来进行布尔值运算的运算符,其返回值也是布尔值。后面开发中经常用于多个条件的判断。
逻辑与 &&
,两边都是true才返回true,否则返回false。
逻辑或 ||
,两边都是false才返回false,否则返回true。
逻辑非 (!)
也叫作取反符,用来取一个布尔值相反的值,如true 的相反值是 false。示例代码如下:
<script>
let isOk = true;
console.log(!isOk);//false
</script>
短路运算(逻辑中断)
:当有多个表达式(值)时,左边的表达式值可以确定结果时,就不再继续运算右边的表达式的值。示例代码如下:
<script>
// 1.逻辑与 表达式1&&表达式2&&表达式3...
// 有0则返回0 否则返回最后一个非0数字
console.log(123 && 456); // 456
console.log(0 && 456); // 0
console.log(123 && 456 && 789); // 789
// 2.逻辑或 表达式1||表达式2||表达式3...
// 返回第一个非0数字
console.log(123 || 456); // 123
console.log(0 || 456); // 456
console.log(123 || 456 || 789); // 123
</script>
<script>
// 第一种写法: 使用第三方变量
let a = 10;
let b = 20;
console.log(`交换变量值之前a为:${a} b为:${b}`);
let temp = a;
a = b;
b = a;
console.log(`交换变量值之后a为:${a} b为:${b}`);
console.log("******************************");
// 第二种写法: 算术运算符的方式
let x = 10;
let y = 20;
console.log(`交换变量值之前x为:${x} y为:${y}`);
let sum = x + y;
x = sum - x;
y = sum - x;
console.log(`交换变量值之后x为:${x} y为:${y}`);
console.log("******************************");
// 第三种写法: 位运算的方式
let m = 10;
let n = 20;
console.log(`交换变量值之前m为:${m} n为:${n}`);
m = m ^ n;
n = m ^ n;
m = m ^ n;
console.log(`交换变量值之后m为:${m} n为:${n}`);
console.log("******************************");
// 第四种写法: 解构赋值
let i = 10;
let j = 20;
console.log(`交换变量值之前i为:${i} j为:${j}`);
[i, j] = [j, i];
console.log(`交换变量值之后i为:${i} j为:${j}`);
console.log("******************************");
// 第五种写法: 一句话搞定
let c = 10;
let d = 20;
console.log(`交换变量值之前c为:${c} d为:${d}`);
c = (c + d) - (d = c);
console.log(`交换变量值之后c为:${c} d为:${d}`);
</script>
在上述交换两个变量的时候,我们提到了 解构赋值
的概念。ES6
允许按照一定模式从数组和对象中提取值,然后对变量进行赋值,这被称为 解构(Destructuring).
示例代码如下:
<script>
// 以前为变量赋值只能直接指定值
let a = 1, b = 2, c = 3;
console.log(a, b, c);
// ES6允许这样写
let [l, m, n] = [1, 2, 3];//可以从数组中提取值 按照对应位置对变量赋值
console.log(l, m, n);
</script>
本质上这种写法属于 模式匹配
,只要等号两边的模式相同,左边的变量就会被赋予对应的值。下面是一些使用嵌套数组进行解构的例子。
<script>
let [foo, [[bar], baz]] = [1, [[2], 3]];
console.log(foo, bar, baz) // 1 2 3
let [, , third] = ["amo", "jerry", "paul"];
console.log(third); //paul
let [x, , y] = [1, 2, 3];
console.log(x, y); // 1 3
let [head, ...tail] = [1, 2, 3, 4];
console.log(head, tail);// 1 [2,3,4]
let [a, b, ...c] = ["amo"];
//如果解构不成功 变量的值就等于undefined
console.log(a, b, c); // amo undefined []
let [m] = [];
let [i, j] = [1]; //这两种解构都属于不成功
console.log(m, i, j); //undefined 1 undefined
</script>
上述代码执行结果为:
另一种情况是 不完全解构
,即等号左边的模式只匹配一部分的等号右边的数组,这种情况下,解构依然可以成功。示例代码如下:
<script>
let [x, y] = [1, 2, 3];
console.log(x, y); // 1 2
let [a, [b], c] = [1, [2, 3], 4];
console.log(a, b, c) // 1 2 4
//上面两个例子都属于不完全解构,但是可以成功。
let [m, n] = 1;
console.log(m, n);
</script>
上述代码执行结果如下:
对于 Set
结构,也可以使用数组的解构赋值。示例代码如下:
<script>
let [x, y, z] = new Set(["Amo", "Jerry", "Paul"]);
console.log(x, y, z); // Amo Jerry Paul
</script>
事实上,只要某种数据结构具有 Iterator
接口,都可以采用数组形式的解构赋值。解构赋值
还允许指定默认值,示例代码如下:
<script>
let [a = true] = [];
console.log(a);
let [x, y = "b"] = ["a"];
console.log(x, y); // a b
//ES6内部使用严格相等运算符(===)判断一个位置是否有值,所以,如果
//一个数组成员不严格等于undefined,默认值是不会改变的
let [m, n = "b"] = ["a", undefined];
console.log(m, n); // a b
let [b = 1] = [undefined]; //这里是undefined理解为没值 则默认值为1
console.log(b); // 1
let [l = 1] = [null];
console.log(l); // null
</script>
如果默认值是一个表达式,那么这个表达式是 惰性
求值的,即只有在用到时才会求值。示例代码如下:
<script>
function f() {
console.log("aaa");
}
let [x = f()] = [1];
console.log(x); // 因为x能取到值,所以函数f根本不会执行
//默认值可以引用解构赋值的其它变量,但该变量必须已经声明
let [a = 1, b = a] = [];
console.log(a, b);
let [m = 1, n = m] = [2];
console.log(m, n);
let [j = 1, k = j] = [1, 2];
console.log(j, k);
let [o = p, p = 1] = [];
console.log(o, p);
</script>
解构不仅可以用于数组,还可以用于对象。示例代码如下:
<script>
let {name, age} = {name: "Amo", age: 18}
console.log(name, age) // Amo 18
</script>
上述代码执行结果如下:
对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定。而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。示例代码如下:
<script>
let {name, age} = {age: 18, name: "Amo"};
console.log(name, age); // Amo 18
let {address} = {sex: "男", hobby: "唱歌"};
console.log(address) // undefined
</script>
如果变量名与属性名不一致,示例代码如下:
<script>
let {foo: baz} = {foo: "aaa", bar: "bbb"};
console.log(baz) // aaa
let obj = {first: "hello", last: "world"};
let {first: f, last: l} = obj;
console.log(f, l); // hello world
//实际上,对象的解构赋值是下面形式的简写
let {a: a, b: b} = {a: "aaa", b: "bbb"};
console.log(a, b); // aaa bbb
//也就是说,对象的解构赋值的内部机制是先查找到同名属性,然后在赋值给对应的变量。
//真正被赋值的是后者,而不是前者
let {name: age} = {name: "amo", address: "重庆市沙坪坝区"}
console.log(age); // amo
</script>
与数组一样,解构也可以用于嵌套结构的对象。示例代码如下:
<script>
let obj = {
p: [
"hello",
{y: "world"}
]
}
let {p: [x, {y}]} = obj;
console.log(x, y); // hello world
</script>
注意,这时 p
是模式,不是变量,因此不会被赋值。如果 p
也要作为变量赋值,可以写成下面这样。
<script>
let obj = {
p: [
"Hello",
{y: "World"}
]
};
let {p, p: [x, {y}]} = obj;
console.log(x, y, p);
</script>
<script>
let node = {
loc: {
start: {
line: 1,
column: 5
}
}
}
let {loc, loc: {start}, loc: {start: {line}}} = node;
console.log(line);
console.log(start);
console.log(loc);
</script>
<script>
let obj = {};
let arr = [];
({foo: obj.prop, bar: arr[0]} = {foo: 123, bar: true});
console.log(obj);
console.log(arr);
//对象指定默认值
let {x = 3} = {};
console.log(x);
let {a, b = 5} = {a: 1};
console.log(a); //1
console.log(b); //5
let {m: n = 3} = {};
console.log(n); //3
let {i: j = 3} = {i: 5};
console.log(j); //5 默认值生效的条件是,对象的属性值严格等于undefined
//对象的解构赋值可以很方便地将现有对象的方法赋值到某个变量
let {log, sin, cos} = Math;
//由于数组本质是特殊的对象,因此可以对数组进行对象属性的解构
let arr2 = [1, 2, 3];
let {0: first, [arr2.length - 1]: last} = arr2;
console.log(first, last); // 1 3
</script>
字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。示例代码如下:
<script>
const [a, b, c, d, e] = "hello";
console.log(a, b, c, d, e);
//类似数组的对象都有一个length属性,因此还可以对这个属性进行解构赋值
let {length: len} = "hello";
console.log(len);//5
</script>
在一个程序执行的过程中,各条代码的执行顺序对程序的结果是有直接影响的。很多时候我们要通过控制代码的执行顺序来实现我们要完成的功能。简单理解:流程控制就是来控制代码按照一定结构顺序来执行。 流程控制主要有三种结构,分别是顺序结构、分支结构 和 循环结构,代表三种代码执行的顺序。
顺序结构是程序中最简单、最基本的流程控制,它没有特定的语法结构,程序会按照代码的先后顺序,依次执行,程序中大多数的代码都是这样执行的。
由上到下执行代码的过程中,根据不同的条件,执行不同的路径代码(执行代码多选一的过程),从而得到不同的结果。
JS
语言提供了两种分支结构语句:if
语句、switch
语句。if
语句语法结构如下:
// 条件成立执行代码,否则什么也不做
if (条件表达式) {
// 条件成立执行的代码语句
}
<script>
let age = 20;
if (age > 18) {
console.log("成年了,可以上网打撸了!");
}
</script>
上述代码执行结果为:
if else
语句(双分支语句),语法结构如下:
// 条件成立 执行if里面代码,否则执行else里面的代码
if (条件表达式) {
// [如果] 条件成立执行的代码
} else {
// [否则] 执行的代码
}
如果某一年是闰年,那么这一年的2月份就有29天,否则这一年的2月份就有28天。应用 if…else
语句判断2020年2月份的天数。代码如下:
<script>
let year = 2020;
let month = 0;
//判断指定年是否是闰年
if ((year % 400 == 0) || (year % 4 == 0 && year % 100 != 0)) {
month = 29;
} else {
month = 28;
}
console.log(`2020年2月份的天数为${month}`);
</script>
上述代码执行结果为:
if else if
语句(多分支语句) 语法结构如下:
// 适合于检查多重条件。
if (条件表达式1) {
语句1;
} else if (条件表达式2) {
语句2;
} else if (条件表达式3) {
语句3;
....
} else {
// 上述条件都不成立执行此处代码
}
将某学校的学生成绩转化为不同等级,划分标准如下:
① 优秀大于等于90分
② 良好大于等于75分
③ 及格大于等于60分
④ 不及格小于60分
假设Amo的考试成绩是85分,输出该成绩对应的等级。其关键代码如下:
<script>
let score = 85;
if (score < 60) {
console.log("不及格");
} else if (score < 74) {
console.log("及格");
} else if (score < 90) {
console.log("良好");
} else {
console.log("优秀");
}
</script>
上述代码执行结果为:
if
语句不但可以单独使用,而且可以嵌套应用,即在 if
语句的从句部分嵌套另外一个完整的 if
语句。基本语法格式如下:
if (表达式1){
if(表达式2){
语句1
}else{
语句2
}
}else{
if(表达式3){
语句3
}else{
语句4
}
}
例如,Amo的高考总分是620,英语成绩是120。假设重点本科的录取分数线是600,而英语分数必须在 130
以上才可以报考外国语大学,应用 if语句
的嵌套判断该考生能否报考外国语大学,代码如下:
<script>
const totalScore = 620;
const englishScore = 120;
if (totalScore > 600) {
if (englishScore > 130) {
console.log("能报考外国语大学!");
} else {
console.log("该考生可以报考重点本科,但不能报考外国语大学!");
}
} else {
if (totalScore > 500) {
console.log("该考生可以报考普通本科");
} else {
console.log("该考生只能报考专科");
}
}
</script>
表达式1 ? 表达式2: 表达式3;
1
为 true ,则返回表达式 2
的值,如果表达式1为 false,则返回表达式3的值if else(双分支)
的简写 示例代码如下:<script>
let x = 4 > 5 ? 1 : 2;
console.log(x); // 2
</script>
switch
分支流程控制,switch
语句也是多分支语句,它用于基于不同的条件来执行不同的代码。当要针对变量设置一系列的特定值的选项时,就可以使用 switch
。语法格式如下:
switch (表达式){
case 常量表达式1:
语句1;
break;
case 常量表达式2:
语句2;
break;
…
case 常量表达式n:
语句n;
break;
default:
语句n+1;
break;
}
参数说明:
case
后相应的语句。如果表达式的值与所有的常量表达式的值都不相等,则执行 default
后面相应的语句。switch
语句,从而使 JavaScript
只执行匹配的分支。如果没有了 break
语句,则该匹配分支之后的所有分支都将被执行,switch
语句也就失去了使用的意义。switch
语句的执行流程如下图所示:
default
语句可以省略。在表达式的值不能与任何一个 case
语句中的值相匹配的情况下,JavaScript
会直接结束 switch
语句,不进行任何操作。case
后面常量表达式的数据类型必须与表达式的数据类型相同,否则匹配会全部失败,而去执行 default
语句中的内容。某公司年会举行抽奖活动,中奖号码及其对应的奖品设置如下:
① 1
代表 一等奖
,奖品是 华为手机
② 2
代表 二等奖
,奖品是 光波炉
③ 3
代表 三等奖
,奖品是 电饭煲
④ 其他号码代表 安慰奖
,奖品是 16G-U盘
假设Amo抽中的奖号为3,输出该员工抽中的奖项级别以及所获得的奖品。代码如下:
<script>
let grade = ""; //定义表示奖项级别的变量
let prize = ""; //定义表示奖品的变量
let code = 3; //定义表示中奖号码的变量值为3
switch (code) {
case 1:
grade = "一等奖";
prize = "华为手机";
break;
case 2:
grade = "二等奖";
prize = "光波炉";
break;
case 3:
grade = "三等奖";
prize = "电饭煲";
break;
default:
grade = "安慰奖";
prize = "16G-U盘";
break;
}
document.write(`该员工获得了${grade}
奖品是${prize}`)
</script>
上述代码执行结果为:
在程序开发的过程中,使用 if
语句还是使用 switch
语句可以根据实际情况而定,尽量做到物尽其用,不要因为 switch
语句的效率高就一味地使用,也不要因为 if
语句常用就不应用 switch
语句。要根据实际的情况,具体问题具体分析,使用最适合的条件语句。一般情况下对于判断条件较少的可以使用 if
条件语句,但是在实现一些多条件的判断中,就应该使用 switch
语句。
while
循环语句也称为前测试循环语句,它是利用一个条件来控制是否要继续重复执行这个语句。while
循环语句与 for
循环语句相比,无论是语法还是执行的流程,都较为简明易懂。while循环语句的语法格式如下:
while(表达式){
语句
}
参数说明:
true
时,重复执行。while
循环语句之所以命名为前测试循环,是因为它要先判断此循环的条件是否成立,然后才进行重复执行的操作。也就是说,while
循环语句执行的过程是先判断条件表达式,如果条件表达式的值为true
,则执行循环体,并且在循环体执行完毕后,进入下一次循环,否则退出循环。while
循环语句的执行流程如下图所示。
例如,应用 while
语句输出1~10
这10个数字的代码如下:
<script>
let i = 1;
while (i <= 10) {
console.log(i);
i++;
}
</script>
do…while
循环语句也称为后测试循环语句,它也是利用一个条件来控制是否要继续重复执行这个语句。与 while
循环所不同的是,它先执行一次循环语句,然后再去判断是否继续执行。do…while
循环语句的语法格式如下:
do{
语句
} while(表达式);
参数说明:
true
时,重复执行。do…while
循环语句执行的过程是:先执行一次循环体,然后再判断条件表达式,如果条件表达式的值为 true
,则继续执行,否则退出循环。也就是说,do…while
循环语句中的循环体至少被执行一次。do…while
循环语句的执行流程如下图所示。
do…while
循环语句同 while
循环语句类似,也常用于循环执行的次数不确定的情况下。do…while
语句结尾处的 while
语句括号后面有一个分号;
,为了养成良好的编程习惯,建议读者在书写的过程中不要将其遗漏。例如,应用 do…while
语句输出 1~10
这10个数字的代码如下:
<script>
let j = 1;
do {
console.log(j);
j++;
} while (j <= 10);
</script>
do…while
语句和 while
语句的执行流程很相似。由于do…while
语句在对条件表达式进行判断之前就执行一次循环体,因此do…while
语句中的循环体至少被执行一次,下面的代码说明了这两种语句的区别。
<script>
let i = 1; //声明变量
while (i > 1) { //定义while语句,指定循环条件
document.write("i的值是" + i); //输出i的值
i--; //变量i自减1
}
let j = 1; //声明变量
do { //定义do...while语句
document.write("j的值是" + j); //输出变量j的值
j--; //变量j自减1
} while (j > 1);
</script>
for
循环语句也称为计次循环语句,一般用于循环次数已知的情况,在 JavaScript
中应用比较广泛。for循环语句的语法格式如下:
for(初始化表达式;条件表达式;更新表达式){
语句
}
参数说明:
true
时,重复执行。for
循环语句执行的过程是:先执行初始化语句,然后判断循环条件,如果循环条件的结果为 true
,则执行一次循环体,否则直接退出循环,最后执行更新表达式,改变循环变量的值,至此完成一次循环。接下来将进行下一次循环,直到循环条件的结果为 false
,才结束循环。for
循环语句的执行流程如下图所示。
例如,应用 for
语句输出 1~10
这10个数字的代码如下:
<script>
for (let i = 1; i <= 10; i++) {
console.log(i);
}
</script>
在使用 for
语句时,也一定要保证循环可以正常结束,也就是必须保证循环条件的结果存在为 false
的情况,否则循环体将无休止地执行下去,从而形成死循环。为使读者更好的了解for语句的使用,下面通过一个具体的实例来介绍 for
语句的使用方法。应用 for
循环语句计算 100以内所有奇数的和
,并在页面中输出计算后的结果。代码如下:
<script>
let sum = 0;
for (let i = 1; i <= 100; i++) {
if (i % 2 != 0) {
sum += i;
}
}
console.log(`1-100的奇数和为${sum}`);
</script>
在一个循环语句的循环体中也可以包含其它的循环语句,这称为循环语句的嵌套。上述 3
种循环语句 (while循环语句、do…while循环语句和for循环语句) 都是可以互相嵌套的。如果循环语句 A
的循环体中包含循环语句 B
,而循环语句 B
中不包含其他循环语句,那么就把循环语句 A
叫做外层循环,而把循环语句 B
叫做内层循环。用嵌套的 for循环
语句输出乘法口诀表。代码如下:
<script>
let i, j; //声明变量
document.write(""
); //输出标记
for (i = 1; i < 10; i++) { //定义外层循环
for (j = 1; j <= i; j++) { //定义内层循环
if (j > 1) document.write("\t"); //如果j大于1就输出一个Tab空格
document.write(j + "x" + i + "=" + j * i); //输出乘法算式
}
document.write("
"); //输出换行标记
}
document.write("
"); //输出标记
</script>
continue
语句用于跳过本次循环,并开始下一次循环。continue
语句只能应用在 while、for、do…while
语句中。例如,在 for
语句中通过 continue
语句输出 10以内不包括5
的自然数的代码如下:
<script>
for (let i = 1; i <= 10; i++) {
if (i == 5) {
continue
} //如果i等于5就跳过本次循环
document.write(i + "\n"); //输出变量i的值
}
</script>
上述代码执行结果如下:
当使用 continue
语句跳过本次循环后,如果循环条件的结果为 false
,则退出循环,否则继续下一次循环。在上面的 switch
语句中已经用到了 break
语句,当程序执行到 break
语句时就会跳出switch
语句。除了 switch
语句之外,在循环语句中也经常会用到break
语句。在循环语句中,break
语句用于跳出循环。break
语句通常用在for、while、do…while或switch
语句中。例如,在 for
语句中通过 break
语句跳出循环的代码如下:
<script>
for (let i = 1; i <= 10; i++) {
if (i == 5) break; //如果i等于5就跳出整个循环
document.write(i + "\n"); //输出变量i的值
}
</script>