JavaScript基础语法
一、JavaScript简介
1.1 JavaScript 代码的书写位置
1.1.1 内部js代码
直接写在html文件中,使用 script 标签包裹,这个 script 标签要放在 body 标签之内,并且要放在最靠近结束标签 </body>的位置。
我们将 script 放在HTML文件的底部附近的原因是浏览器会按照代码在文件中的顺序加载 HTML。如果先加载的 JavaScript 期望修改其下方的 HTML,那么它可能由于 HTML 尚未被加载而失效。因此,将 JavaScript 代码放在 HTML页面的底部附近通常是最好的策略。
=== "外部js代码"
将js代码写在 .js 后缀的文件中,在html文件中使用 script 标签引入。
<script src=""></script>
???+ note
1. script标签中间无需写代码,否则会被忽略!
2. 外部JavaScript会使代码更加有序,更易于复用,且没有了脚本的混合,HTML 也会更加易读,因此这是个好的习惯。
=== "写在其他html标签内部"
此处不介绍
1.2 注释
单行注释 //,快捷键 ++ctrl+slash++
多行注释 /* 此处代码会被忽略 */,快捷键 ++shift+alt+a++
1.3 结束符
js代码使用 ; 作为每一行代码结束的标志,可写可不写,但是要统一
实际情况: 实际开发中,可写可不写, 浏览器(JavaScript 引擎) 可以自动推断语句的结束位置
现状: 在实际开发中,越来越多的人主张,书写 JavaScript 代码时省略结束符
约定:为了风格统一,结束符要么每句都写,要么每句都不写(按照团队要求.)
1.4 常用的输入输出语句
document.write('要输出的内容')在网页上输出内容,可以传入包含html标签的字符串,这些字符串会被添加到body标签内alert()页面弹出警告对话框console.log('要输出的内容')在浏览器控制台输出传入的内容prompt('提示信息')显示一个对话框,对话框中包含一条文字信息,用来提示用户输入文字,返回的数据是字符串类型,如果输入的是数字一般使用+进行隐式转换
???+ note "JavaScript 代码执行顺序"
按HTML文档流顺序执行JavaScript代码
`alert()` 和 `prompt()` 它们会跳过页面渲染先被执行
二、变量
使用 let 关键字来声明变量,一般声明变量就要初始化(对变量赋值)。
!!! warning
不要使用关键字 var 来声明变量,let 的各方面均由于 var
可以一次性声明多个变量,不同变量之间使用 , 分隔,但是不推荐使用。
??? question "算法——交换两个变量的值"
有两个变量a和b,需要交换二者的值?
1. 声明一个临时变量t
2. 将a的值赋值给t,即 `t = a`
3. 将b的值赋值给a,即 `a = b`
4. 将t的值赋值给b,即 `b = t`
```js
// 已知两个变量a,b
let a = 17
let b = 20
// a,b交换之前的输出结果
console.log(a, b) // 17 20
// 通过临时变量进行交换
let c = a
a = b
b = c
// a,b交换之后的输出结果
console.log(a, b) // 20 17
```
???+ note "变量命名规范"
- 不能用js关键字
- 只能用下划线、字母、数字、$组成,且数字不能开头
- 区分大小写
- 见名知意
- 遵守小驼峰命名法,第一个单词首字母小写,后面每个单词首字母大写。例:userName
???+ info "数组array"
类似于python中的列表,但是只能使用正下标,不能使用负数下标,可以存储不同的数据类型
可以对数组变量使用 `.length` 来获取数组长度
???+ "常量"
使用 const 关键字来声明常量,常量声明时必须初始化,命名时常量的变量名全大写。
三、数据类型
- 基本数据类型:
- number 数字型
- string 字符串型
- boolean 布尔型
- undefined 未定义型
- null 空类型
- 引用数据类型:
- object 对象
3.1 数字number
js中的数字类型类似于python中的数字类型。NaN 是js中的一个特殊的数字,它代表一个计算错误,它是一个不正确的或者一个未定义的数学操作所得到的结果,任何对 NaN 的操作都会返回 NaN
3.2 字符串string
通过单引号(') 、双引号(")或反引号(`) 包裹的数据都叫字符串,单引号和双引号没有本质上的区别,推荐使用单引号。字符串可以使用 + 拼接。字符串中有变量时,可以用 ${ } 包住变量,类似于python中是 f字符串
- 无论单引号或是双引号必须成对使用
- 单引号/双引号可以互相嵌套,但是不以自已嵌套自已(口诀:外双内单,或者外单内双)
- 必要时可以使用转义符 \,输出单引号或双引号
3.3 布尔值boolean
表示肯定或否定时在计算机中对应的是布尔类型数据。
它有两个固定的值 true 和 false,表示肯定的数据用 true(真),表示否定的数据用 false(假)。
3.4 未定义类型undefined
未定义是比较特殊的类型,只有一个值 undefined
只声明变量,不赋值的情况下,变量的默认值为 undefined,一般很少直接为某个变量赋值为 undefined。我们开发中经常声明一个变量,等待传送过来的数据。如果我们不知道这个数据是否传递过来,此时我们可以通过检测这个变量是不是undefined,就判断用户是否有数据传递过来。
3.5 空类型null
JavaScript 中的 null 仅仅是一个代表“无”、“空”或“值未知”的特殊值。常把 null 作为尚未创建的对象,即将来有个变量里面存放的是一个对象,但是对象还没创建好,可以先给个null
???+ null 和 undefined 区别
undefined 表示没有赋值
null 表示赋值了,但是内容为空
3.6 使用typeof判断数据类型
typeof 运算符可以返回被检测的数据类型。它支持两种语法形式(用x表示变量):
- 作为运算符:
typeof x(常用的写法) - 函数形式:
typeof(x)
3.7 类型转换
=== "隐式转换"
某些运算符被执行时,系统内部自动将数据类型进行转换,这种转换称为隐式转换。
`+` 号两边只要有一个是字符串,都会把另外一个转成字符串。除了+以外的算术运算符 比如 - * / 等都会把数据转成数字类型
???+ tip
- `+` 号作为正号解析可以转换成数字型
- 任何数据和字符串相加结果都是字符串
=== "强制转换"
转换成数字类型:
- `Number(数据)` 转成数字类型。如果字符串内容里有非数字,转换失败时结果为 NaN,NaN也是number类型的数据,代表非数字
- `parseInt(数据)` 只保留整数,可以以数字开头的字符串中提取整数
???+ tip "将秒数转换为时分秒"
- 小时数: `h = parseInt(总秒数 / 60 / 60 % 24)`
- 分钟数: `m = parseInt(总秒数 / 60 % 60)`
- 秒数: `s = parseInt(总秒数 % 60)`
- `parseFloat(数据)` 可以保留小数,可以以数字开头的字符串中提取数字
转换成字符串类型:
`String(数据)`
`变量.toString(进制)`
转换为布尔值:
- 强制转换 `Boolean()` 函数 将 `''`, `0`, `undefined`, `null`, `false`, `NaN` 转换为false
- 进行数学加减法运算时 `''`, `null`, `false` 会转换为数字0
四、运算符
???+ info "优先级"
1. 小括号 ()
2. 一元运算符 自增 ++,自减 --,逻辑非 !
3. 算术运算符 按照数学运算顺序
4. 关系运算符 >, >=, <, <=
5. 相等运算符 ==, !=, ===, !==
6. 逻辑且 &&
7. 逻辑或 ||
8. 赋值运算符 =
9. 逗号运算符 ,
=== "算术运算符"
- +求和
- -求差
- *求积
- /求商
- %取模(取余数)
=== "赋值运算符"
- =
- +=
- -=
- *=
- /=
- %=
=== "自增自减运算符"
自增自减运算符可以放在变量之前,也可以放在变量之后,一般放在变量之后。
- `++` 自增运算符
- `--` 自减运算符
=== "比较运算符"
- >
- <
- >=
- <=
- == 值是否相等,不推荐使用
- != 不等于,不推荐使用
- === 类型和值是否都相等
- !== 左右两边是否不全等
???+ note
涉及到NaN的比较返回false
=== "逻辑运算符"
- && 且
- || 或
- ! 非
五、分支语句
5.1 if语句
=== "单分支"
js if (条件) { 条件成立时执行的代码 }
=== "双分支"
js if (条件) { 条件成立时执行的代码 } else { 条件不成立时执行的代码 }
!!! tip "三目运算符"
三目运算符可以替代简单的if双分支语句。
语法:
`条件? true时执行的代码: false时执行的代码`
=== "多分支"
js if (条件) { 代码 } else if (条件) { 代码 } else { 代码 }
5.2 switch语句
switch (变量名) {
case 值1:
代码
break
case 值2:
代码
break
default:
代码
break
}???+ note
- 找到跟小括号里数据全等的case值,并执行里面对应的代码。若没有全等 === 的则执行default里的代码
- switch case语句一般用于等值判断,不适合于区间判断(if语句)
- switch case一般需要配合break关键字使用 没有break会造成case穿透
六、循环语句
6.1 while循环
while (循环终止条件) {
循环体
使循环终止的代码(一般是自增自减运算)
}???+ note "循环语句三要素"
- 变量起始值
- 循环终止条件:当条件为true时才执行循环中的代码
- 使循环终止的代码:常用自增自减运算
6.2 for循环
for (变量起始值; 循环终止条件; 使循环终止的代码) {
循环体
}6.3 退出循环
break 语句,退出本次循环
continue 语句,退出整个循环语句
七、数组Array
使用let声明一个数组的两种方式:
let myArr = [元素1, 元素2, 元素3]let myArr = new Array(元素1, 元素2, 元素3)
和python中的列表类似,不过下标索引只支持正向索引。通过数组的 length 属性,可以获取数组的长度。
使用for循环遍历数组
// let arr = new Array('js', 'html', 'css')
let arr = ['js', 'html', 'css']
for (let i = 0; i < arr.length; i++) {
alert(arr[i])
}??? question "算法——寻找数组中的最大值和最小值"
寻找数组[2, 6, 1, 77, 52, 25, 7]中的最大值和最小值。
```js
let arr = [2, 6, 1, 77, 52, 25, 7]
// 第一步:假设下标为0的元素就是最大值,也是最小值
let max = arr[0]
let min = arr[0]
// 第二步:for循环遍历,让假定的最值依次和其他元素比较
for (let i = 1; i < arr.length; i++) {
// 第三步:如果找到比假定的最大值还要大的数,将这个数假定为最大值
if (arr[i] > max) {
max = arr[i]
}
// 第三步:如果找到比假定的最小值还要小的数,将这个数假定为最小值
if (arr[i] < min) {
min = arr[i]
}
}
console.log(max) // 77
console.log(min) // 1
```
操作数组:
- 重新赋值 arr[i] = 新值
- 在末尾追加元素
arr.push('元素1', '元素2', '元素3')方法,在数组末尾追加一个或多个元素 - 在开头插入元素
arr.unshift('元素1', '元素2', '元素3')方法,在数组开头插入一个或多个元素,返回新数组长度 - 删除元素
- arr.pop() 删除最后一个元素,返回这个被删除的元素
- arr.shift() 删除第一个元素,返回这个被删除的元素
- arr.splice(start, deleteCount) 其中start参数表示开始删除位置的下标,可选参数deleteCount表示删除元素的个数,此方法从start下标开始,删除deleteCount个元素,未传入deleteCount时,删除之后的所有元素
- 排序 arr.sort() 数组元素从小到大排序,此操作会改变原数组
// 默认,从小到大排序 arr.sort(function(a, b) { return a - b }) // 从大到小排序 arr.sort(function(a, b) { return b - a })
??? question "算法——冒泡排序"
将数组[5, 4, 3, 2, 1]中的元素按照从小到大排序:
冒泡排序依次将最大的书往右边移动,每执行一趟,就会有一个数移动到最右侧。{==|==} 右侧是已经排好了的数字。
**分析:**
- 原顺序 ++5++ ++4++ ++3++ ++2++ ++1++
- 第0趟(需要比较4次):
- 第0次比较 ++4++ ++5++ ++3++ ++2++ ++1++ {==|==}
- 第1次比较 ++4++ ++3++ ++5++ ++2++ ++1++ {==|==}
- 第2次比较 ++4++ ++3++ ++2++ ++5++ ++1++ {==|==}
- 第3次比较 ++4++ ++3++ ++2++ ++1++ ++5++ {==|==}
- 第1趟(需要比较3次):
- 第0次比较 ++3++ ++4++ ++2++ ++1++ {==|==} ++5++
- 第1次比较 ++3++ ++2++ ++4++ ++1++ {==|==} ++5++
- 第2次比较 ++3++ ++2++ ++1++ ++4++ {==|==} ++5++
- 第2趟(需要比较2次):
- 第0次比较 ++2++ ++3++ ++1++ {==|==} ++4++ ++5++
- 第1次比较 ++2++ ++1++ ++3++ {==|==} ++4++ ++5++
- 第3趟(需要比较1次):
- 第0次比较 ++1++ ++2++ {==|==} ++3++ ++4++ ++5++
第一步:外层for循环(趟数是4趟,需要循环4次)数组总长度arr.length是5,因此循环终止条件是arr.length-1
for (let i = 0; i < arr.length-1; i++) {
内层for循环
}
第二步:内层for循环(每趟需要比较的次数,需要比较 arr.length-1-趟序号 次)
for (let j = 0; j < arr.length-i-1; j++) {
相邻两数,如果左大于右,交换两数的值
}
第三步:交换两个数的值
if (arr[j] > arr[j + 1]) {
let t = arr[j]
arr[j] = arr[j + 1]
arr[j + 1] = t
}
```js
let arr = [5, 4, 3, 2, 1]
console.log(arr) // [5, 4, 3, 2, 1]
// 将此数组元素从小到大排序
for (let i=0; i < arr.length-1; i++) {
for (let j = 0; j < arr.length-i-1; j++) {
if (arr[j] > arr[j+1]) {
let t = arr[j]
arr[j] = arr[j+1]
arr[j+1] = t
}
}
}
console.log(arr) // [1, 2, 3, 4, 5]
```
???+ tip "map方法(常用)"
数组的 .map(function (item, index) {}) 方法, 类似于python列表推导式,可以用于产生新数组. 也类似于python列表遍历的 enumerate() 函数,可以同时遍历数组的元素和下标(但是这种遍历方法不推荐使用,因为 .map() 方法是用来产生新元组的).
语法:
```js
const arr = ['py', 'js', 'html', 'css']
const newArr = arr.map(function (item, index) {
console.log(item, index) // 遍历数组,依次输出数组元素和下标
return item + '语言'
})
console.log(newArr) // ['py语言', 'js语言', 'html语言', 'css语言']
```
???+ info ".join()方法"
数组的 .join() 可以用来将数组中的元素拼接为一个字符串, 类似于python中的 ','.join(list) 方法,只不过js中的 .join() 不传参时,相当于传入了默认值 ','
```js
const arr = ['py', 'js', 'html', 'css']
const newArr1 = arr.join()
console.log(newArr1) // py,js,html,css
const newArr2 = arr.join('')
console.log(newArr2) // pyjshtmlcss
```
???+ tip ".forEach()方法"
.forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数. 这个方法没有返回值,它的作用就是遍历数组, 类似于python的enumerate()函数
语法:
```js
arr.forEach(function(item, index) {
// 函数体
})
// 或
arr.forEach(function(item) {
// 函数体
})
```
=== "Python"
```py
mylist = ['py', 'c', 'js', 'css']
for index, item in enumerate(mylist):
print(index) # 遍历下标
print(item) # 遍历列表
```
=== "JavaScript"
```js
const arr = ['py', 'c', 'js', 'css']
// forEach可以同时遍历数组元素和下标
arr.forEach(function(item, index) {
console.log(item) // 遍历数组
console.log(index) // 遍历下标
})
```
???+ tip ".filter()方法"
.filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素. 用于筛选数组符合条件的元素,并返回筛选之后元素的新数组
语法:
```js
arr.filter(function(item, index){
return 筛选条件
})
// 或
arr.filter(function(item){
return 筛选条件
})
```
返回值:返回数组,包含了符合条件的所有元素。如果没有符合条件的元素则返回空数组. 因为返回新数组,所以不会影响原数组
```js
const arr = [51, 2, 7, 15, 37, 20]
const newArr = arr.filter(function(item, index){
return item > 20
})
console.log(newArr) // [51, 37]
```
八、函数
8.1 具名函数
function 函数名(参数) {
函数体
return 返回值
}- 定义函数时,参数可以为空,如果有多个参数,用逗号分隔
- 如果定义函数时,没有设置默认值,那么此参数的默认值是undefined
- 函数可以不设置返回值,无返回值的函数的返回值是undefined
- 函数内部使用let声明的变量只在函数内部生效(作用域是函数内部),如果函数内外有同名的变量,先访问局部变量再访问全局变量(就近原则)
???+ info "逻辑中断"
另一种设置函数默认值的方式:
js function getSum(a, b) { a = a || 0 b = b || 0 return a + b } // 相当于 function getSum(a=0, b=0) { return a + b }
使用且&&、或||,当满足一定条件时只让左边执行,而右边不执行。无论 && 还是 || ,运算结果都是最后被执行的表达式值,一般用在变量赋值
- `&&` 左边为false就短路
- `||` 左边为true就短路
???+ note "函数命名规范"
- 小驼峰命名法
- 以动词开头,以下为常用动词及其含义:
| 动词 | 含义 |
|:---:|---|
| can | 判断是否可以执行某个操作 |
| has | 判断是否包含某个值 |
| is | 判断是否为某个值 |
| get | 获取某个值 |
| set | 设置某个值 |
| load | 加载某些数据 |
8.2 匿名函数
两种匿名函数:
- 函数表达式:将匿名函数赋值给一个变量,并且通过变量名称进行调用 我们将这个称为函数表达式
// 定义匿名函数 let 变量名 = function () { 函数体 } // 调用匿名函数 变量名()
- 立即执行函数:不需要调用就能直接执行的匿名函数。多个立即执行函数之间使用分号隔开
// 写法一 (function () { 函数体 })(); // 写法二 (function () { 函数体 }());
九、对象
声明对象的两种方式:
- 方式一
let 对象名 = {} - 方式二
let 对象名 = new Object()
对象由属性和方法组成:
let 对象名 = {
属性名: 属性值,
方法名: 函数
}- 对象中的属性名和属性值类似于python中的字典
- 属性名值对使用逗号分隔
- 属性名可以使用 "" 或 ''包裹,一般情况下省略,除非名称遇到特殊符号如空格、连字符、下划线等
操作对象:
- 查询属性值:类似于python中的对象,可以使用
.属性名访问对象属性值;也类似于python中的字典,可以使用对象名[属性名]来访问属性值,属性名需要使用单引号或双引号包裹 - 更改属性值:类似于python中的对象和字典,可以对属性重新赋值
- 新增属性:操作同上,如果属性不存在,则会新增属性
- 删除属性:通过属性名删除属性
delete 对象名.属性名 - 对象中的方法:定义在对象中的函数就是方法,方法中也可以定义函数参数。调用方法类似于python中的方法
let obj = { sayHi: function() { alert('hi') } }
使用 for in 语句遍历对象,类似于python字典的遍历,此处获取属性值必须使用类似于python字典的写法:
let obj = {
name: 'jack',
age: 10,
gender: 'male'
}
for (let k in obj) {
console.log(k) // 属性名
console.log(obj[k]) // 属性值
}内置对象:
类似于python中的标准库。
内置对象 Math 提供一系列和数学计算相关的方法
- random:生成0-1之间的随机数(包含0不包括1)
- ceil:向上取整
- floor:向下取整
- max:找最大数
- min:找最小数
- pow:幂运算
- abs:绝对值
???+ tip "生成随机整数"
js // 生成0到10之间的随机整数 Math.floor(Math.random * 11) // 生成5到10之间的随机整数 Math.floor(Math.random * 6) + 5 // 生成N到M之间的随机整数 Math.floor(Math.random * (M - N + 1)) + N