本文将主要记录JavaScript的基础部分,当前是ES6(ECMAscript)规范。
本文的部分主要为js的基本原理与构成,与实际页面的操作仍有一定的距离。

JavaScript 变量、常量与数据类型
JavaScript 思维导图(1-5)

A007-1s.jpg

1. JavaScript简介

1.1 概念

H5/CSS3是标记语言,而JavaScipt是脚本语言,是一种运行在浏览器的编程语言。

1.2 作用

A.网页特效 (监听用户行为—网页作出反馈)
B. 表单验证 (表单数据的合法性判断)
C. 数据交互 (获取后台的数据, 渲染到前端/vue.js)
D. 服务端编程 (node.js)

1.3 组成

JavaScript由EMCAScript和Web APIs组成。
其中,EMCAScript是一套规范,规定了js的核心语法。
而APIs可以分为DOM(操作页面元素)和BOM(操作浏览器)两部分。

1.4 权威手册

MDN(mdn web docs): https://developer.mozilla.org/zh-CN/

1.5 js书写位置

A. 内部:html文件内部,body标签中的script标签内,跟在html元素后面(放在底部)。

1
2
3
4
<body>
<script>
</script>
</body>

B. 外部:通过script标签引入外部js文件。
1
<script src="my.js"></script>

C. 行内:直接在html标签元素内部写。(常见于vue)

1.6 注释与结束符

单行注释:// (ctrl+/)
块注释:/**/ (ctrl+alt+a)
浏览器弹窗输出:alert(‘弹窗文本’)
js结束符:“;” 不同于CSS,js语句可以不用加分号也能运行。
结束符只要项目中统一使用/不使用即可。最新趋势是不加(如vue)。

1.7 输入输出

A. 文档输出内容 document.write(‘’)
可以直接在页面上输出,且支持输出html标签。

1
2
document.write('我是div标签')
document.write('<h1>我是标题</h1>')

B. 控制台打印输出 console.log(‘’)
1
2
console.log('看看对不对')
console.log('日志')

C. 输入弹窗 prompt(‘’)
1
prompt('请输入您的年龄:')

D. 输出弹窗 alert(‘’)
1
alert('弹窗警告')

1.8 字面量(literal)脸

数字字面量:1000
字符串字面量:’’
数组字面量:[]
对象字面量:{}

2. 变量

变量,即是容器。
声明并赋值,是变量的基本使用方式。

2.1 变量声明与赋值

现在js中变量声明使用let,老版本程序中多使用var.
例如:

1
2
3
let age = 18
let unname = '字符串'
console.log(age, unname)

又或者输入递给变量:
1
2
let unname = prompt('请输入姓名')
document.write(unname)

2.2 变量命名规则

js中,变量命名规则如下:
A. 不能使用关键字 (let,var,if等)
B. 由下划线字母数字$组成,且不能数字开头
C. 大小写敏感
D. 要有含义,且使用驼峰命名法(mingMingFa)

3. 数组

数组,是数据的组合。
数组可以存放任意形式的数据,比如数值、字符串、数组等都可以。
元素:数组中的每个数据
下标:数组中数据的编号
长度:数组中数据的个数,通过‘数组名.length’属性可以调出。
可见,数组长度=序号+1

3.1 数组声明与赋值

声明形式如下:

1
2
3
let arr = [1,2,3,4,5]
let names = ['小明','小刚','小红']
console.log(arr)

3.2 数组序号

从0开始编号,arr[0],arr[1],…

1
console.log(arr[0]) //输出arr数组的第一个元素

4. 常量

常量,不会改变的变量。不可以重复赋值。
使用const来声明。初次声明必须赋值。

1
const G = 9.8

5. 数据类型

js中,数据类型可以分为两大类:A.基本数据类型 B.引用(复杂)数据类型
其中基本数据类型有5类:数字型、字符串型、布尔型、Null、Undefined
而复杂数据类型主要有:对象(object)

“简单数据类型直接把值存在栈中,复杂数据类型把地址存在栈中,再由地址指向堆中存放的数据。”

由于js是属于弱数据类型的语言,即在赋值前是不能确定具体数据类型的。

5.1 数字型(number)

数字型可以是:整数、小数、正数、负数

1
2
3
let num = 10
let num = 10.11
let num = -10

5.1.1 算术运算符

加减乘除+-*/
取余%
例如:

1
2
3
4%2 --> 4/2=2...0
5%3 --> 5/3=1...2
3%5 --> 3/5=0...3

取余常用于判断数值能否被整除。

运算优先级:乘除取余>加减, ()可以提高优先级

5.1.2 计算错误NaN

NaN代表计算错误,(not a number)

1
2
console.log('啊啊' - 2) //NaN
console.log(NaN + 2) //NaN

5.2 字符串型(string)

js中,被‘’or””or``包裹的数据都是字符串,通常使用‘’。
例如:

1
2
3
let str = ''
let str = "噗噜噗噜"
let str = `123123`

如果字符串中需要使用引号,一般外单内双/外双内单/转义符\’

5.2.1 字符串拼接

字符串间通常使用加号拼接

1
2
3
4
console.log('阿巴'+'阿巴')
let unname = '派蒙'
let dialogue = '阿巴阿巴'
document.write(unname +':'+ dialogue) //派蒙:阿巴阿巴

5.2.2 模板字符串

属于ES6新语法,用来简化处理字符串与变量混合使用的场景。
在``字符串中,${}来包裹变量名。

1
2
let age = 18
document.write(`我今年${age}岁了`)

5.3 布尔型(boolean)

true和false是布尔型的字面量。

1
let isCool = true

5.4 未定义型(undefined)

只声明了,但未赋值/定义的。
常用于检测有无数值传输过来。

1
let num

5.5 空型(null)

赋值了,但内容为空。
null实际是一个尚未创建的对象(object),使用null占位。

1
let num = null

5.6 数据类型检测

浏览器的控制台中,数字型(蓝色)、字符串型(黑色)
一般使用typeof来检测数据类型,常用运算符形式使用。

1
2
3
let num = 10
typeof num //运算符形式,number
typeof(num) //函数形式,number

5.7 数据类型转换

使用场景:弹窗输入为字符串型,需要转换为数字型。

5.7.1 隐式转换

隐式转换方法:
A. +号只要有一边是字符串,拼接结果就是字符串。
B. 可以利用-*/运算符将将数据类型转换为数字型。(+开头时也能用)
例如:

1
2
3
4
2+2     //4
2+'2' //22
2-'2' //0
+'123' //123(数字型)

5.7.2 显式转换

Number()

Number()用于将数据类型转换为数字型。
例如:

1
2
3
let str = '123'
Number(str) //123
Number('阿巴') //NaN

案例:
1
2
let num = Number(prompt('输入工资'))    //输入数据直接数字型化
let num = +prompt('输入工资') //输入数据直接数字型化(隐式转换)

parseInt()

parseInt()用于从数字开头的字符串中提取数值的整数,并存为数字型。
例如:

1
2
parseInt('12px')    //12
parseInt('12.94px') //12

parseFloat()

parseFloat()用于从数字开头的字符串中提取完整数值,并存为数字型。
例如:

1
2
parseFloat('12px')    //12
parseFloat('12.94px') //12.94

JS基础语法案例集 1-5

基础语法案例(1-5)

1.点哪个按钮亮哪个

需求分析:首先H5写4个按钮标签,然后做一个按钮选中的CSS样式,接着使用JS设定-如果单击则添加类选择器。

代码:

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
<!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>
.pink {
background-color: pink;
}
</style>
</head>

<body>
<button class="pink">按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<script>
let bts = document.querySelectorAll('button') //把页面中所有的button选中,存进bts
for (let i = 0; i < bts.length; i++) { //遍历bts数组
bts[i].addEventListener('click', function () { //创建一个事件触发器,联动单击功能函数
document.querySelector('.pink').className = '' //取消原先的选中显示
this.className = 'pink' //给选中的按钮加上CSS
})
}
</script>
</body>

</html>

效果图:
A007-1a.gif

2.输入与输出

2.1 计算

1
2
3
4
5
<script>
let r = prompt('请输入圆的半径:')
let re = 3.14 * r * r
document.write(re)
</script>

2.2 文本

1
2
3
4
5
<script>
let uname = prompt('请输入您的姓名:')
let age = prompt('请输入您的年龄:')
document.write(`大家好,我叫${uname}, 我今年${age}岁了`)
</script>

2.3 数字与文本

1
2
3
4
5
<script>
let num1 = +prompt('请输入第一个数字:')
let num2 = +prompt('请输入第二个数字:')
alert(`两个数相加的和是:${num1 + num2}`)
</script>

3.综合案例-订单生成

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
  <title>订单生成</title>
<style>
h2 {
text-align: center; //标题-行居中(tac)
}

table {
border-collapse: collapse; //合并相邻边框(边框线从双线合并为实线)
height: 80px; //行高设定
margin: 0 auto; //使其在页面中居中
text-align: center; //所有文字居中对齐
}

th {
padding: 5px 30px; //给表头一个padding,就不用设置表格宽度了。上下5px,左右30px
}

table,
th,
td {
border: 1px solid #000; //表格table-表头行th-表格行td-加边框
}

</style>
</head>

<body>
<h2>订单确认</h2>

<script>
// 1 用户输入
let price = +prompt('请输入商品价格:')
let num = +prompt('请输入商品数量:')
let address = prompt('请输入收获地址:')
// 2.计算总额
let total = price * num
// 3.页面打印渲染
document.write(`
//table>tr>th*5
//tr>td*5
<table>
<tr>
<th>商品名称</th>
<th>商品价格</th>
<th>商品数量</th>
<th>总价</th>
<th>收货地址</th>
</tr>
<tr>
<td>小米青春版PLUS</td>
<td>${price}元</td>
<td>${num}</td>
<td>${total}元</td>
<td>${address}</td>
</tr>
</table>
`)
</script>
</body>
JavaScript 运算符、语句
JavaScript 思维导图(6-7)

A007-2s.png

6. 运算符

6.1 赋值运算符(=)

对变量赋值/累加赋值

1
2
let num = 1
num += 1 //等价于 num = num + 1 / 每次加一

除了+=以外,还有-= = = /= %= 等累计赋值符。

6.2 一元运算符

6.2.1 自增符(++)

1
2
3
4
5
6
7
8
9
10
11
12
13
++i       //前置自增(先自加再运算)
//例如:
let i = 1
console.log(++i + 2) //结果为2+2=4

i++ //后置自增(先运算再自加)
//例如:
let i = 1
console.log(i++ + 2) //结果为1+2=3 (执行完后i为2)

//案例:
let i = 1
console.log(i++ + ++i + i) //结果为1+3+3=7

6.3 比较运算符

这类运算符的结果只可能为布尔型(true/false)。

  1. 常见的比较运算符如下:
    A007-6-3.jpg

    1
    2
    3
    = 赋值
    == 判断两边是否相等
    === 判断两边是否类型和值都相等

    由于比较运算符自带隐式转换,所以支持将字符型转换为数字型再和数字型比较。(除了===)

  2. 字符串型之间也可以进行比较,比较的是ASCII码的大小。(字典序比较)

    1
    2
    3
    4
    #一些常见的ASCII码
    0-->48
    A-->65
    a-->97
  3. 只要与NaN比较,那结果一定是false。因为NaN不等于任何值。

  4. 尽量不要比较小数,因为会出精度问题。(涉及小数的运算通常使用“放缩法”)

  5. 不同类型之间的比较会发生隐式转换。

6.4 逻辑运算符

逻辑运算符通常分为3个:逻辑与(&&)、逻辑或(||)、逻辑非(!)。
很简单,略。

  • 例子:判断1个数是4的倍数,但不是100的倍数。
    1
    2
    let num = +prompt('请输入一个数字:')
    alert(num % 4 === 0 && num % 100 !== 0)

6.5 各个运算符之间的优先级

A007-6-5.jpg

7. 语句

主要语句可以被分为顺序语句、分支语句和循环语句,3大类。

7.1 表达式和语句

表达式:可以被求值的代码。
语句:可以被执行的代码。
表达式与语句的区别:表达式可以被求值,放在赋值语句右侧。但语句不一定有值。

7.2 分支语句

三大流程控制语句:顺序结构、分支结构、循环结构。
分支语句有:if语句、三元运算符、switch语句。

7.2.1 if语句

if语句有三类:单分支、双分支、多分支。
有关条件判断的知识点—>除了0的数字都为真,除了’’(空字符)的字符串都是真。

if单分支语句

1
2
3
if (条件){
满足条件后执行的代码
}

if双分支语句

1
2
3
4
5
if (条件){
满足条件后执行的代码
} else {
不满足时执行的代码
}

if多分支语句

1
2
3
4
5
6
7
8
9
if (条件1){
满足条件1后执行的代码
} else if (条件2){
满足条件2时执行的代码
} else if (条件3){
满足条件3时执行的代码
} else {
满足其余条件时执行的代码
}

if语句的小例子

1
2
3
4
5
6
7
let uname = prompt('请输入用户名:')
let pwd = prompt('请输入密码:')
if (uname === 'pink' && pwd === '123456'){
alert('登录成功')
} else {
alert('用户名或密码错误')
}

7.2.2 三元运算符

三元运算符,是种简化的if双分支语句。

1
条件?满足条件执行的代码:不满足条件执行的代码

一般用来取值。

  • 例1:示范

    1
    3 > 5 ? alert('假的') : alert('真的')
  • 例2:数字补0
    输入一个数,如果小于10,就在前面补0,如:03.

    1
    2
    3
    let num = prompt('请输入一个数:')
    num = num < 10 ? 0 + num : num //巧妙利用了隐式转换2次
    alert(num)

7.2.3 switch语句

switch语句,是个多分支选择语句。

1
2
3
4
5
6
7
8
9
10
11
switch (数据) {
case 数值1:
代码1
break
case 数值2:
代码2
break
default:
代码n
break
}

  • 小例子:计算器
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    //1.用户输入(1个数字1个运算符1个数字)
    let num1 = +prompt('请输入第一个数字:')
    let num2 = +prompt('请输入第二个数字:')
    let sp = prompt('请输入+ - * /其中之一的运算符:')
    //2.判断输出
    switch(sp){
    case '+':
    alert('两个数字的加法操作是$(num1 + num2)')
    break
    case '-':
    alert('两个数字的加法操作是$(num1 - num2)')
    break
    case '*':
    alert('两个数字的加法操作是$(num1 * num2)')
    break
    case '/':
    alert('两个数字的加法操作是$(num1 / num2)')
    break
    default:
    alert('请输入+-*/之中的运算符')
    }

7.3 循环语句

常见的循环有while和for循环两种。都可以使用break和continue。

7.3.1 断点调试(Debug)

浏览器—>F12—>sources—>打开html—>对行号打断点—>刷新浏览器—>发现整体状态停留在断点处—>可以按下一步走一行

7.3.2 while循环

while本质是在条件满足期间一直执行这段代码。

1
2
3
while (循环条件) {
循环代码
}

while三要素:变量起始值,变化量,终止条件。

while循环练习
  1. 输出1-100

    1
    2
    3
    4
    5
    let i=1
    while (i<=100){
    document.write(这是第${i}个数<br>)
    i++
    }
  2. 计算1+…+100=

    1
    2
    3
    4
    5
    6
    7
    let i=1
    let sum=0
    while (i<=100){
    sum=sum+i
    i++
    }
    document.write(1+...+100=${sum})
  3. 计算1~100之间所有的偶数之和

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    let i=1
    let sum=0
    while (i<=100){
    //除二余数为0为偶数,除二不为0为奇数
    if(i%2===0){
    sum=sum+i
    }
    i++
    }
    document.write(1~100之间所有的偶数之和为${sum})

continue: 结束本次循环,继续下一次循环
break: 退出循环

  • 例子:你爱我吗?
    1
    2
    3
    4
    5
    6
    while (true){
    let str = prompt('你爱我吗')
    if (str === '爱'){
    break
    }
    }

7.3.3 for循环

for循环示范:

1
2
3
for (循环前执行;运行条件;每次循环结束就执行){
循环代码
}

例如:
1
2
3
for (i=1;i<=10;i++){
document.write('*') //打印10个‘*’
}

无限循环:for(;;){}

for循环练习
  1. 遍历数组
    1
    2
    3
    4
    let arr=['A','B','C']
    for (i=0;i<arr.length;i++){ //或者i<=arr.length-1
    document.write(arr[i])
    }
  2. 打印row行col列的方阵‘★’(经典)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    //用户输入
    let row = +prompt('请输入行数')
    let col = +prompt('请输入列数')
    //循环打印
    for (let i=1;i<=row;i++){ //行
    for (let j=1;j<=col;j++){ //列
    document.write(‘★’)
    }
    document.write('<br>') //换行
    }
  3. 打印三角阵‘★’(经典)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    //用户输入
    let row = +prompt('请输入行数')
    let col = +prompt('请输入列数')
    //循环打印
    for (let i=1;i<=row;i++){ //行
    for (let j=1;j<=i;j++){ //列(列中操作数量跟着行来走j<=i)(j<=row-i+1就是倒三角了)
    document.write('★')
    }
    document.write('<br>') //换行
    }
  4. 打印九九乘法表
    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
      <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>
    ...
    ...
    <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>`) //用span标签包裹
    }
    // 换行
    document.write('<br>')
    }
    </script>
JavaScript 数组

8. 数组操作

JavaScript 思维导图(8)

A007-3s.png

数组,是一种带顺序的数据类型。起始编号为0。(详见第3章)

1
2
3
//数组声明
let arr = [1,2,'arr',true] //字面量声明
let arr = new Array(1,2,3,4) //构造函数声明

8.1 遍历数组

在for循环中,for循环练习的第一个例子里已经提过一个简单的遍历数组的方法。

1
2
3
4
let arr=['A','B','C']
for (i=0;i<arr.length;i++){
document.write(arr[i])
}

8.2 数组小练习

例1: 数组求和与求平均值(遍历法)

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

例2: 数组求最值

1
2
3
4
5
6
7
8
9
10
11
12
// 初始化
let arr = [2, 6, 1, 7, 400, 55, 88, 100]
let max = arr[0] // max 存最大值
let min = arr[0] // min 存最小值
// 遍历数组
for (let i = 1; i < arr.length; i++) {
max < arr[i] ? max = arr[i] : max // 如果 max 比数组元素的值小,我们就把这个元素赋值给 max
min > arr[i] ? min = arr[i] : min // 如果 min 比数组元素的值大,我们就把这个元素赋值给 min
}
// 输出 max
console.log(`最大值是: ${max}`)
console.log(`最小值是: ${min}`)

8.3 数组的增删查改筛

增:数组添加新的数据

1
2
arr.push(新增内容1,新增内容2)      //将新增元素(1个或多个)添加到数组末尾,并返回数组的新长度。【重点】
arr.unshift(新增内容1,新增内容2) //将新增元素(1个或多个)添加到数组开头,并返回数组的新长度。

删:删除数组中的数据

1
2
3
arr.pop()                         // 删除数组中最后一个元素,并返回该元素的值。(一次只能删除一个)
arr.shift() // 删除数组中前面第一个元素,并返回该元素的值。(一次只能删除一个)
arr.splice(操作的下标,删除的个数) // 删除数组中下标指定的元素,并指定删除的数量。(不给个数,直接默认后面全删了)

查:查询数组数据

1
2
3
// 数组[下标]
let arr = []
console.log(arr[0]) //由于是空数组,所以查询为undefined

改:数组重新赋值

1
2
3
4
// 数组[下标]=新值
let arr = []
arr[0] = 1
// 整体修改可以用遍历

筛:数组元素筛选

这种情况一般有:(a) 查找大于某值的元素并存入新数组;(b) 对于数组中的元素进行去0操作…

数组筛选练习
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script>
// 重点案例
let arr = [2, 0, 6, 1, 77, 9, 54, 3, 78, 7]
// 1. 声明新的空的数组
let newArr = []
// 2. 遍历旧数组
for (let i = 0; i < arr.length; i++) {
if (arr[i] >= 10) {
// 3. 满足条件 追加给新的数组
newArr.push(arr[i])
}
}
// 4. 输出新的数组
console.log(newArr)
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
<script>
let arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7]
// 1. 声明一个新的数组
let newArr = []
// 2. 遍历筛选
for (let i = 0; i < arr.length; i++) {
if (arr[i] !== 0) {
newArr.push(arr[i])
}
}
// 输出新数组
console.log(newArr)
</script>

8.4 数组应用案例(柱形图)

综合案例-渲染柱形图
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
//涉及到移动端CSS知识
<style>
* {
margin: 0;
padding: 0;
}

.box {
display: flex; //flex显示模式
width: 700px;
height: 300px;
border-left: 1px solid pink; //左边框
border-bottom: 1px solid pink; //右边框
margin: 50px auto;
justify-content: space-around;
align-items: flex-end; //柱子底部对齐
text-align: center; //文字水平居中
}

.box>div {
display: flex;
width: 50px;
background-color: pink;
flex-direction: column;
justify-content: space-between;
}

.box div span {

margin-top: -20px;
}

.box div h4 {
margin-bottom: -35px;
width: 70px;
margin-left: -10px;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<script>
// 1. 四次弹框效果
// 声明一个新的数组
let arr = []
for (let i = 1; i <= 4; i++) {
arr.push(prompt(`请输入第${i}季度的数据:`))
}

// 盒子开头
document.write(` <div class="box">`)

// 盒子中间 利用循环的形式 跟数组有关系
for (let i = 0; i < arr.length; i++) {
document.write(`
<div style="height: ${arr[i]}px;">
<span>${arr[i]}</span>
<h4>第${i + 1}季度</h4>
</div>
`)
}

// 盒子结尾
document.write(` </div>`)
</script>

A007-8-4.gif

JavaScript 函数与匿名函数

9. 函数

JavaScript 思维导图(9)

A007-4s.png

函数,可以封装一部分代码方便调用。
函数声明方式:

1
2
3
function 函数名(){
函数体
}

函数调用方式:
1
函数名()

其中命名用小驼峰命名法、动词开头。

【函数的一些特性】

  1. 函数不调用不执行。
  2. 同名函数,后面会覆盖前面的。
  3. 形参与实参的数量可以不一致。(形参过多undefined;实参过多由函数内部arguments变量装载)
  4. return后就不执行了。(return结束函数;break结束循环和switch)

9.1 函数传参

通过给函数赋予参数,可以实现对函数的输入。
例子:

1
2
3
4
5
6
7
8
9
//构建一个getSum函数,对一段数字序列进行求和。
function getSum(start, end) { // 这里start和end属于“形参”: 形式上的参数。
let sum = 0
for (let i = start; i <= end; i++) {
sum += i
}
console.log(sum)
}
getSum(100, 200) // 这里给的“100”和“200”属于“实参”:实际的参数。

且通常为了让函数稳定不报错,会给形参赋予一个默认值。

小练习-函数封装-数组求和
1
2
3
4
5
6
7
8
9
10
function getArrSum(arr = []) {
let sum = 0
for (let i = 0; i < arr.length; i++) {
sum += arr[i]
}
console.log(sum)
}
getArrSum([1, 2, 3, 4, 5])
getArrSum([11, 22, 33])
getArrSum() // 0

9.2 函数返回值

通过给函数加返回值,可以实现函数的输出。
在函数体中写“return 返回值”可以输出返回值。
例如:

1
2
3
4
5
6
//一种经典的返回值调用结构
function fn(){
return 20
}
let re = fn()
console.log(re)

在这里,函数处理数据,但不输出,由返回值形式,以函数名“存储”输出,该使用时调出。
(a) 在使用return后,后面的代码不会被执行,函数会立刻结束。
(b) 如果不return,函数的返回值默认为undefined。

小练习-函数返回值-求最大值函数
1
2
3
4
5
6
7
8
9
10
11
function getMax(arr = []) {
//遍历求数组最大元素
for (let i = 1; i < arr.length; i++) {
if(max < arr[i]) {
max =arr[i]
}
}
return max //设定函数返回值(返回多个值时请使用数组[x, y, ...])
}
let max = getMax([1, 2, 3, 4, 5, 6]) //函数输出给变量
console.log('该数组的最大值是:${max}') //变量正式显示

9.3 函数的断点调试

网页-F12-Sources-html/js代码所在文件-点击行数进行断点调试-鼠标悬停可以看见各个变量的数值。

9.4 作用域

定义:变量的可用范围
常见错误:函数内部的作用域 与 函数外的作用域 不互通。
一般分为全局作用域与局部作用域,即对应全局变量(script标签内部/js文件内)与局部变量(函数内部)。
【特殊情况】如果函数内部不声明直接赋值,就默认为全局变量。(非规范写法)
变量访问原则?就近查询,逐级上查。

9.5 匿名函数

匿名函数声明方式:

1
function () {}

使用方法:

  1. 函数表达式:将匿名函数赋给一个变量,通过变量名来调用匿名函数(不同于具名函数,必须要先声明才能调用)

    1
    2
    3
    let fn = function () {
    //函数体
    }
  2. 立即执行函数:防止变量污染。需要加分号,第二个小括号是调用。

    1
    2
    3
    (function(){})();
    or
    (function(){}());

    举个例子:

    1
    2
    3
    (function(x, y){
    console.log(x + y)
    })(1, 2);

9.6 综合案例:封装时间换算函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<script>
// 1. 用户输入
let second = +prompt('请输入秒数:')
// 2.封装函数
function getTime(t) {
// console.log(t) // 总的秒数
// 3. 转换
// 小时: h = parseInt(总秒数 / 60 / 60 % 24)
// 分钟: m = parseInt(总秒数 / 60 % 60)
// 秒数: s = parseInt(总秒数 % 60)
let h = parseInt(t / 60 / 60 % 24)
let m = parseInt(t / 60 % 60)
let s = parseInt(t % 60)
h = h < 10 ? '0' + h : h
m = m < 10 ? '0' + m : m
s = s < 10 ? '0' + s : s
// console.log(h, m, s)
return `转换完毕之后是${h}小时${m}分${s}秒`
}
let str = getTime(second)
document.write(str)
console.log(h)
</script>

9.7 逻辑中断

在逻辑与/逻辑或的运算时,由于(与中一假全假,或中一真全真)的原则,导致部分情况只需要读取左边就可以输出结果。
例1:

1
2
3
4
5
6
let age = 18
console.log(false && age++) //使用逻辑中断,不读取右边的代码。
console.log(age) //由于逻辑中断,所以age依旧为18
console.log(true || age++) //使用逻辑中断,不读取右边的代码。
console.log(age) //由于逻辑中断,所以age依旧为18
//如果逻辑与,两边真,则返回最后一个真值。

例2:
1
2
3
4
5
6
function fn(x, y){
x = x || 0 //这里使用逻辑或做了一个逻辑中断,目的是给变量一个默认参数值为0,且不影响正常赋值。
y = y || 0 //当形参x,y都是未定义undefined,逻辑或中,一假则读后0。
console.log(x + y) //当形参接收了实参数据时,逻辑或中,一真则逻辑中断。
}
fn()

【总结】逻辑与一假则中断;逻辑或一真则中断。

9.8 转换为布尔型

对于一个变量,可以使用Boolean函数来转换。
‘’/0/undefined/null/false/NaN —> 转换为布尔为false,其余转换为true。

例子:

1
console.log(Boolean('pink')); //true

*隐式转换复习

  1. “” + 1 = “1”
  2. 减法-只能用于数字,且遇到空字符串“”会转化为0
  3. null数字转换后变为0
  4. undefined数字转换后变为NaN
JavaScript 对象与基本使用

10. 对象

JavaScript 思维导图(10)

A007-5s.png

10.1 对象的定义

为了储存用户数据,全是数字很难分辨其实际意义,故而类似C语言的结构体,Javascript中也有这个概念——“对象”
“对象”是一种数据类型,是一种无序的数据集合(数组是有序的数据集合)
举个例子:

1
2
3
4
5
6
let obj = {
unname: 'Niord',
age: 18,
gender: 'male',
'my-name': 'Niord'
}

这就是一个典型的对象结构。

10.2 对象的声明

1
2
let 对象名 = {}
let 对象名 = new Object()

10.3 对象的使用

对象由属性和方法组成:

1
2
3
4
let 对象名 = {
属性名: 属性值, //对应名词、形容词
方法名: 函数 //对应描述一个动作
}

10.4 对象的操作-增删改查

查询对象

(a) 对象名.属性名
obj.unname //Niord

(b) 对象名[‘属性名’]
obj[‘my-name’] //Niord
(记得使用console.log等方法来输出)

增加/修改对象描述

对象.(新)属性名 = 新值

删除对象描述

delete 对象名.属性
(但是最新语法已经不推荐这么做了)

10.5 对象的方法 【重要】

在上文中10.3章节中,我们提到过在对象中除了添加属性描述,还可以添加方法描述,而对应的值则为函数名。
这个架构其实和UIS语法中的《元件中动画的调用》有一些相似。
先举个例子:
这里我们用到了匿名函数来作为对象的方法描述。

1
2
3
4
5
6
let person = {
unname: 'Niord',
sayHi: function() {
document.write('Hi!')
}
}

在这个语句中,我们在person对象中,创建了一个sayHi的方法,并用一个匿名函数来描述,输出一个Hi。
如何调用方法?
person.sayHi()
对象名.方法名()
即可调用,与其同样原理的有“document.write()”其实也是document对象中write的方法。

10.6 遍历对象 【重要】

如何便利地输出对象的所有信息?
与数组遍历类似,对象也可以遍历,遍历输出。
如下所示,我们使用for-in语法:

1
2
3
4
5
let arr = ['1','2','3']   //我们先以数组为例,展示一下for-in语法。
for (let k in arr) { //这里我们可以假设数组中存在一个序列k,但是这里k是字符串类型的。
console.log(k)
console.log(arr[k]) //然后我们就可以通过k来查找arr数组中的元素(属性/方法)
}

这是一种通过假设序列k来遍历的方法,在对象遍历中十分常用。
下面我们创建一个对象并使用for-in语法进行遍历。
1
2
3
4
5
6
7
8
9
10
11
//创建对象
let obj = {
unname: 'Niord',
age: 18,
gender: 'male',
}
//遍历对象
for (let k in obj) {
console.log(k) //先看看k遍历下来都是什么?-->各个属性名,例如:'unname'
console.log(obj[k]) //这里看似obj[k],实际上是obj['unname'],是对象查询中的第二种写法。(详见10.4)
}

10.7 对象输出案例

对象渲染输出案例
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
<table>
<caption>学生列表</caption>
<tr>
<th>序号</th>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>家乡</th>
</tr>
<!-- script写到这里 -->
<script>
// 1. 数据准备
let students = [
{ name: '小明', age: 18, gender: '男', hometown: '河北省' },
{ name: '小红', age: 19, gender: '女', hometown: '河南省' },
{ name: '小刚', age: 17, gender: '男', hometown: '山西省' },
{ name: '小丽', age: 18, gender: '女', hometown: '山东省' },
{ name: '晓强', age: 16, gender: '女', hometown: '蓝翔技校' }
]
// 2. 渲染页面
for (let i = 0; i < students.length; i++) {
document.write(`
<tr>
<td>${i + 1}</td>
<td>${students[i].name}</td> //查询对象中的属性
<td>${students[i].age}</td>
<td>${students[i].gender}</td>
<td>${students[i].hometown}</td>
</tr>
`)
}
</script>
</table>

10.8 JS内置对象

在JS中有一些对象是提前内置好的,常用的有:
console.log()
document.write()
这两用来输出的内置对象。
另外还有比较经典的Math对象,支持一系列数学操作。
比如:
Math.PI() //输出PI
Math.random() //输出0-1的随机数,左闭右开
Math.ceil() //输出向上取整
Math.floor() //输出向下取整
Math.round() //四舍五入取整
parseInt() //*暴力切除取整,支持字符串,字符混杂的情况
Math.max()
Math.min()
Math.abs() //取绝对值
Math.pow() //幂运算
更多请见MDN

10.9 Math.random()的应用 【重要】

(a) 生成0~10之间的随机整数
Math.floor(Math.random()*(10 + 1)) //[0,1)—[0,10)—[1,11)—向下取整—0~10

(b) 从数组中取随机元素
Math.floor(Math.random()*arr.length) //对一定长度的数组序列号取随机—0~?
因此,我们可以从中学到(随机点名)的实现方法。

1
2
3
4
let arr = ['red', 'green', 'blue']
let random = Math.floor(Math.random() * arr.length)
console.log(random) //随机数组序号生成
console.log(arr[random]) //随机抽选出一个数组元素

(c) 生成N~M之间的随机整数
Math.floor(Math.random()*(M-N+1))+N //[0,1)—[0,M-N+1)—[N,M+1)—向下取整—N~M
因此我们甚至可以包装成一个函数:

1
2
3
4
function getRandom(N, M) {
return Math.floor(Math.random() * (M - N + 1)) + N
}
console.log(getRandom(4, 8)) //直接输入我们想要的区间

(d) 猜数字小游戏(限定次数)

点击查看
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>
// 1. 随机生成一个数字 1~10
// 取到 N ~ M 的随机整数
function getRandom(N, M) {
return Math.floor(Math.random() * (M - N + 1)) + N
}
let random = getRandom(1, 10)
// 2. 设定三次 三次没猜对就直接退出
let flag = true // 开关变量
for (let i = 1; i <= 3; i++) {
let num = +prompt('请输入1~10之间的一个数字:')
if (num > random) {
alert('您猜大了,继续')
} else if (num < random) {
alert('您猜小了,继续')
} else {
flag = false
alert('猜对了,真厉害')
break
}
}
// 写到for的外面来
if (flag) {
alert('次数已经用完')
}
</script>

(e) 生成随机颜色
这里分别展示两种颜色格式(16进制、RGB格式)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//生成随机颜色函数
function getRandomColor() {
//以#ffffff格式生成随机颜色
let str = '#'
let arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']
// 利用for循环随机抽6次 累加到str里面
for (let i = 1; i <= 6; i++) {
// 每次要随机从数组里面抽取一个
// random 是数组的索引号 是随机的
let random = Math.floor(Math.random() * arr.length)
// str = str + arr[random]
str += arr[random]
}
return str
}
//函数调用
console.log(getRandomColor())
1
2
3
4
5
6
7
8
function getRandomColor() {
let r = Math.floor(Math.random() * 256)
let g = Math.floor(Math.random() * 256)
let b = Math.floor(Math.random() * 256)
return `rgb(${r},${g},${b})`
}
//函数调用
console.log(getRandomColor())

我们刚才使用getRandomColor()函数生成了随机颜色,那么如何赋给一个网页上的盒子呢?
这里我们用到内置document对象的querySelector方法,把创建好的div输入;
并通过属性/方法来调用修改颜色。

1
2
3
4
style内,w300+h300创建一个300*300的盒子。
script内,输入:
const div = document.querySelector('div')
div.style.backgroundColor = getRandomColor()

JavaScript 一些基础综合案例

构思:通过javascript的使用,循环渲染小部件,用于多部件的网页,并方便进行信息数据的管理。

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<body>
<!-- 4. box核心内容区域开始 -->
<div class="box w">

<div class="box-hd">
<h3>精品推荐</h3>
<a href="#">查看全部</a>
</div>

<div class="box-bd">
<ul class="clearfix">

//这里写一个小模块,打个样,不输出,待会直接循环输出。
<!-- <li>
<a href="#">
<img src="images/course01.png" alt="">
<h4>
Think PHP 5.0 博客系统实战项目演练
</h4>
<div class="info">
<span>高级</span> • <span>1125</span>人在学习
</div>
</a>
</li> -->

<script>
//创建一个数组对象,存放一些数据。
let data = [
{
src: 'images/course01.png',
title: 'Think PHP 5.0 博客系统实战项目演练',
num: 1125 // 学习人数
},
//。。。中间省略一堆模块。。。
{
src: 'images/course04.png',
title: '自动添加的模块',
num: 1000
}
]

//for循环输出对象信息(包在li标签、a标签里面)
for (let i = 0; i < data.length; i++) {
document.write(`
<li>
<a href="#">
<img src=${data[i].src} title="${data[i].title}">
<h4>
${data[i].title}
</h4>
<div class="info">
<span>高级</span> • <span>${data[i].num}</span>人在学习
</div>
</a>
</li>
`)
}
</script>
</ul>
</div>
</div>
</body>

JavaScript 堆与栈

11. 堆与栈

简单数据类型的堆栈存储.png
可以从图中看到,简单数据类型直接将值存储在栈中,赋值后不会引起重赋值影响。
复杂数据类型的堆栈存储.png
对应的,复杂数据类型(对象),会将值和属性存在堆中,栈中只有对应指向的地址,因此存在赋值后引起的重赋值变动影响。

11.1 声明变量const优先

声明变量优先const,如果变量需要变化,再换成let。

简单数据类型,变量发生变化,就必须用let;
但是复杂数据类型,对象/数组发生追加,还是可以用const,因为栈中地址未发生变化。
但是,如果对象/数组中存储的类型发生了改变,就会导致地址发生变动,就会让const报错。(比如空变有)

因此,变量声明用const居多。

什么时候用let?
(a) 基本数据类型的值/复杂数据类型的地址发生改变,需要let
(b) 一个变量需要加减运算,例如循环中的i++等,需要let

更多JavaScript内容放在第二份js笔记中,将会记录一些API调用相关的内容。