JavaScript基础
# JavaScript介绍
# 介绍
js是一门脚本语言,是一种轻量级的编程语言,它是一种可插入HTML页面的编程代码,插入后可由所有的现代浏览器执行。
node.js能支持js代码跑在后端服务器上,所以它也可以用来写后端代码。
# 注释语法
单行注释
// 我是一条注释
多行注释
/*
多行注释1
多行注释2
... ...
*/
2
3
4
5
# JS分号
JavaScript是以分号作为语句的结束符。
# 引用方式
第一种方式:script标签内部直接书写js代码。
<!-- 例如: -->
<script>... ...</script>
2
第二种方式:script标签src属性导入外部js文件,其中src可以是本地路径,也可以是远程Url。
<!-- 例如: -->
<script src="home.js"></script>
2
# JavaScript变量
# 定义变量方式
JS定义变量名时,需要用关键字声明。
# 关键字var
var语法定义变量会作用于全局。
例如:
var name="thankneko";
# 关键字let
let语法定义变量会区分局部和全局,在局部定义则作用于局部,在全局则作用于全局。
例如:
let name="thankneko";
# 定义常量方式
# 关键字const
js中可以通过关键字const定义常量,常量定义后值无法修改。
例如:
const name="thankneko";
# 变量命名规范
- js中变量名只能是"数字、字母、下划线、$"。
- 不能用关键字作为变量名。
- js中变量名推荐使用小驼峰命名法。
# JavaScript数据类型
# 介绍
JS是动态类型的编程语言,会自动识别值的数据类型。
JS中可以通过typeof [变量名];查看变量的数据类型。
# 数值类型
# 定义
整数和浮点数都是数值类型,特殊的NaN也是数值类型,表示"不是一个数字"。
// 例如:
var a = 11;
var a = 11.11;
2
3
# 数值类型转换
parseInt();
会截取浮点数的整数部分进行转换。
会截取字符串的数值部分,遇到非数值则会停下,如果第一位就不是数值,则返回NaN。
parseFloat();
与上面一样,不同的是可以截取出小数点后的。
# 字符串类型
# 定义
单行文本可以通过''和""定义,多行文本可以通过``模板字符串定义。
模板字符串可用于定义多行文本、格式化字符串。格式化字符串 "${变量名}" 会引用上文的变量名。
// 例如:
var name="hhh";
var msg=`hhhhh
hhhhh`
var sss=`my name is ${name}`
2
3
4
5
# 字符串拼接
直接使用+号拼接即可,例如:sss = "字符串1" + "字符串2"
# 常用方法
返回字符串长度:[字符串].length
移除字符串左右两侧的空白字符:[字符串].trim()
无法指定去除的内容。
移除字符串左侧的空白字符:
[字符串].trimLeft()移除字符串右侧的空白字符:
[字符串].trimRight()
返回指定索引对应的字符串内容:[字符串].charAt(索引值)
对字符串进行切片:[字符串].slice(start, end)
可识别负数,顾头不顾尾。
从左往右查找指定内容:[字符串].indexOf("指定内容")
会返回字符串中第一次出现指定内容的索引。
将字符串字母转为全小写:[字符串].toLowerCase()
将字符串字母转为全大写:[字符串].toUpperCase()
按指定分隔符切割字符串:[字符串].split("分隔符")
后面可跟个数值参数,取切割结果的前几个元素。
在后面拼接上指定的字符串:[字符串].concat("字符串1", "字符串2"...)
JS是弱类型语言,会自动转换数据类型。
字符串非贪婪正则匹配:[字符串].match(/正则表达式/)
也可以传入正则对象。
会返回一个列表,存放匹配到的值。
字符串贪婪正则匹配:[字符串].match(/正则表达式/g)
也可以传入正则对象。
会返回一个列表,存放匹配到的值。
# 布尔类型
true / false 在JS中,布尔值是全小写的。
其中false包括:空字符串、0、null、undefined、NaN。
# null
表示一个变量的值为空,可用于指定或清空变量的值。
# undefined
表示一个变量没有赋值,函数没有指定返回值时,会返回undefined。
# JavaScript运算
# 算术运算符
+ 加
- 减
* 乘
/ 除
% 取余
** 取幂
++ 递增
-- 递减
# 自增自减
加号在后面,先做赋值后自增+1。
var a=x++
// x的值先赋值给a,然后x再自增+1,同等于:
var x=10
var a=x++
2
3
4
5
6
加号在前面,先自增+1后赋值。
var a=++x
// x先自增+1,然后x的值再赋值给a,同等于:
var x=10
var a=++x
2
3
4
5
6
# 比较运算符
> 大于。
< 小于。
>= 大于或等于。
<= 小于或等于。
== 等于,弱等于,内部会自动转换成相同的数据类型。
如:
1 == 1 返回 true 1 == "1" 返回 true
=== 绝对等于,强等于,内部不会自动转换成相同的数据类型。
如:
1 === 1 返回 true 1 === "1" 返回 false
!= 不等于,弱不等于,内部会自动转换成相同的数据类型。
如:
1 != 1 返回 false 1 != "1" 返回 false
!== 不绝对等于,强不等于,内部不会自动转换成相同的数据类型。
如:
1 !== 1 返回 false 1 !== "1" 返回 true
# 逻辑运算符
比较运算返回的是布尔值,逻辑运算返回的是数据。
&& 与,左边为真时,结果的值就是右边的值。
|| 或,左边为真时,结果的值就是左边的值。
! 非,取反。
# 赋值运算符
=、+=、-=、*=、/=
# 展开运算符
展开运算符用三个点 ... 表示,主要用于把可迭代对象或对象的属性拆开,可用于
// 数组的展开
const a = [1, 2, 3];
const b = [4, 5];
// 合并数组
const merged = [...a, ...b]; // [1,2,3,4,5]
// 在数组中插入元素
const result = [0, ...a, 6]; // [0,1,2,3,6]
// 复制数组(浅拷贝)
const copy = [...a]; // [1,2,3]
// 对象的展开
const obj1 = { name: 'Alice', age: 25 };
const obj2 = { city: 'Beijing', hobby: 'reading' };
// 合并对象(后面的属性会覆盖前面的同名属性)
const mergedObj = { ...obj1, ...obj2 };
// { name:'Alice', age:25, city:'Beijing', hobby:'reading' }
// 复制对象(浅拷贝)
const copyObj = { ...obj1 };
// 展开并作为参数传入
function sum(x, y, z) {
return x + y + z;
}
const args = [1, 2, 3];
const total = sum(...args);
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
# JavaScript流程控制
# if判断语法
# 单分支 if
if(条件){条件成立时执行的代码块}
# 双分支 if-else
if(条件){... ...}
else{条件不成立时执行的代码块}
2
# 多分支 if-else if-else
if(条件1){... ...}
else if(条件2){... ...}
else if(条件3){... ...}
... ...
else{... ...}
2
3
4
5
# switch分支语法
用于提前列举好可能出现的条件和解决方式。
break用于跳出该switch,如果不加则会继续往下匹配。
switch(变量){
case 值1:
变量值为值1时会执行的代码块
break;
case 值2:
变量值为值2时会执行的代码块
break;
... ...
default:
上面条件都没匹配上时,默认执行的代码块
最后一条可以不写break
}
2
3
4
5
6
7
8
9
10
11
12
# for循环语法
# C风格循环
for(起始条件; 循环条件; 每次循环后执行的操作){
循环执行的代码块
}
2
3
# 迭代循环
循环中目前迭代到的索引会赋值给变量。
for(let 变量名 in 迭代对象){
循环执行的代码块
}
2
3
# while循环语法
while(循环条件){
循环执行的代码块
}
2
3
# 三元运算符
[条件]?[成立时执行的表达式]:[不成立时执行的表达式]
条件成立取"?"后面的值,否则取":"后面的值。
// 例如:
1>2?console.log("yes"):console.log("no")
res = 1>2?1:3
2
3
# JavaScript函数
注意:
js函数即便多传或少传参数,都不会报错。
js函数的返回值,如果用多个","隔开,则只会返回最后一个,如需返回多个可以使用数组。
js函数会先查找函数体内的变量,找不到再去全局变量找。
# 函数定义
JS定义函数的关键字是:function。
function 函数名(形参1,形参2...){函数体代码}
# 控制函数传参
函数体内会有一个arguments变量,用于接收传入的所有参数,我们可用它来控制函数的传参,可以判断arguments的长度、参数等。
// 例如:
function funcname(args){
if (arguments.length!=1) {
console.log("传入的参数不正确!")
}
}
2
3
4
5
6
# 函数传入标签对象
调用函数时,可以通过传入标签的id值来传入标签对象,它会找对id对应的标签对象并传入。
<p id="one">Test</p>
function test(ele){
console.log(ele);
}
test(one)
2
3
4
5
6
# 匿名函数
function (形参) {
...
}
2
3
# 箭头函数
由于箭头函数本身没有this,所以在使用this时会使用上一层的this。
// 匿名箭头函数
(形参) => ...;
// 有名箭头函数
var 函数名 = (形参) => ...;
var 函数名 = (形参) => {
...
}
2
3
4
5
6
7
8
# JavaScript对象
JS中也是一切皆对象,js中的对象包含数组、自定义对象等。
[] - 数组类型,类似于Python列表。
{} - 自定义对象,类似于Python中的字典,可以存储方法或数据。
# 数组类型定义
// 数组定义
var test = [1, 2, "test", true]
// 数组[索引],索引取值,不支持负数。
test[0]
2
3
4
5
# 数组类型方法
返回数组的元素个数:[数组].length
尾部追加元素:[数组].push(元素)
弹出尾部元素:[数组].pop()
头部插入元素:[数组].unshift(元素)
移除头部元素:[数组].shift()
切片:[数组].slice(start, end)
将数组以分隔符连接成字符串:[数组].join("分隔符")
将指定数组的元素追加到数组中:[数组].concat(数组)
相当于python中列表的extend方法。
for循环传入函数:[数组].forEach(函数)
会将数组的元素用for取出,一个一个传入函数中。可以传入已有的函数,也可以临时定义匿名函数:
[数组].forEach(function(形参){函数体})函数需要的参数越多,会传入更多的值。
- 第一个会传入元素值。
- 第二个会传入元素对应的索引值。
- 第三个会传入元素的数据来源。
从数组中移除范围区间的元素:[数组].splice(start, end)
从数组中移除start索引到end索引的元素,当有第三个参数时,第三个参数会作为元素插入删除了元素的位置。
数组过滤:[数组].filter(function(item){...})
不修改原数组,过滤完后会返回过滤后数组。
它会将数组的元素,一个个传入匿名函数,如果函数返回true则保留该元素,如果返回false则不保留。
# 对象定义
第一种方式:var [对象名]={key:value, key:value...}
var d={'name': 'sekaiova', 'age': 18}
第二种方式:var [对象名]=new Object()
关键字new可创建自定义对象、内置对象。new Object()会创建空自定义对象。
# 对象赋值取值
对象名[key] 或 对象名.key 可以用于赋值和取值。
// 例如:
d["name"] = "hhh"
d.name = "hhh"
console.log(d["name"])
console.log(d.name)
// 支持用for循环迭代自定义对象的键key
for(let i in d){
console.log(i, d[i])
}
2
3
4
5
6
7
8
9
10
# 解构赋值
解构赋值用于从数组或对象中提取值,并一次性把这些值赋给对应的变量,类似于Python的解压赋值。
数组解构赋值
解构时左侧的变量顺序与数组的索引对应,缺失的元素会得到undefined(除非提供默认值)。
const arr = [10, 20, 30];
// 基本写法
const [a, b, c] = arr; // a=10, b=20, c=30
// 跳过元素
const [first, , third] = arr; // first=10, third=30
// 默认值
const [x = 1, y = 2] = [5]; // x=5, y=2
// 剩余元素(rest)
const [head, ...tail] = arr; // head=10, tail=[20,30]
2
3
4
5
6
7
8
9
10
11
12
13
对象解构赋值
const obj = { name: 'Alice', age: 25, city: 'Beijing' };
// 基本写法(变量名必须与属性名相同)
const { name, age } = obj; // name='Alice', age=25
// 重命名(给变量起别名)
const { name: userName, city: location } = obj; // userName='Alice', location='Beijing'
// 默认值
const { gender = 'female' } = obj; // gender='female'(因为对象里没有 gender)
// 剩余属性(rest)
const { name, ...rest } = obj; // rest={ age:25, city:'Beijing' }
2
3
4
5
6
7
8
9
10
11
12
13
# 常用内置对象
# Date对象
创建时间对象:let [对象名]=new Date()
括号内也可以手动指定时间:
Date("2011/11/11 11:11:11")
Date对象的月份是从0开始的"0-11",所以下面方式传入要-1:
Date(2011,11,11,11,11,11)
时间对象取值:
结构化时间:
[时间对象]格式化时间:
[时间对象].toLocaleString()获取时间戳:
[时间对象].getTime()获取指定单位时间:
[时间对象].getDate() - 获取日
[时间对象].getDay() - 获取星期
[时间对象].getMonth() - 获取月份
[时间对象].getFullYear() - 获取年份
[时间对象].get...()
# JSON对象
JSON可以不创建JSON对象,直接使用JSON也可以使用序列化、反序列化方法。
序列化:JSON.stringify("数据类型")
将数据类型转化为JSON字符串。
反序列化:JSON.parse("JSON字符串")
将JSON字符串转化为数据类型。
# RegExp对象
JS使用正则需要创建正则对象。
创建正则对象:
第一种方式:let [对象名]=new RegExp("正则表达式")
需以文本方式指定用于匹配内容的正则表达式。
第二种方式 (更方便):let [对象名]=/正则表达式/
/正则表达式/ 为非贪婪匹配,匹配到第一个就停止。
/正则表达式/g 为贪婪匹配,会匹配整行字符串。
正则对象方法:
[正则对象].test("需要匹配的内容")
判断正则对象是否可以匹配指定的内容,返回布尔值。
当test什么都不传时,会默认传入"undefined"。
注意:
全局匹配会有一个LastIndex属性,匹配后索引会停在上次最后匹配到的位置。如果不需要可以不使用全局匹配,或者也可以手动重置该属性regobj.lastIndex = 0。
# 对象属性简写
在ES6中,创建对象时,如果对象的属性名和变量名相同,则可以使用属性简写来让代码更简洁。
const name = 'Alice';
const age = 25;
// 基本写法
const person = {
name: name,
age: age
};
// 属性简写:对象的属性名和变量名相同
const person = { name, age };
2
3
4
5
6
7
8
9
10
11
# 对象方法简写
ES6还支持方法简写,即在对象里直接写函数定义,而不需要 function 关键字和冒号。
// 基本写法
const obj = {
greet: function() {
console.log('Hello');
}
};
// 方法简写
const obj = {
greet() {
console.log('Hello');
}
};
2
3
4
5
6
7
8
9
10
11
12
13
# JavaScript模块化
# 介绍
JS模块化是一种将JS代码拆分位若干个可复用、可按需导入的单独模块的机制。
如果不使用模块化,则只能通过Script标签引入JS文件,但这种方式依赖关系不明显、代码复用困难,还会污染全局变量。
# 常用模块化方案
| 特性 | ES6 模块(ESM) | CommonJS(CJS) |
|---|---|---|
| 关键字 | import / export | require() / module.exports |
| 运行方式 | 预解析(静态导入) | 运行时(动态导入) |
| 是否支持顶层导入 | ✅ 是 | ❌ 否 |
| 是否支持异步导入 | ✅ import() | ❌ 仅同步 |
| 适用环境 | 浏览器 & Node.js (ESM) | Node.js (CJS) |
| 默认方式 | 适用于浏览器和前端 | Node.js 默认方式 |
# 导入与导出
模块化的核⼼思想就是:模块之间是隔离的,通过导⼊和导出进⾏数据和功能的共享。
我们可以导入导出变量、函数或类。
导入的就是引入其他模块导出的内容,以使用其代码和功能。
导出就是公开当前模块的指定内容,使其他模块可以导入这些公开的内容。
# ES6 Modules
ES6在2015年引入了 import 和 export 关键字,成为JavaScript官方的模块化方案(ECMAScript Modules, ESM)。
浏览器端应用广泛。
# 导出
声明的同时导出:
export const 命名 = 值;export function 命名 () {...};export class 命名 {...};
先声明后导出:
export 命名;export { 命名1, 命名2, ... };
默认导出:
export default ...;- 一个模块只能有一个默认导出,它代表模块的核心功能,默认导出在导入时书写更简洁。
// 声明的同时命名导出
export let name = "Hello"
export let age = 18
// 先声明后命名导出
let name = "Hello"
let age = 18
export { name, age };
// 声明的同时默认导出
export default function sayHi(){
console.log("Hi!")
}
// 先声明后默认导出
export default sayHi;
// 默认导出也可以导出多个
export default { name, age, sayHi };
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 导入
如果要在HTML文件中使用ES6模块,则需要在script标签中加
type='module'属性,才能在其中使用import语句进行导入。在JS文件中则可以直接import导入。
默认导入:import 命名 from 'JS文件路径';
命名导入:import { 命名1, 命名2, ... } from 'JS文件路径';
// 命名导入时需要指定确切的名称
import { name, age } from './test.js';
// 命名导入的同时取别名,需使用as关键字
import { name as myName, age as myAge } from './test.js';
// 默认导入时可以使用任何名称,也无需使用as关键字
import sayHi from './test.js';
// 可以同时使用默认和命名导入
import sayHi, { name, age } from './test.js';
// 在HTML文件中导入
<script type="module">
import { name } from './test.js'
console.log(name)
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# CommonJS
CommonJS 使用 exports 和 require 来进行导入导出。
服务端应用广泛。
# 导出
直接赋值(推荐):module.exports = { 内部名称1, 内部名称2, ... };
逐个挂载(不推荐):export.命名 = 内部名称;
let name = "Hello"
let age = 18
// 直接赋值(推荐)
module.exports = { name, age }
// 逐个挂载(不推荐)
exports.name = name
exports.age = age
2
3
4
5
6
7
8
9
# 导入
导入模块:const 命名 = require('JS文件路径');
解构导入:const { 命名1, 命名2, ... } = require('JS文件路径');
CommonJS中相对路径的本地模块(以./或../开头)可以省略.js后缀,Node.js会自动帮你加上。
// 导入模块
const Test = require('./test');
// 使用模块导出的内容
console.log(Test.name)
// 解构导入模块中的内容
const { name, age } = require('./test');
// 使用解构导入的模块的内容
console.log(name)
2
3
4
5
6
7
8
9