8. 语句
8.1 表达式和语句
-
表达式:一组代码的集合,JS解释器会计算出一个结果
x = 7 3 + 4 num++
-
语句:JS整句或命令,js语句是以分号结束(可以省略)
比如:if语句 for语句
表达式与语句的区别:
表达式:计算一个值,但语句是用来自行以某件事情发生(做什么事)
如alert() 是一个语句,弹出一个对话框。如prompt弹出一个对话框
如 3+4 最后计算出了一个结果
8.2 分支语句
JS中的三大流程控制语句:顺序结构(自上而下执行),分支结构,循环结构
8.2.1 if分支语句
if语句有三种使用:单分支,双分支,多分支
-
单分支语句的使用语法:
if (条件){ 满足条件要执行的代码 }
- 括号内的条件为true时,进入大括号里执行代码。
- 小括号内的结果若不是boolean型,会发生隐式转换为布尔型。
- 5个false数据类型:(false , 0 ,undefined , null , " " 均为false)
<script> if (true) { alert(11) } if (3 > 5) { console.log('真的') } if ('pink') { console.log('真的') } </script>
案例:单分支课堂案例1:用户输入高考成绩,如果分数大于700分数,则提示考入黑马程序员
<script>
let score = prompt('请输入高考成绩')
if (score > 700) {
document.write(`<h3>提示</h3>
<div>恭喜考入黑马程序员</div>`)
}
</script>
- 双分支语句
语法:
if ( 条件 ) {
满足条件要执行的代码
} else {
不满足条件要执行的代码
}
案例:
用户输入,如果工龄大于1年,年底奖金 + 2000,否则年底没有奖金
<script>
let years = prompt('请输入工龄:')
let money = 10000
if (years > 1) {
document.write(`奖金为:${money + 2000}`)
} else {
document.write(`奖金为:${money}`)
}
</script>
案例:
让用户输入年份,判断这一年是闰年还是平年,并输出
闰年:能被4整除但是不能被100整除,或者被400整除的年份是闰年,否则都是平年
<script>
let year = prompt("请输入年份:")
if (year % 4 === 0 && year % 100 !== 0 || year % 400 === 0){
document.write('闰年')
} else {
document.write('平年')
}
</script>
-
多分支语句
语法:自上而下执行,当发现有满足条件的,就会跳出if多分支
if (条件1) { 代码1 } else if (条件2) { 代码2 } else if (条件3) { 代码3 } else { 代码n }
案例:输入不同时间,输出不同的问候语
- 12点以前,输出上午好
- 18点以前,输出下午好
- 20点以前,输出晚上好
<script> let time = prompt('请输入小时:') if (time < 12 ) { document.write('上午好') } else if (time <=18) { document.write('下午好') } else if (time <20 ) { document.write('晚上好') } else { document.write('夜深了') } </script>
8.2.2 三元运算符
语法:自上而下执行,当发现有满足条件的,就会跳出if多分支
-
其实是比if 双分支更简单的写法,有时候也叫做三元表达式
-
符号:?与:配合使用
-
语法:
条件? 满足条件执行的代码 : 不满足条件执行的代码 // 如果判断为false,则不做任何操作 条件? 满足条件执行的代码 : undefined 条件? 满足条件执行的代码 : null
三元表达式一般用来取值
<script> console.log(true ? 1 : 2) console.log(false ? 1 : 2) 3 > 5 ? alert('第一个') : alert('第二个') </script>
案例:
需求:用户输入2个数,控制台输出最大值
<script>
let num1 = +prompt('请输入第一个数字:')
let num2 = +prompt("请输入第二个数字:")
let result = num1 > num2 ? num1 : num2
document.write(`最大的数字为${result}`)
</script>
案例:数字补0案例
需求:用户输入1个数字,如果小于10,就在前面补充一个0
<script>
let num = prompt('请输入一个数字:')
let num_str = num<10 ? `0${num}`:num
document.write(num_str)
</script>
8.2.3 switch语句
语法:
语法:
-
用数据逐一对所有的值进行全等
===
判断 -
default 可以不用
-
switch不是自上而下,而是直接就匹配到对应的值上
-
一定要注意数据的类型,因为要求的是全等匹配
-
一定要使用break,否则switch会穿透
switch (数据) {
case 值1:
代码1
break
case 值2:
代码2
break
default:
代码n
break
}
<script>
switch (2) {
case 1:
alert(1)
break
case 2:
alert(2)
break
case 3:
alert(3)
break
default:
alert('没有数据')
}
</script>
案例:简单计算器
需求:用户输入2个数字,然后输入 = - * /任何一个,可以计算结果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
let num1 = + prompt("请输入第一个数字:")
let num2 = + prompt("请输入第二个数字:")
let method = prompt("请输入计算方式:")
let result
switch (method){
case "+":
result = num1 + num2
break
case "-":
result = num1 - num2
break
case "*":
result = num1 * num2
break
case "/":
num2=0?alert("除数等于0"):result=num1/num2
break
default:
alert('输入错误')
}
alert(`结果为${result}`)
</script>
</body>
</html>
8.3 while循环
while循环的语法:
while (循环条件) {
要重复执行的代码(循环体)
}
<script>
while (true){
console.log('我死了')
}
</script>
循环需要具备3个要素
- 变量初始值
- 终止条件
- 计数器
// i=1 为变量初始值
let i = 1
// i<=3为终止条件
while (i <= 3) {
document.write(`我会循环3次<br>`)
// i的累加为计数器
i++
}
案例:计算1到100,所有偶数的和
<script>
let i = 0
let sum = 0
while (i <= 100) {
if (!(i%2)) {
sum += i
}
i++
}
document.write(sum)
</script>
<script>
let i = 0
let sum = 0
while (i <= 100) {
sum += (i % 2 ? 0 : i)
i++
}
document.write(sum)
</script>
8.4 循环的退出
continue 和 break
continue是进行下一次循环;break是跳出循环
<script>
let i = 1
while (i<=6) {
if (i===3){
// 注意i++一定要写在continue的前面
i++
continue
}
document.write(`我再吃第${i}个包子<br>`)
i++
}
</script>
★重点案例:
需求:用户可以选择存钱,取钱,查看余额和退出
<script>
let money = 0
while (true) {
let str = prompt(`请选择操作:
1. 存钱
2. 取钱
3. 查看余额
4. 退出`)
if (str === '4') {
alert('再见')
break
} else if (str === '1') {
let num = +prompt(`请输入存入金额:`)
money += num
} else if (str === '2') {
let num = +prompt(`请输入取钱金额:`)
money -= num
} else if (str === '3') {
alert(`您的账户余额为${money}`)
}
}
</script>
8.5 for循环
8.5.1 for循环基本使用
while循环有3个循环要素,起始值,计数器,终止条件。
for循环:将循环的三要素写在一起,开发中一般都是使用for循环
for循环的语法:
for (声明记录循环次数的变量;循环条件;变化值) {
循环体
}
<script>
for (let i = 1;i<=10;i++) {
document.write(`月薪过万<br>`)
}
</script>
案例:计算0~100的偶数和
<script>
let sum = 0
for (let num=0;num<=100;num++) {
sum += num % 2 ? 0 : num
}
document.write(`sum:${sum}`)
</script>
for循环最大的价值是循环数组
let arr = ['马超','赵云','张飞','关羽','黄忠']
// arr.length 数组的长度
for (let i = 0 ; i< arr.length ; i++) {
document.write(`${arr[i]}<br>`)
}
8.5.1 退出循环
continue和break<详见while循环的continue和break>
8.5.2 循环嵌套
语法:
for (外部声明记录循环次数的变量;循环条件;变化值) {
for (内部声明记录循环次数的变量;循环条件;变化值) {
循环体
}
}
★**重点案例:九九乘法表**
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
span{
display:inline-block;
padding:5px 10px;
border:1px solid black;
margin:2px;
border-radius: 5px;
}
</style>
</head>
<body>
<script>
for (i = 1; i <= 9; i++) {
for (j = 1; j <= i; j++) {
result = i * j < 10 ? '0' + (i * j) : i * j
document.write(`<span>${i}×${j}=${result}</span>`)
}
document.write(`<br>`)
}
</script>
</body>
</html>
display: inline-block;
:允许元素既具有内联元素的特性(如与其他元素保持在同一行内),又具有块级元素的特性(如能够设置宽度、高度和其他盒模型属性)。
9 数组
9.1 数组是什么
array:是一种可以按照顺序保存数据的数据类型
9.2 数组的基本使用
-
申明数组
方式1:
let arr = [数据1,数据2,... ,数据3]
方式2:构造函数的方式
let arr = new Array(数据1,数据2,... ,数据3)
数组中,数据的编号叫索引或下标
-
术语:
- 元素
- 下标
- 长度:arr.length
-
遍历数组:使用for循环
for (let i = 0; i<arr.length; i++) { arr[i] }
案例1:数组求和,求[2,6,1,7,4]里面所有元素的和与平均值
<script> let arr = [2,6,1,7,4] let sum = 0 for (let i = 0; i<arr.length;i++) { sum += arr[i] } document.write(`sum=${sum}<br>aver=${sum/arr.length}`) </script>
案例2:求数组中最大值 [2,6,1,77,52,25,7]
<script> let arr = [2,6,1,77,52,25,7] max_num = arr[0] for (let i =1 ; i< arr.length;i++){ max_num = arr[i]>max_num? arr[i]:max_num } document.write(max_num) </script>
9.3 操作数组
类型 | 位置 | 关键字 |
---|---|---|
添加 | 开始 | unshift |
添加 | 末尾 | push |
删除 | 开始 | shift |
删除 | 末尾 | pop |
删除 | 指定位置,并且指定删除个数 | splice(start,deletecount) |
数组的增删改查:
-
数据的修改
arr[0]='lightpink'
-
数据的增加
-
push:将一个或多个元素添加到数组的末尾,并返回数组的新长度
arr.push(元素1,元素2,...,元素n)
<script> let arr = ['red', 'green'] let new_length = arr.push('pink') document.write(arr) document.write(new_length) </script>
-
unshift:与push基本相同,就是将元素放置在数组的开头
案例:将数组[2,0,6,1,77,0,52,6,19,7,92,9,10]中大于等于10的元素选出来,放入新数组
<script> let arr = [2,0,6,1,77,0,52,6,19,7,92,9,10] let brr = [] for (let i = 0;i<arr.length;i++) { if (arr[i]>=10) { brr.push(arr[i]) } } document.write(brr) </script>
-
-
删除数组中的数据
-
arr.pop()
从数组中删除最后一个元素,并返回删除的值
-
arr.shift()
从数组中删除第一个元素
-
arr.splice(start,deletecount)
从start位置开始,删除deletecount个数,如果不指定,就是从start开始,后面全部删除。
-
10 函数
10.1 函数使用
-
函数声明的基本语法
函数名的命名规范与变量名的命名方式一样
function 函数名(){ 函数体 }
例如:
<script> function sayHi(){ document.write('say,hi') } // 函数的调用 sayHi() </script>
-
函数的调用
正常写法为先声明后调用
10.3 函数传参
语法:
function 函数名(参数列表) {
函数体
}
例如:求两个数的和
<script>
function getSum(num1,num2){
let sum = 0
sum = num1 + num2
document.write(sum)
}
getSum(1,2)
</script>
形参与实参:函数声明中的参数为形参。实参为调用函数时,传入的参数
注意:函数的形参与实参的个数尽量相同,但如果不同,javascript也不会报错。这种情景一般分为3种情况
-
形参个数大于实参个数
function fn(x,y){ console.log(x+y) } fn(1)
这种情况返回的时Nan。因为x被赋值为1,y没有被赋值,y就是一个undefined。因此相加之后不是一个数字
-
形参个数小于实参个数
function fn(x,y){ console.log(x+y) } fn(1,2,3)
这种情况返回3,因为fn中只有2个变量可以接受1,2.
对于这种情况有一个不推荐的方式就是在函数体内调用arguments
<script>
function fn(){
console.log(arguments)
}
fn(1,2,3)
</script>
网页的控制台中,arguments返回的时一个伪数组arguments(3)
它与一般的数组的区别是没有push pop等操作。但是也可以进行遍历
案例:传入一个学生的分数的数组,求总分
<script>
let scores = [60,60,70,80,90,100];
function add(arr){
let ttl = 0;
for(i=0;i<arr.length;i++){
ttl += arr[i]
}
console.log(ttl)
}
add(scores);
</script>
10.3 函数返回值
关键字:return
语法:return 数据
function 函数名(参数列表) {
函数体
return ...
}
例如
<script>
function getSum(x,y){
return x + y
}
</script>
let num = getSum(10,30)
document.write(sum)
- return有退出函数的作用
- 函数没有return或者只写一个return,默认返回的时undefined
10.3.1 turn返回多个值
如果需要返回多个值,可以return一个数组
<script>
function fn(x,y) {
let jia = x+y
let jian = x-y
return [jia,jian]
}
</script>
10.3.2 return 与三元表达式
例如:输入2个数字,就最大值
以下代码是正确的:
<script>
let num1 = +prompt('请输入第一个数字:')
let num2 = +prompt('请输入第二个数字:')
function getMax(x,y) {
return x>y? x:y
}
</script>
以下代码是错误的,因为短接的问题
<script>
let num1 = +prompt('请输入第一个数字:')
let num2 = +prompt('请输入第二个数字:')
function getMax(x,y) {
x>y ? return x:return y
}
</script>
错误的原因是return具有短路性,只要执行了第一个return x,后面的所有代码就不会再执行,因此电脑会认为是语法错误,写错了。
10.4 作用域
例如下面的代码
for(let i = 0;i<3;i++){
document.write('怎么回事呢?')
}
console.log(i)
控制台会显示Uncaught ReferenceError: i is not defined
或者如下代码
function fun(){
let num2 = 20
}
fun()
console.log(num2)
控制台会显示Uncaught ReferenceError: num2 is not defined
10.4.1 作用域的概述
通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字的冲突。
作用域的分类:
- 全局有效:整个script标签内部
- 局部有效:函数内有效
- 块级有效:{}内,比如if for 内部。
10.4.2 变量的作用域
内部可以访问外部作用域的变量,但是外部不能直接访问内部的变量
-
全局变量:scirpt范围内
<script> // 1.全局变量 全局能用 let num = 10 console.log(num) function fn() { console.log(num) } fn() if (true){ console.log(num) } </script>
-
局部变量:函数范围内
<script> function fn(){ let num=10 function fn1(){ console.log(num) //可以调用 let num2 = 20 } fn1() console.log(num2) //会报错:num is not defined } fn() console.log(num) //会报错:num is not defined </script>
-
块级变量:语句范围内
<script> if (true) { let num =10 } console.log(num) //会报错:num is not defined </script>
例外的情况
在函数与块级作用域内,如果变量没有声明,直接进行赋值。这个变量就是全局变量。但是强烈不推荐
<script>
function fn(){
num = 10
}
console.log(num) //这个可以访问到
</script>
10.4.3 作用域链
就近原则:调用变量时,先在当前作用域进行查找。如果当前作用域里面没有,就找上一层作用域。逐层向上查找。如果都找不到,就显示undefined
<script>
let num =10
function fn(){
let num = 20
console.log(num)
}
</script>
10.5 匿名函数
匿名函数就是没有名字的函数。 匿名函数也称为函数表达式
javascript的函数分类
-
具名函数
function fn(){}
-
匿名函数:也称作为函数表达式
function (){}
匿名函数的语法规范:
let fn = function (x,y) {
// 函数体
console.log(x+y)
}
调用
fn(1,2)
注意:如果function(){}
前面不用变量接收,则会直接报错
10.6 立即执行函数
不需要调用,直接可以执行
立即执行函数的优点:由于作用域的关系,写在立即执行函数中的变量,不会与外面的变量存在重复声明的问题。变量不会被污染。
立即执行函数有2种语法,以下2种方式在运行的效果上没有什么区别。
-
第一种:
(function(){})()
-
第二种
(function(){代码体}())
注意:多个立即执行函数之间必须使用分号进行分隔
(function () {console.log(11)}()); //不加这个分号会报错
(function () {console.log(22)}())
11 对象
11.1 什么是对象
-
对象:object是javascript里的一种数据类型
-
可以理解为一种无序的数据类型
-
用来详细的描述一个【实体】
-
一个对象可以有静态特征(属性)和动态行为(方法)
11.2 对象使用
-
对象声明语法
let 对象名 = {}
例如:
let person = {}
-
对象有属性和方法组成
let 对象名 = { 属性名:属性 方法名:函数 // 函数使用匿名函数 }
-
属性
属性名可以使用
""
或''
,一般情况下省略,除非名称遇到特殊符号,如空格,中横线等。json就必须添加引号了。let person = { name:'刘德华', age:18, sex:'男' }
-
对象属性的2种访问方法
方式1
console.log(person.name)
方式2
console.log(person['name'])
注意第二种方式2,中括号中的属性名需要追加单引号
-
对象的方法
对象的方法需要使用匿名函数
let person = { name : 'andy', sayHi : function(){ //匿名函数 document.write('hi~~~') } }
例如:
<script> let person = { 'name':'刘德华', age:18, sex:'男', sayHi:function (){ console.log('hi') }, mtv:function (mtv_name){ person.age++ //在方法中,可以对自己的属性进行修改 return `出演了${mtv_name}` } } console.log(person.name) person.sayHi() str = person.mtv('无间道') document.write(str) document.write(`<br>`) document.write(person.age) </script>
-
对象方法的调用
person.sayHi() // 注意要加小括号 str = person.mtv('无间道') document.write(str)
11.3 操作对象
对象的操作也是增删改查
-
增:
增的方法与改的方法是一样的。直接使用对象.新属性的方法进行增加
-
修改:
使用对象.属性的方法进行修改
-
查:<详见之前对象属性的访问方法>注意有2种方法
第二种方法更加常用,后面遍历对象时,使用第二种方法。
-
删除:(很少使用,了解就好,最新的语法其实是不允许的)
关键字:delete
delete obj.uname console.dir(obj)
11.4 遍历对象(for in 语句)
假如我们需要获取对象的所有属性
问题:
- 对象没有length属性。
- 对象是无序的。
因此为了遍历对象,我们有了新的遍历对象的语句for in
结构的语句
语法:
for (let i in obj) {
循环体
}
例如下面的代码
let obj = {
uname : 'andy',
age:'18',
sex:'男'
}
for (let k in obj) { // 开发一般使用k,是key的缩写
console.log(k) // 打印属性名
console.log(obj[k]) // 打印属性,注意一定使用中括号
}
注意:打印属性的时候一定要使用中括号,否则会提示undefined。
案例:学生信息表
11.5 内置对象
11.5.1 内置对象是什么
JavaScript内部提供的对象,包含各种属性和方法给开发者调用
11.5.2 内置对象Math
随机数:0~1之间取随机数
Math.random()
取整函数
Math.ceil(1.5) // 2 向上取整
Math.floor(1.5) // 2 向下取整
Math.round(1.5) // 2 四舍五入,往大取整
最大值与最小值
Math.max(1,5,9,45) // 注意:数组不能求最大值
Math.min(1,5,9,45) // 注意:数组不能求最大值
11.5.3 随机数
// 生成0~10的随机数
Math.floor(Math.random()*(10+1))
// 生成N~M之间的随机数
Math.floor(Math.random()*(M-N+1)) + N
将N~M之间的随机数封装成函数
<script>
function getRandomInt(min,max){
let result = Math.floor(Math.random()*(max - min + 1)) + min
return result
}
console.log(getRandomInt(5,10))
</script>
案例:随机点名案例
需求:请把[‘赵云’,‘黄忠’,‘关羽’,‘张飞’,‘马超’,‘刘备’,‘曹操’]随机显示一个名字到页面上
<script>
function getRandomInt(min,max) {
return Math.floor(Math.random()*(max-min+1)) + min
}
function getRandomName(name_list) {
let counter = name_list.length
let random_num = getRandomInt(0,counter-1)
return name_list[random_num]
}
let name_array = ['赵云','黄忠','关羽','张飞','马超','刘备','曹操']
let name = getRandomName(name_array)
document.write(name)
</script>
关键案例:数组重新排列
关键点:深复制与浅复制
<script>
function shuffer(array){
/*如果是let temparr = array,这不是赋值,而是将temparr指向array的内存
最后的结果就是name_array 与 newArr是一样的
数组前面加三个... 就是浅拷贝的意思
*/
let temparr = [...array]
for(let i=temparr.length-1;i>0;i--) {
const j = Math.floor(Math.random()*(i+1))
let temp = temparr[i]
temparr[i] = temparr[j]
temparr[j] = temp
}
return temparr
}
let name_array = ['赵云', '黄忠', '关羽', '张飞', '马超', '刘备', '曹操']
newArr = shuffer(name_array)
document.write(`${name_array}<br>${newArr}`)
</script>
拓展
术语解释
术语 | 解释 | 举例 |
---|---|---|
关键字 | 在js中有特殊意义的词汇 | let、var、function、if、else、for、switch等 |
保留字 | 将来可能会变为关键字的词汇 | int,short,long,char |
标识(标识符) | 变量名,函数名的另一种叫法 | |
表达式 | 可以产生value的代码 | |
语句 | 一句代码也称为一条语句,一般按用途还会分类: 输出语句,声明语句,分支语句,循环语句 |
基本数据类型和引用数据类型
以下以及堆与栈的区别复听为百度网板中 js中的《简单和引用数据类型及作业》
-
基本数据类型:值类型
如string,number,boolean,undefined,null
基本数据类型存放的是值
-
引用类型:复杂数据类型,在存储时,变量中存储的仅仅是地址(引用),因此叫做引用数据类型
通过new关键字创建的对象,如object,array,Date等
堆与栈的区别
-
栈(操作系统):由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈;
简单的数据存放在栈中
-
堆(操作系统):存储复杂类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。
引用数据类型存放在堆里面
简单数据类型与引用数据类型的存放机制
-
简单数据类型就是在栈中存放了一个值
-
引用数据类型是在堆中存放数据,在栈中存放了一个指向堆的一个地址