JavaScript

一、JavaScript基础

1、JavaScript 介绍

1.1 JavaScript 是什么

是一种运行在客户端(浏览器)的编程语言,实现人机交互效果。

作用(做什么?)

(1)–网页特效 (监听用户的一些行为让网页作出对应的反馈)

(2)–表单验证 (针对表单数据的合法性进行判断)

(3) –数据交互 (获取后台的数据, 渲染到前端) ajax

(4) –服务端编程 (node.js)

JavaScript的组成(有什么?)

1
2
3
4
5
6
7
ECMAScript:
规定了js基础语法核心知识。
比如:变量、分支语句、循环语句、对象等等
Web APIs :
DOM 操作文档,比如对页面元素进行移动、大小、添加删除等操作
BOM 操作浏览器,比如页面弹窗,检测窗口宽度、存储数据到浏览器等等

JavaScript****权威网站: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript

1.2 JavaScript 书写位置

内部 JavaScript

1
2
3
4
直接写在html文件里,用script标签包住

规范:script标签写在</body>上面

我们将 <script> 放在HTML文件的底部附近的原因是浏览器会按照代码在文件中的顺序加载 HTML

如果先加载的 JavaScript 期望修改其下方的 HTML,那么它可能由于 HTML 尚未被加载而失效。

因此,将 JavaScript 代码放在 HTML页面的底部附近通常是最好的策略。

1
2
3
4
5
6
7
<body>
<!-- 内部js -->
<script>
// 页面弹出警示框
alert('你好,js~')
</script>
</body>

外部 JavaScript

代码写在以.js结尾的文件里

语法:通过script标签,引入到html页面中。

注意:script标签中间无需写代码,否则会被忽略!

1
2
3
4
5
6
<body>
<script src="./js/my.js">
// 中间不要写内容
</script>
</body>

内联 JavaScript

代码写在标签内部

1
2
3
4
5
<body>
<button onclick="alert('hello')"> hello
</button>
</body>

1.3 JavaScript 的注释

单行注释

1
2
3
4
符号://
作用://右边这一行的代码会被忽略
快捷键:ctrl + /

块注释

1
2
3
4
符号:/*  */
作用:在/* 和 */ 之间的所有内容都会被忽略
快捷键:shift + alt + A

1.4 JavaScript 结束符

1
2
3
4
5
6
结束符
作用: 使用英文的 ; 代表语句结束
实际情况: 实际开发中,可写可不写, 浏览器(JavaScript 引擎) 可以自动推断语句的结束位置
现状: 在实际开发中,越来越多的人主张,书写 JavaScript 代码时省略结束符
约定:为了风格统一,结束符要么每句都写,要么每句都不写(按照团队要求.)

1.5 JavaScript 输入输出语法

2、变量

2.1 变量基本使用

1
2
3
4
5
6
7
8
9
10
11
12
13
<script>
// 1. 声明一个年龄变量
// let age
// // 2. 赋值 = 赋值
// age = 18
// console.log(age)
// 3. 声明的同时直接赋值 变量的初始化
// let age = 18
let num = 20
let uname = '张三'
console.log(num)
console.log(uname)
</script>

注意:let关键字不允许多次声明一个变量

1
2
3
let age = 18;
let age = 20;
console.log(age); // 会报错,不允许多次声明age变量

声明多个变量:

语法:多个变量中间用逗号隔开。

1
let age = 18, uname = "zhangsan"

说明:看上去代码长度更短,但并不推荐这样。为了更好的可读性,请一行只声明一个变量。

2.2 变量命名规则与规范

1
2
3
4
5
6
7
8
9
10
1. 规则:
不能用关键字
关键字:有特殊含义的字符,JavaScript 内置的一些英语词汇。例如:let、var、if、for等
只能用下划线、字母、数字、$组成,且数字不能开头
字母严格区分大小写,如 Age 和 age 是不同的变量
2. 规范:
起名要有意义
遵守小驼峰命名法
第一个单词首字母小写,后面每个单词首字母大写。例:userName

2.3 let和var的区别

1
2
3
4
5
6
7
8
在较旧的JavaScript,使用关键字 var 来声明变量 ,而不是 let。
var 现在开发中一般不再使用它,只是我们可能再老版程序中看到它。
let 为了解决 var 的一些问题。
var 声明:
可以先使用 在声明 (不合理)
var 声明过的变量可以重复声明(不合理)
比如变量提升、全局变量、没有块级作用域等等

2.4 数组

一种将 一组数据存储在单个变量名下 的优雅方式

1. 声明语法

1
let 数组名 = [数据1,数据2,...,数据n]
1
let arr = [10, 20, 30]

数组是按顺序保存,所以每个数据都有自己的编号

计算机中的编号从0开始,所以小明的编号为0,小刚编号为1,以此类推

在数组中,数据的编号也叫索引或下标

数组可以存储任意类型的数据

2. 取值语法

1
数组名[下标]
1
2
3
4
5
6
7
8
let arr = ['刘德华', '张学友', '黎明', '郭富城', '张三', 10]
// 2. 使用数组 数组名[索引号] 从0
// console.log(arr)
console.log(arr[0]) // 刘德华
console.log(arr[4])

// 3. 数组长度 = 索引号 + 1
console.log(arr.length) // 6

2.5 常量

使用 const 声明的变量称为“常量”。

使用场景:当某个变量永远不会改变的时候,就可以使用 const 来声明,而不是let。

命名规范:和变量一致

1
2
3
4
5
6
7
8
9
<script>
// 1.常量 不允许更改值
// const PI = 3.14
// console.log(PI)
// PI = 3.15
// console.log(PI)
// 2. 常量声明的时候必须赋值
// const PI
</script>

2.6 数据类型

基本数据类型(简单/基础)

1
2
3
4
5
6
number 数字型
string 字符串型
boolean 布尔型
undefined 未定义型
null 空类型

引用数据类型(复杂类型,)

1
object 对象,函数,数组

数字类型(Number)

JavaScript 中的正数、负数、小数等 统一称为 数字类型

1
2
3
JS 是弱数据类型,变量到底属于那种类型,只有赋值之后,我们才能确认
C#是强数据类型 例如 int a = 3 必须是整数

1
2
3
4
5
6
7
8
9
数字可以有很多操作,比如,乘法 * 、除法 / 、加法 + 、减法 - 等等,所以经常和算术运算符一起。
数学运算符也叫算术运算符,主要包括加、减、乘、除、取余(求模)。
+:求和
-:求差
*:求积
/:求商
%:取模(取余数) 开发中经常作为某个数字是否被整除


1
2
3
4
5
6
7
JavaScript中 优先级越高越先被执行,优先级相同时以书从左向右执行。
乘、除、取余优先级相同
加、减优先级相同
乘、除、取余优先级大于加、减
使用 () 可以提升优先级
总结: 先乘除后加减,有括号先算括号里面的~~~

NaN Not a Number)代表一个计算错误。它是一个不正确的或者一个未定义的数学操作所得到的结果

任何对 NaN 的操作都会返回 NaN

1
2
3
4
console.log(NaN - 2)
console.log(NaN + 2)
console.log(NaN / 2)
console.log(NaN === NaN)

字符串类型(string)

通过单引号( ‘’) 、双引号( “”)或反引号( ` ) 包裹的数据都叫字符串,单引号和双引号没有本质上的区别,推荐使用单引号。

注意事项:

  1. 无论单引号或是双引号必须成对使用

  2. 单引号/双引号可以互相嵌套,但是不以自已嵌套自已

  3. 必要时可以使用转义符 \,输出单引号或双引号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// let str = 'zhangsan'
// let str1 = "zhangsan"
// let str2 = `中文`
// console.log(str2)
// console.log(11)
// console.log(`11`)
// console.log(str)
// console.log('str')
// console.log('hello"world"')
// console.log("hello'world'")
// console.log('hello\'world\'')
// 字符串拼接
// console.log(1 + 1)
// console.log('hello' + 'world')

let age = 25

// document.write('我今年' + 19)
// document.write('我今年' + age)
// document.write('我今年' + age + '岁了')
document.write('我今年' + age + '岁了')

模板字符串

使用场景

拼接字符串和变量

在没有它之前,要拼接变量比较麻烦

语法

1
2
3
4
5
6
7
`` (反引号)

在英文输入模式下按键盘的tab键上方那个键(1左边那个键)

内容拼接变量时,用 ${ } 包住变量


布尔类型(boolean)

表示肯定或否定时在计算机中对应的是布尔类型数据。

它有两个固定的值 true false,表示肯定的数据用 true(真),表示否定的数据用 false(假)。

1
2
3
// console.log(3 > 4)
// let isCool = false
// console.log(isCool)

未定义类型(undefined)

未定义是比较特殊的类型,只有一个值 undefined

什么情况出现未定义类型?

只声明变量,不赋值的情况下,变量的默认值为 undefined,一般很少【直接】为某个变量赋值为 undefined

null(空类型)

JavaScript 中的null仅仅是一个代表“无”、“空”或“值未知”的特殊值

1
2
3
4
null 和 undefined 区别:
undefined 表示没有赋值
null 表示赋值了,但是内容为空

null开发中的使用场景

1
2
将来有个变量里面存放的是一个对象,但是对象还没创建好,可以先给个null 

1
2
3
4
5
6
7
8
9
10
11
12
13
// 1. true  false 是布尔型字面量  
// console.log(3 > 4)
// let isCool = false
// console.log(isCool)
// 2. 未定义类型 弱数据类型 声明一个变量未赋值就是 undefined
// let num
// console.log(num)
// 3. null 空的
// let obj = null
// console.log(obj)
// 计算有区别
console.log(undefined + 1) // NaN
console.log(null + 1) // 1

2.7 检测数据类型

通过 typeof 关键字检测数据类型

typeof 运算符可以返回被检测的数据类型。它支持两种语法形式:

1
2
3
第一种:作为运算符: typeof x (常用的写法)
第二种:函数形式: typeof(x)

1
2
3
4
5
6
7
8
9
10
11
12
let num = 10
console.log(typeof num)
let str = 'zhangsan'
console.log(typeof str)
let str1 = '10'
console.log(typeof str1)
let flag = false
console.log(typeof flag)
let un
console.log(typeof (un))
let obj = null
console.log(typeof obj)

2.8 类型转换

JavaScript是弱数据类型: JavaScript也不知道变量到底属于那种数据类型,只有赋值了才清楚。

注意: 使用表单、prompt 获取过来的数据默认是字符串类型的,此时就不能直接简单的进行加法运算。

此时需要转换变量的数据类型。

通俗来说,就是把一种数据类型的变量转换成我们需要的数据类型。

隐式转换

1
2
3
4
5
某些运算符被执行时,系统内部自动将数据类型进行转换,这种转换称为隐式转换。
规则:
+ 号两边只要有一个是字符串,都会把另外一个转成字符串
除了+以外的算术运算符 比如 - * / 等都会把数据转成数字类型

1
2
3
+号作为正号解析可以转换成数字型
任何数据和字符串相加结果都是字符串

显式转换

编写程序时过度依靠系统内部的隐式转换是不严禁的,因为隐式转换规律并不清晰,大多是靠经验总结的规律。

为了避免因隐式转换带来的问题,通常根逻辑需要对数据进行显示转换。

1
2
3
4
5
6
7
8
9
10
11
12
概念:
自己写代码告诉系统该转成什么类型
转换为数字型
Number(数据)
转成数字类型
如果字符串内容里有非数字,转换失败时结果为 NaN(Not a Number)即不是一个数字
NaN也是number类型的数据,代表非数字
parseInt(数据)
只保留整数
parseFloat(数据)
可以保留小数

1
2
3
4
转换为字符型:
String(数据)
变量.toString(进制)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let str = '123'
console.log(Number(str))
console.log(Number('zhangsan'))
// let num = Number(prompt('输入年薪'))
// let num = +prompt('输入年薪')
// console.log(Number(num))
// console.log(num)
console.log(parseInt('12px'))
console.log(parseInt('12.34px'))
console.log(parseInt('12.94px'))
console.log(parseInt('abc12.94px'))

// -------------------
console.log(parseFloat('12px')) // 12
console.log(parseFloat('12.34px')) // 12.34
console.log(parseFloat('12.94px')) // 12.94
console.log(parseFloat('abc12.94px')) //

3、运算符

3.1 赋值运算符

已经学过的赋值运算符:=

1
2
3
4
5
6
+=
-=
*=
/=
%=

1
2
3
4
5
6
7
8
9
<script>

let num = 1
// num = num + 1
// 采取赋值运算符
// num += 1
num += 3
console.log(num)
</script>

3.2 一元运算符

众多的 JavaScript 的运算符可以根据所需表达式的个数,分为一元运算符、二元运算符、三元运算符

二元运算符:

1
let num = 10 + 20

一元运算符:

例: 正负号

1
2
3
4
5
6
7
8
9
10
11
12
13
// // 1. 前置自增
// let i = 1
// ++i
// console.log(i)

// let i = 1
// console.log(++i + 1)
// 2. 后置自增
// let i = 1
// i++
// console.log(i)
// let i = 1
// console.log(i++ + 1)

l自增:

符号:++

作用:让变量的值 +1

l自减:

符号:–

作用:让变量的值 -1

1.前置自增和后置自增独立使用时二者并没有差别!

2.一般开发中我们都是独立使用

3.3 比较运算符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
> :    左边是否大于右边
<: 左边是否小于右边
>=: 左边是否大于或等于右边
<=: 左边是否小于或等于右边
==: 左右两边值是否相等
===: 左右两边是否类型和值都相等
!==: 左右两边是否不全等
比较结果为boolean类型,即只会得到 true 或 false


= 单等是赋值
== 是判断
=== 是全等
开发中判断是否相等,强烈推荐使用 ===

1
2
3
4
5
6
7
字符串比较,是比较的字符对应的ASCII码
从左往右依次比较
如果第一位一样再比较第二位,以此类推
NaN不等于任何值,包括它本身
涉及到"NaN“ 都是false


3.4 逻辑运算符

1
2
3
4
5
6
提问:如果我想判断一个变量 num 是否大于5且小于10,怎么办?
错误写法: 5 < num < 10

使用场景:逻辑运算符用来解决多重条件判断
正确写法: num > 5 && num < 10

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
console.log(3 > 5)
console.log(3 >= 3)
console.log(2 == 2)
// 比较运算符有隐式转换 把'2' 转换为 2 双等号 只判断值
console.log(2 == '2') // true
// console.log(undefined === null)
// === 全等 判断 值 和 数据类型都一样才行
// 以后判断是否相等 请用 ===
console.log(2 === '2')
console.log(NaN === NaN) // NaN 不等于任何人,包括他自己
console.log(2 !== '2') // true
console.log(2 != '2') // false
console.log('-------------------------')
console.log('a' < 'b') // true
console.log('aa' < 'ab') // true
console.log('aa' < 'aac') // true
console.log('-------------------------')

3.5 运算符优先级

一元运算符里面的逻辑非优先级很高

逻辑与比逻辑或优先级高

4、语句

4.1 表达式和语句

表达式是可以被求值的代码,JavaScript 引擎会将其计算出一个结果。

语句:

语句是一段可以执行的代码。

比如: prompt() 可以弹出一个输入框,还有 if语句 for 循环语句等等

1
2
3
4
5
6
7
区别:
表达式:因为表达式可被求值,所以它可以写在赋值语句的右侧。
表达式 num = 3 + 4
语句:而语句不一定有值,所以比如 alert() for和break 等语句就不能被用于赋值。
语句 alert() 弹出对话框 console.log() 控制台打印输出
某些情况,也可以把表达式理解为表达式语句,因为它是在计算结果,但不是必须的成分 (例如continue语句)

4.2 分支语句

if语句有三种使用:单分支、双分支、多分支

单分支使用语法:

1
2
3
4
括号内的条件为true时,进入大括号里执行代码
小括号内的结果若不是布尔类型时,会发生隐式转换转为布尔类型
如果大括号只有一个语句,大括号可以省略,但是,俺们不提倡这么做~

双分支if语法:

多分支if语法:

4.3 三元运算符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script>
// 三元运算符
// 条件 ? 代码1 : 代码2
// console.log(3 > 5 ? 3 : 5)
// if (3 < 5) {
// alert('真的')
// } else {
// alert('假的')
// }
// 3 < 5 ? alert('真的') : alert('假的')

let sum = 3 < 5 ? 3 : 5
console.log(sum)
</script>

4.4 switch 语句

找到跟小括号里数据全等的case值,并执行里面对应的代码

若没有全等 === 的则执行default里的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script>
switch (2) {
case 1:
console.log('您选择的是1')
break // 退出switch
case 2:
console.log('您选择的是2')
break // 退出switch
case 3:
console.log('您选择的是3')
break // 退出switch
default:
console.log('没有符合条件的')
}
</script>

4.5 循环语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<script>
// // 1. 变量的起始值
// let i = 1
// // 2. 终止条件
// while (i <= 3) {
// document.write('我要循环三次 <br>')
// // 3. 变量的变化量
// i++
// }
// 1. 变量的起始值
let end = +prompt('请输入次数:')
let i = 1
// 2. 终止条件
while (i <= end) {
document.write('我要循环三次 <br>')
// 3. 变量的变化量
i++
}

</script>

continue:结束本次循环,继续下次循环

break:跳出所在的循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<script>
// let i = 1
// while (i <= 5) {
// console.log(i)
// if (i === 3) {
// break // 退出循环
// }
// i++

// }


let i = 1
while (i <= 5) {
if (i === 3) {
i++
continue
}
console.log(i)
i++

}
</script>

4.6 循环-for

1
2
3
while(true) 来构造“无限”循环,需要使用break退出循环。
for(;;) 也可以来构造“无限”循环,同样需要使用break退出循环。

1
2
3
4
5
6
7
8
9
10
11
12
13
// 1. 输出1~100岁
// for (let i = 1; i <= 100; i++) {
// document.write(`今年我${i}岁了 <br>`)
// }
// 2. 求1~100之间的偶数和
// let sum = 0
// for (let i = 1; i <= 100; i++) {
// if (i % 2 === 0) {
// // 把i加到sum里面去
// // sum = sum + i
// sum += i
// }
// }

4.7 for 循环嵌套

1
2
3
4
5
6
7
8
9
// // 外层循环打印行数
// for (let i = 1; i <= 5; i++) {
// // 里层循环打印几个星星
// for (let j = 1; j <= 5; j++) {
// document.write('☆')
// }
// // 进行换行显示
// document.write('<br>')
// }

打印直角三角形

1
2
3
4
5
6
7
8
9
10
11
12
<script>
// 1. 外层循环控制行数
for (let i = 1; i <= 5; i++) {
// 2. 里层循环控制列数(几个星星)
for (let j = 1; j <= i; j++) {
document.write('◆')
}
// 换行
document.write('<br>')
}

</script>

打印乘法口诀表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
span {
display: inline-block;
width: 100px;
padding: 5px 10px;
border: 1px solid pink;
margin: 2px;
border-radius: 5px;
box-shadow: 2px 2px 2px rgba(255, 192, 203, .4);
background-color: rgba(255, 192, 203, .1);
text-align: center;
color: hotpink;
}
</style>
</head>

<body>

<script>
// 1. 外层循环控制行数
for (let i = 1; i <= 9; i++) {
// 2. 里层循环控制列数
for (let j = 1; j <= i; j++) {
document.write(`<span>${j} X ${i} = ${i * j}</span>`)
}
// 换行
document.write('<br>')
}

</script>
</body>

</html>

5、 数组

5.1 遍历数组

需求:求数组 [2,6,1,7, 4] 里面所有元素的和以及平均值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<script>
let arr = [2, 6, 1, 7, 4]
// 1. 求和的变量 sum
let sum = 0
// 2.遍历累加
for (let i = 0; i < arr.length; i++) {
// console.log(arr[i])
// sum = sum + arr[i]
sum += arr[i]
}
console.log(`数组的和的结果是: ${sum}`)
// 3. 平均值 和 / arr.length = 4
console.log(`数组的平均值结果是: ${sum / arr.length}`)


// sum = sum + arr[0]
// console.log(sum)
</script>

5.2 操作数组

5.2.1 新增

·数组.push() 方法将一个或多个元素添加到数组的末尾,并返回该数组的新长度 (重点)

语法:

arr.unshift(新增的内容) 方法将一个或多个元素添加到数组的开头,并返回该数组的新长度

1
2
3
4
5
6
7
8
9
10
11
<script>
let arr = ['zhangsan', 'lisi']
// 新增 push 推末尾
// console.log(arr.push('wangwu')) // 3
// arr.push('maliu', 'laowang')
// console.log(arr)
// 开头追加
arr.unshift('red')
console.log(arr)
</script>

5.2.2 删除

数组. shift() 方法从数组中删除第一个元素,并返回该元素的值

语法:

数组. pop() 方法从数组中删除最后一个元素,并返回该元素的值

语法:

数组. splice() 方法 删除指定元素

语法:

1
2
3
4
5
6
7
解释:
start 起始位置:
指定修改的开始位置(从0计数)
deleteCount:
表示要移除的数组元素的个数
可选的。 如果省略则默认从指定的起始位置删除到最后

6、函数

6.1 为什么需要函数

1
2
3
4
5
6
7
函数: 
function,是被设计为执行特定任务的代码块
说明:
函数可以把具有相同或相似逻辑的代码“包裹”起来,通过函数调用执行这些被“包裹”的代码逻辑,这么做的优势是有利于精简代码方便复用。
比如我们前面使用的 alert() 、 prompt() 和 console.log() 都是一些 js 函数,只不过已经封装好了,我们直接使用的。


6.2 函数使用

函数的声明语法

函数名命名规范

和变量命名基本一致

尽量小驼峰式命名法

前缀应该为动词

命名建议:常用动词约定

函数的调用语法

注意:声明(定义)的函数必须调用才会真正被执行,使用 () 调用函数

函数体

函数体是函数的构成部分,它负责将相同或相似代码“包裹”起来,直到函数调用时函数体内的代码才会被执行。函数的功能代码都要写在函数体当中。

6.3 函数传参

这样的函数只能求 10 + 20, 这个函数功能局限非常大

1
2
3
4
5
参数列表
传入数据列表
声明这个函数需要传入几个数据
多个数据用逗号隔开

例如:

1
2
3
function getSum(num1){
console.log(num1+3);
}

上面是单个参数,

如果是多个参数

1
2
3
function setSum(num1,num2){
console.log(num1+num2);
}

在调用函数的时候,也是需要传递参数的。

调用语法:

1
函数名(传递的参数列表)
1
2
3
4
function setSum(num1,num2){
console.log(num1+num2);
}
getSum(10,20);// 10传递给了num1,20传递给了num2,相当于给num1和num2两个变量赋值

上面定义的num1,num2两个参数是形参,而在调用getSum函数的时候,传递的10,20是实参

1
2
3
4
5
形参:声明函数时写在函数名右边小括号里的叫形参(形式上的参数)
实参:调用函数时写在函数名右边小括号里的叫实参(实际上的参数)
形参可以理解为是在这个函数内声明的变量(比如 num1 = 10)实参可以理解为是给这个变量赋值
开发中尽量保持形参和实参个数一致

6.4 参数默认值

1
2
3
4
5
function getSum(x=0,y=0){
console.log(x+y);
}
getSum(); // 结果是0
getSum(1,2) // 结果是3

6.5 函数返回值

当调用某个函数,这个函数会返回一个结果出来,这个就是有返回值的函数。

当函数需要返回数据出去时,用return关键字

语法

1
return 数据

使用方式:

1
2
3
4
5
function getSum(x,y){
return x+y;
}
let sum = getSum(3,6);
console.log(sum);
1
2
3
4
在函数体中使用 return 关键字能将内部的执行结果交给函数外部使用
return 后面代码不会再被执行,会立即结束当前函数,所以 return 后面的数据不要换行写
return函数可以没有 return,这种情况函数默认返回值为 undefined

说明:

1
2
3
4
5
6
两个相同的函数后面的会覆盖前面的函数
在Javascript中 实参的个数和形参的个数可以不一致
如果形参过多 会自动填上undefined (了解即可)
如果实参过多 那么多余的实参会被忽略 (函数内部有一个arguments,里面装着所有的实参)
函数一旦碰到return就不会在往下执行了 函数的结束用return

6.6 作用域

考虑下面程序的执行结果

1
2
3
4
for(let i = 0;i<3;i++){
console.log("hello");
}
console.log(i);
1
2
3
4
5
function fun(){
let num2 = 20;
}
fun();
console.log(num2);

通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域

作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。

全局作用域

全局有效,作用于所有代码执行的环境(整个 script 标签内部)或者一个独立的js文件

局部作用域

局部有效,作用于函数内的代码环境,就是局部作用域。 因为跟函数有关系,所以也称为函数作用域。

在JavaScript中,根据作用域的不同,变量可以分为:

全局变量:函数外部let 的变量,全局变量在任何区域都可以访问和修改

局部变量:函数内部let的变量,局部变量只能在当前函数内部访问和修改

变量有一个坑, 特殊情况:

如果函数内部,变量没有声明,直接赋值,也当全局变量看,但是强烈不推荐

但是有一种情况,函数内部的形参可以看做是局部变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<script>
// let num = 20
// function fn() {
// num = 10 // 全局变量来看 强烈不允许
// }
// fn()
// console.log(num)

// function fun(x, y) {
// // 形参可以看做是函数的局部变量
// console.log(x)
// }
// fun(1, 2)
// console.log(x) // 错误的

// let num = 10
function fn() {
// let num = 20
function fun() {
// let num = 30
console.log(num)
}
fun()
}
fn()
</script>

6.7 变量的访问原则

1
2
3
4
5
只要是代码,就至少有一个作用域
写在函数内部的局部作用域
如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域
访问原则:在能够访问到的情况下 先局部, 局部没有在找全局

1
2
3
4
5
6
7
8
9
10
function f1() {
let num = 123
function f2() {
console.log( num )
}
f2()
}
let num = 456
f1()

以上程序的输出结果是?

1
2
3
4
5
6
7
8
9
10
11
function f1() {
            let num = 123
            function f2() {
                let num = 0
                console.log(num)
            }
            f2()
 }
let num = 456
f1()

以上程序的输出结果是?

总结:作用域链:采取就近原则的方式来查找变量最终的值

6.8 匿名函数

l函数可以分为:具名函数和匿名函数

具名函数:

1
2
3
声明:function fn() {}
调用:fn()

匿名函数:

1
2
function()  {}

所谓的匿名函数:就是没有名字的函数, 无法直接使用。

使用方式:

函数表达式

立即执行函数

. 函数表达式

1
2
3
4
5
let fn = function(){
函数体
}
// 调用
fn();

使用场景

1
2
3
4
5
6
7
<button>单击</button>
<script>
let btn = document.querySelector('button');
btn.onclick = function(){
alert('hello');
}
</script>

立即执行函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<script>
// let num = 10
// let num = 20
// (function () {
// console.log(11)
// })()

// (function () {
// let num = 10
// })();
// (function () {
// let num = 20
// })();
// 1. 第一种写法
(function (x, y) {
console.log(x + y)
let num = 10
let arr = []
})(1, 2);
// (function(){})();
// 2.第二种写法
// (function () { }());
(function (x, y) {
let arr = []
console.log(x + y)
}(1, 3));


// (function(){})()
// (function(){}())
</script>

注意:多个立即执行函数要用;分割,否则会出现错误。

1
2
3
4
5
6
立即执行函数有什么作用?
防止变量污染
立即执行函数需要调用吗? 有什么注意事项呢?
无需调用,立即执行,其实本质已经调用了
多个立即执行函数之间用分号隔开

7、对象

1
2
3
4
5
6
7
8
保存网站用户信息,比如姓名,年龄,电话号码… 用以前学的数据类型方便吗?
不方便,很难区分
我们是不是需要学习一种新的数据类型,可以详细的描述某个事物?
姓名
年龄
电话


1
let arr =[190,190,190] // 3个190是什么意思

7.1 对象是什么

对象(object):JavaScript里的一种数据类型

可以理解为是一种无序的数据集合, 注意数组是有序的数据集合

7.2 对象使用

对象声明语法:

1
let 对象名  ={}

对象有属性和方法组成

1
2
3
4
let 对象名= {
属性名:属性值,
方法名:函数
}

属性

数据描述性的信息称为属性,如人的姓名、身高、年龄、性别等,一般是名词性的。

1
2
3
4
5
let person = {
userName:'zhangsan',
age:18,
gender:'男'
}
1
2
3
4
5
属性都是成 对出现的,包括属性名和值,它们之间使用英文 : 分隔
多个属性之间使用英文 , 分隔
属性就是依附在对象上的变量(外面是变量,对象内是属性)
属性名可以使用 "" 或 '',一般情况下省略,除非名称遇到特殊符号如空格、中横线等

7.3 对象使用

获取属性的值

语法:对象名.属性

1
2
3
4
5
6
7
 let person = {
userName:'zhangsan',
age:18,
gender:'男'
}
console.log(person.userName);
console.log(person.age);

修改属性的值

语法:对象名.属性 = 新值

1
2
3
4
5
6
7
 let person = {
userName:'zhangsan',
age:18,
gender:'男'
}
person.age = 19;
console.log(person.age);

新增属性

语法:对象名.新属性 = 新值

1
2
3
4
5
6
7
 let person = {
userName:'zhangsan',
age:18,
gender:'男'
}
person.address = "北京"
console.log(person);

删除属性

语法:delete 对象名.属性

1
2
3
4
5
6
7
 let person = {
userName:'zhangsan',
age:18,
gender:'男'
}
delete person.gender
console.log(person);

属性查找的另外一种写法

1
2
3
4
5
6
let person = {
'user-name':"zhangsan",
age:18,
gender:'男'
}
console.log(person.user-name); // NaN
1
2
3
4
5
6
let person = {
'user-name':"zhangsan",
age:18,
gender:'男'
}
console.log(person['user-name']); // zhangsan

对于多词属性或者添加了 - 等属性,点操作就不能用了。

我们可以采取: 对象[‘属性’] 方式, 单引号和双引号都阔以

7.4 对象中的方法

数据行为性的信息称为方法,如跑步、唱歌等,一般是动词性的,其本质是函数。

1
2
3
4
5
6
7
8
9
10
let person = {
userName:'zhangsan',
age:18,
gender:'男',
// 可以添加形参
sayHi:function(){
console.log('hello');
}
}
person.sayHi(); // 可以添加实参

7.5 遍历对象

1
2
3
4
for 遍历对象的问题:
对象没有像数组一样的length属性,所以无法确定长度
对象里面是无序的键值对, 没有规律. 不像数组里面有规律的下标

1
2
3
4
5
6
7
8
9
let obj ={
userName:'zhangsan',
age:18,
gender:'男',
}
for(let k in obj){
console.log(k); // 打印的是属性名
console.log(obj[k]) ;// 打印的是属性的值
}

7.6 内置对象

JavaScript内部提供的对象,包含各种属性和方法给开发者调用

例如:前面使用的document.write(),console.log()

Math对象

1
2
3
4
5
6
7
8
9
10
11
介绍: Math对象是JavaScript提供的一个“数学”对象
作用: 提供了一系列做数学运算的方法
Math对象包含的方法有:
random:生成0-1之间的随机数(包含0不包括1)
ceil:向上取整
floor:向下取整
max:找最大数
min:找最小数
pow:幂运算
abs:绝对值

Math[对象在线文档](https://www.w3school.com.cn/js/jsref_obj_math.asp)

Math.random() 随机数函数, 返回一个0 - 1之间,并且包括0不包括1的随机小数 [0, 1)

l如何生成0-10的随机数呢?

1
2
Math.floor(Math.random() * (10 + 1))

如何生成5-10的随机数?

1
Math.floor(Math.random() * (5 + 1)) + 5

如何生成N-M之间的随机数

1
Math.floor(Math.random() * (M - N + 1)) + N

7.7 基本数据类型和引用数据类型

简单类型又叫做基本数据类型或者值类型,复杂类型又叫做引用类型。

值类型:简单数据类型/基本数据类型,在存储时变量中存储的是值本身,因此叫做值类型

string ,number,boolean,undefined,null

引用类型:复杂数据类型,在存储时变量中存储的仅仅是地址(引用),因此叫做引用数据类型

通过 new 关键字创建的对象(系统对象、自定义对象),如 Object、Array、Date等

1
2
3
4
5
6
堆栈空间分配区别:
1、栈(操作系统):由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈;
简单数据类型存放到栈里面
2、堆(操作系统):存储复杂类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。
引用数据类型存放到堆里面

1
2
3
值类型(简单数据类型): string ,number,boolean,undefined,null
值类型变量的数据直接存放在变量(栈空间)中

1
2
3
引用类型(复杂数据类型):通过 new 关键字创建的对象(系统对象、自定义对象),如 Object、Array、Date等
引用类型变量(栈空间)里存放的是地址,真正的对象实例存放在堆空间中