一,介绍
1.1 基础知识
-
JavaScript 是什么?
- 是一种运行在客户端(浏览器)的编程语言,实现人机交互效果。
-
JavaScript 的作用
- 网页特效(监听用户的一些行为让网页作出对应的反馈)
- 表单验证(针对表单数据的合法性进行判断)
- 数据交互(获取后台的数据,渲染到前端)
- 服务端编程(node.js)

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

1.2 JS书写位置
-
内部 JavaScript
直接写在 html 文件里,用 script 标签包住
规范:script 标签写在</body>上面 -
外部 JavaScript
代码写在以.js 结尾的文件里面
语法:通过 scrippt 标签,将 js 引入 html 页面中
<body> <script src="my.js"></script> </body>script 标签中间无需写代码,否则会被忽略!
外部 lavascript 会使代码更加有序,更易于复用,且没有了脚本的混合,HTML 也会更加易读,因此这是个好的习惯。
-
内联 JavaScript
代码写在标签内部
语法:
<body> <button onclick="alert('内联js')"> 按钮 </button> </body>只做了解,实际代码不这么写
1.3 JS注释和结束符
-
单行注释
//注释,快捷键是ctrl+/ -
多行注释
/* 多行注释,快捷键是shift+alt+a */ -
结束符
- 作用:使用英文的
;代表语句结束 - 实际情况:实际开发中,可写可不写,浏览器可以自动推断语句结束位置
- 作用:使用英文的

1.4 输入输出语法
-
输出语法
-
语法 1
document.write('要输出的内容') document.write('<h1>要输出的内容</h1>')作用:向 body 内输出内容
注意:如果输出的内容写的是标签,也会被解析成网页元素
-
语法 2
alert('要输出的内容')作用:页面弹出警告对话框
-
语法 3
console.log('控制台打印')作用:控制台输出语法,我们 f12 的时候查看控制台调试用的
-
-
输入语法
-
语法
prompt('请输入你的name')作用:显示一个对话框,对话框中包含一条文字信息,用来提示用户输入文字
效果:
-

JavaScript 代码执行顺序
- 按HTML文档流顺序执行JavaScript代码
alert()和prompt()它们会跳过页面渲染先被执行
二,变量
在 JavaScript 中,变量是用于存储数据的“容器”。可以通过var、let或const来声明变量,这三者有不同的作用域和行为
2. 1 var 声明的变量
- 作用域:
var声明的变量有函数作用域。它在声明所在的函数内有效,如果在函数外声明,它就会是全局变量。 - 变量提升(Hoisting):
var声明的变量会提升到函数或全局作用域的顶部,但赋值保持原位。即使在声明之前使用,JavaScript不会报错,只是值为undefined。 - 重复声明: 可以多次用
var声明同一个变量。
console.log(x); // undefined
var x = 10;
console.log(x); // 10
2.2 let 声明的变量
- 作用域:
let具有块作用域,只在声明所在的块(例如{}内)有效。常用于局部变量。 - 变量提升: 虽然
let也会提升,但在其声明之前不能访问变量,会抛出ReferenceError。这种行为叫暂时性死区(Temporal Dead Zone, TDZ)。 - 重复声明: 在同一作用域内,不能重复声明同一个变量。
// console.log(y); // ReferenceError: Cannot access 'y' before initialization
let y = 20;
console.log(y); // 20
2.3 const 声明的变量
- 作用域:
const也具有块作用域,与let相同。 - 常量:
const用于声明常量,声明时必须赋值,之后不能再被重新赋值。不过,如果const声明的是一个对象或数组,虽然不能改变对这个对象的引用,但可以修改对象的属性或数组的元素。 - 变量提升:
const与let相同,也有暂时性死区。 - 重复声明: 在同一作用域内,不能重复声明同一个变量。
const z = 30;
// z = 40; // TypeError: Assignment to constant variable
2.4 小结
- 使用
var在现代JavaScript开发中逐渐减少,建议使用let或const。 let适用于需要改变值的变量,const则适用于声明常量或不会重新赋值的变量。
三,数据类型
JS 数据类型分为两大类:
- 基本数据类型
- number数字型
- string字符串型
- boolean布尔型
- undefined未定义型
- null空类型
- 引用数据类型
- object对象
3.1 基本数据类型
3.1.1 number数字型
JavaScript 中的正数、负数、小数等 统一称为 数字类型。
let age = 18 //整数
let price = 88.99 //小数
注意:
- JS是弱数据类型,变量到底数据哪种类型,只有赋值后我们才能确定
3.1.2 string字符串型
通过单引号'',双引号" ",反引号,包裹的数据都叫字符串,单引号和双引号没有本质上的区别,推荐使用单引号。
let uname = '小明' //使用单引号
let gender = "男" //使用双引号
let str= '' //这种情况叫空字符串
注意点:
- 无论单引号还是双引号必须成对使用
- 单引号/双引号可以互相嵌套,但是不以自已嵌套自已(口诀 :外双内单,或者外单内双 )
- 必要时可以使用转义符\,输出单引号或双引号
字符串拼接:
- 场景:+ 运算符可以实现字符串的拼接
- 口诀:数字相加,字符相连
模板字符串
-
使用场景:拼接字符串和变量
-
用法
- 使用反引号
- 内容拼接变量时,用 ${}包住变量
document.write('使用模板字符串之前的写法'+num+'测试') document.write(`使用模板字符串之后的写法${num}测试`)
3.1.3 boolean布尔型
表示肯定或否定时在计算机中对应的是布尔类型数据
它有两个固定的值 true 和 false,表示肯定的数据用 true(真),表示否定的数据用 false(假)。
let isTrue=true
console.log(isTrue)
3.1.4 undefined未定义型
未定义类型是比较特殊的数据类型,只有一个取值undefined
出现 undefined 的情况
- 只声明变量,不赋值的情况下,变量的默认值为 undefined,一般很少【直接】为某个变量赋值为 undefined。
开发中使用场景:
- 我们开发中经常声明一个变量,等待传送过来的数据,
如果我们不知道这个数据是否传递过来,此时我们可以通过检测这个变量是不是undefined,就判断用户是否有数据传递过来。
3.1.5 null空类型
JavaScript 中的 null 仅仅是一个代表无,空或值未知的特殊值。
let obj=null
null 和 undefined 的区别
- undefined 表示没有赋值
- null 表示赋值了,但是内容为空
null 开发中的使用场景:
- 将来有个变量里面存放的是一个对象,但是对象还没创建好,可以先给个null
3.2 检测数据类型
通过 typeof 关键字检测数据类型
-
typeof 运算符可以返回被检测的数据类型。它支持两种语法形式:
typeof x //作为运算符 typeof(x) //作为函数形式换言之,有括号和没有括号,得到的结果是一样的,所以我们直接使用运算符的写法。
3.3 类型转换
JavaScript 是弱数据类型,JavaScript 也不知道变量到底属于那种数据类型,只有赋值了才清楚
坑: 使用表单、prompt 获取过来的数据默认是字符串类型的,此时就不能直接简单的进行加法运算。
3.3.1 隐式转换
某些运算符被执行时,系统内部自动将数据类型进行转换,这种转换称为隐式转换。
规则:
+号两边只要有一个是字符串,都会把另外一个转成字符串- 除了
+以外的算术运算符 比如-*/等都会把数据转成数字类型
缺点:
- 转换类型不明确,需要经验才能总结
技巧:
-
+号作为正号解析可以转换成数字型console.log(+'123')//数字型 -
任何数据和字符串相加结果都是字符串
-
减法 -,会导致空字符串 "" 转换为 0
-
null 结果数字转换后会变成 0
-
undefined 结果数字转换会变成 NaN
3.3.2 显示转换
编写程序时过度依靠系统内部的隐式转换是不严禁的,因为隐式转换规律并不清晰,大多是靠经验总结的规律。
为了避免因隐式转换带来的问题,通常根逻辑需要对数据进行显示转换。
写法
Number(数据)- 转化为数字类型
- 如果字符串内容里有非数字,转换失败时结果为 NaN(NotaNumber)即不是一个数字
- NaN也是number类型的数据,代表非数字
parseInt(数据)- 只保留整数
parseFloat(数据)- 可保留小数
四,运算符
4.1 算数运算符
数字可以有很多操作,比如,乘法 *、除法 /、加法 +、减法 - 等等,所以经常和算术运算符一起。
数学运算符也叫算术运算符,主要包括加、减、乘、除、取余 (求模)。
+:求和-:求差*:求积/:求商%:取模(取余)
运算符优先级:同时使用多个运算符编写程序时,会按着某种顺序先后执行,我们称为优先级。JavaScript 中 优先级越高越先被执行,优先级相同时以书从左向右执行。
- 乘、除、取余优先级相同
- 加、减优先级相同
- 乘、除、取余优先级大于加、减
- 使用()可以提升优先级
- 总结:先乘除后加减,有括号先算括号里面的
4.2 赋值运算符
赋值运算符:对变量进行赋值的运算符
-
=:将等号右边的值赋予给左边,要求左边必须是一个容器 -
+=let nun=1 num +=1 //等价于num = num +1 -
-=let nun=1 num -=1 //等价于num = num -1 -
*=let nun=1 num *=1 //等价于num = num*1 -
/=let nun=1 num /=1 //等价于num = num/1 -
%=let nun=1 num %=1 //等价于num = num%1
4.3 自增运算符
- 自增
- 符号:
++ - 作用:让变量值+1
- 符号:
- 自减
- 符号:
-- - 作用:让变量值-1
- 符号:
let num=1
num++
num--
需要注意 ++ 和 -- 的位置不同效果也不同
num++和++num是不一样的a-num++代表的是先运算a-num然后再给num+1a+ ++num代表的是先运算num+1然后计算a-num
4.4 比较运算符
比较运算符:
>:大于<:小于>=:大于等于<=:小于等于==:值等于===:类型和值等相等(开发中更推荐使用这个)!=:值不等于!==:类型和值是否都不相等
比较结果为 boolean 类型,只会得到 true 或 false
坑点:
-
字符串比较,是比较字符对应的 ASCII 码
-
从左往右依次比较
-
如果第一位一样再比较第二位,以此类推
-
比较的少,了解即可
-
-
NaN 不等于任何值,包括它本身。
-
尽量不要比较小数,因为小数存在精度问题
-
不同类型之间比较会发生隐式转换
console.log(2 == '2')//结果为true,因为比较运算符存在隐式类型转换,会把'2'变成2,因为==值判断值 console.log(2 === '2‘)//结果为false,因为===同时比较值和类型
4.5 逻辑运算符
| 符号 | 名称 | 特点 |
|---|---|---|
| && | 逻辑与 | 两边都为true结果才为true |
| || | 逻辑或 | 有一个true结过就是true |
| ! | 逻辑非 | true变false,false变true |
4.6 运算符优先级
| 优先级 | 运算符 | 顺序 |
|---|---|---|
| 1(最高) | 小括号 | () |
| 2 | 一元运算符 | ++ -- ! |
| 3 | 算数运算符 | 先* / %后+ - |
| 4 | 关系运算符 | > >= < <= |
| 5 | 相等运算符 | == != === !== |
| 6 | 逻辑运算符 | 先&&后|| |
| 7 | 赋值运算符 | = |
| 8 | 逗号运算符 | , |
别管这么多,知道数学加减乘除顺序,知道 () 优先级最高,知道 && 大于 || 就好了
五,流程控制语句
5.1 表达式
表达式是可以被求值的代码,JavaScript 引擎会将其计算出一个结果。
例如:
num=3+4

5.2 分支语句
分支语句可以让我们有选择性的执行想要的代码。
5.2.1 if分支语句
-
单分支
if(条件){ //满足条件执行的代码 } -
双分支
if(条件){ //满足条件执行的代码 }else{ //不满足条件执行的代码 } -
多分支
if(条件){ //满足条件执行的代码 }else if(条件2){ //满足条件执行的代码 }else{ //不满足条件执行的代码 }
注意点:
-
括号内的条件为 true 时,进入大括号里执行代码
-
小括号内的结果若不是布尔类型时,会发生隐式转换转为布尔类型
-
如果大括号只有一个语句,大括号可以省略,但是,不提倡这么做
5.2.2 三元运算符
语法:
条件 ? 满足条件执行的语句 : 不满足条件执行的语句
5.2.3 switch语句
语法:
switch(表达式){
case 值1:
代码1
break
case 值2:
代码2
break
case 值3:
代码3
break
default:
默认代码
break
}
注意点:
- switch case语句用于等值判断,不适合于区间判断
- switch case一般需要配合break关键字使用 没有break会造成case穿透
5.3 循环语句
循环:重复执行一些操作,
5.3.1 while循环
语法:
while(循环条件){
//要重复执行的代码(循环体)
}
- 跟if语句很像,都要满足小括号里的条件为true才会进入循环体 执行代码
- while大括号里代码执行完毕后不会跳出,而是继续回到小括号里判断条件是否满足,若满足又执行大括号里的代码,然后再回到
小括号判断条件,直到括号内条件不满足,即跳出
while 循环三要素:循环的本质就是以某个变量为起始值,然后不断产生变化量,慢慢靠近终止条件的过程。所以,while 循环需要具备三要素:
- 变量起始值
- 循环终止条件(没有终止条件,循环会一直执行,造成死循环)
- 变量变化量(用自增或者自减)
举例:
let i=1
while(i <=3 ){
console.log(`次数${i}`)
i++
}
5.3.2 循环关键字
循环结束关键字:
- break:退出循环
- continue:结束本次循环,继续下次循环
举例:
let i=1
while(true){
if(i == 3){
break//结束循环
}
console.log(`次数${i}`)
i++
}
let j=1
while(true){
if(j == 3){
continue//结束本次循环执行,继续下次循环
}
console.log(`次数${i}`)
i++
}
5.3.3 for循环
-
作用:重复执行代码
-
好处:把声明起始值、循环条件、变化值写到一起,让人一目了然,它是最常使用的循环形式
-
语法:
for(变量起始值;终止条件;变量变化量){ //循环体 } for(let i=1;i<=3;i++){ console.log(`次数${i}`) }
5.3.4 循环嵌套
循环嵌套:一个循环里面再嵌套一个循环,一般用在 for 循环里面。
for(外部声明记录循环次数的变量;循环条件;变化值){
for(内部声明记录循环次数的变量;循环条件;变化值){
//循环体
}
}
- 不只是可for循环嵌套,for也可以和while相互嵌套,无所谓的,看具体实现。
- break和continue也可以用到for循环里面的,结束的是当前这个循环,具体看在哪个循环体里面。
六,Array数组
JavaScript 中的数组是用于存储多个值的列表。数组是非常灵活的,可以包含各种类型的数据,并且有许多内置方法来操作数组。本文将介绍 JavaScript 数组的常见操作,包括创建数组、修改数组、遍历数组、排序、过滤、映射等操作。
6.1 创建数组
数组可以通过多种方式创建:
-
空数组:
let arr1 = []; let arr2 = new Array() -
带有初始值的数组:
let fruits = ['apple', 'banana', 'orange']; let arr2 = new Array('apple', 'banana', 'orange') let numbers = [1, 2, 3, 4, 5];
数组中的元素可以是任何数据类型,甚至可以是对象或其他数组。
6.2 访问数组元素
使用索引访问数组元素,索引从 0 开始:
let fruits = ['apple', 'banana', 'orange'];
console.log(fruits[0]); // 输出 'apple'
console.log(fruits[2]); // 输出 'orange'
6.3 修改数组元素
数组的元素是可修改的,可以直接通过索引修改:
let fruits = ['apple', 'banana', 'orange'];
fruits[1] = 'grape';
console.log(fruits); // ['apple', 'grape', 'orange']
6.4 数组长度
可以使用 .length 属性获取数组的长度:
let fruits = ['apple', 'banana', 'orange'];
console.log(fruits.length); // 3
6.5 数组方法
6.5.1 添加元素
-
push():在数组末尾添加元素
let fruits = ['apple', 'banana']; fruits.push('orange'); console.log(fruits); // ['apple', 'banana', 'orange'] -
unshift():在数组开头添加元素
fruits.unshift('grape'); console.log(fruits); // ['grape', 'apple', 'banana', 'orange']
6.5.2 删除元素
-
pop():从数组末尾删除元素
fruits.pop(); console.log(fruits); // ['grape', 'apple', 'banana'] -
shift():从数组开头删除元素
fruits.shift(); console.log(fruits); // ['apple', 'banana']
6.5.3 查找元素
-
indexOf():查找元素的索引
let index = fruits.indexOf('banana'); console.log(index); // 1 -
includes():检查数组是否包含某个元素
let hasApple = fruits.includes('apple'); console.log(hasApple); // true
6.5.4 遍历数组
-
for 循环:最基本的方式
let fruits = ['apple', 'banana', 'orange']; for (let i = 0; i < fruits.length; i++) { console.log(fruits[i]); } -
forEach():数组专用方法
fruits.forEach(function(fruit) { console.log(fruit); });
6.6 数组排序
-
sort():按字母顺序对数组进行排序
let fruits = ['apple', 'banana', 'orange']; fruits.sort(); console.log(fruits); // ['apple', 'banana', 'orange'] -
对数字进行排序时,
sort()会将数字当作字符串处理,需要提供比较函数:let numbers = [40, 1, 5, 200]; numbers.sort((a, b) => a - b); console.log(numbers); // [1, 5, 40, 200]
6.7 数组映射
map():创建一个新数组,其中每个元素是原数组的操作结果:
let numbers = [1, 2, 3, 4];
let doubled = numbers.map(num => num * 2);
console.log(doubled); // [2, 4, 6, 8]
map 可以遍历数组处理数据,并返回新数组
const arr=['red','blue','green']
const newArr=arr.map(function(els,index){
console.log(els)//数组元素
console.log(index)//数组索引
return els+'颜色'
})
console.log(newArr)//['red颜色','blue颜色','green颜色']
6.8 数组过滤
filter():根据条件筛选出符合条件的元素:
let numbers = [1, 2, 3, 4, 5];
let filtered = numbers.filter(num => num > 2);
console.log(filtered); // [3, 4, 5]
6.9 数组合并
concat():合并两个或多个数组:
let arr1 = [1, 2];
let arr2 = [3, 4];
let merged = arr1.concat(arr2);
console.log(merged); // [1, 2, 3, 4]
6.10 数组转字符串
join():将数组元素连接成一个字符串:
let fruits = ['apple', 'banana', 'orange'];
let result = fruits.join(', ');
console.log(result); // 'apple, banana, orange'
6.11 数组拆分和合并
-
splice():从数组中删除、添加或替换元素:
let fruits = ['apple', 'banana', 'orange']; fruits.splice(1, 1); // 从索引 1 开始删除 1 个元素 console.log(fruits); // ['apple', 'orange'] -
slice():截取数组的部分内容,返回一个新数组:
let fruits = ['apple', 'banana', 'orange', 'grape']; let sliced = fruits.slice(1, 3); // 从索引 1 到 3 之间的元素 console.log(sliced); // ['banana', 'orange']
七,函数
JavaScript 的函数是最基础且强大的编程构建块之一。它们是用来执行特定任务的可重用代码块。JavaScript 中的函数不仅可以像普通函数那样调用,还可以作为对象,甚至作为其他函数的参数或返回值。
7.1 函数的定义
7.1.1 声明函数
这是最常见的定义函数的方式。
function greet() {
console.log('Hello, world!');
}
greet(); // 输出:Hello, world!
7.1.2 函数表达式
函数也可以作为表达式的一部分定义,并赋值给变量。
const greet = function() {
console.log('Hello, world!');
};
greet(); // 输出:Hello, world!
7.1.3 箭头函数
ES6 引入了一种更简洁的定义函数的语法,称为箭头函数(Arrow Function)。它特别适合定义短小的匿名函数。
const greet = () => {
console.log('Hello, world!');
};
greet(); // 输出:Hello, world!
箭头函数的简洁之处在于:
- 当只有一个参数时,可以省略括号。
- 当只有一行代码且返回值时,可以省略大括号和
return关键字。
const double = x => x * 2;
console.log(double(5)); // 输出:10
7.2 函数的参数
7.2.1 传递参数
函数可以接收参数,并根据传入的参数执行相应的操作。
function greet(name) {
console.log(`Hello, ${name}!`);
}
greet('Alice'); // 输出:Hello, Alice!
7.2.2 默认参数
可以为函数的参数设置默认值,当没有传递参数时使用该默认值。
function greet(name = 'stranger') {
console.log(`Hello, ${name}!`);
}
greet(); // 输出:Hello, stranger!
greet('Bob'); // 输出:Hello, Bob!
7.2.3 Rest 参数
使用 rest 参数可以将函数的参数收集到一个数组中,方便处理不确定数量的参数。
function sum(...numbers) {
return numbers.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3)); // 输出:6
console.log(sum(4, 5, 6, 7, 8)); // 输出:30
7.3 返回值
函数可以通过 return 关键字返回值,调用函数时可以获取该返回值。
function add(a, b) {
return a + b;
}
const result = add(5, 10);
console.log(result); // 输出:15
如果函数中没有 return 语句,函数默认返回 undefined。
7.4 匿名函数
匿名函数就是没有名字的函数,通常作为回调函数传递。
setTimeout(function() {
console.log('This message appears after 2 seconds');
}, 2000);
7.5 回调函数
回调函数是作为参数传递给其他函数并在稍后执行的函数。
function greetUser(name, callback) {
console.log(`Hello, ${name}!`);
callback();
}
greetUser('Alice', function() {
console.log('Callback executed!');
});
7.6 高阶函数
高阶函数是指接收函数作为参数,或者返回另一个函数的函数。
function createMultiplier(multiplier) {
return function(num) {
return num * multiplier;
};
}
const double = createMultiplier(2);
console.log(double(5)); // 输出:10
const triple = createMultiplier(3);
console.log(triple(5)); // 输出:15
7.7 函数作用域和闭包
7.7.1 作用域
局部作用域:在函数内部定义的变量只能在函数内部访问,称为局部变量。
全局作用域:在函数外部定义的变量可以在代码的任何地方访问,称为全局变量。
let globalVar = 'I am global';
function myFunction() {
let localVar = 'I am local';
console.log(globalVar); // 可以访问全局变量
}
myFunction();
console.log(localVar); // 错误:localVar 未定义
7.7.2 闭包
闭包是指函数内部的函数可以访问外部函数的变量,即使外部函数已经执行完毕。闭包能够“记住”它的词法作用域。
function outer() {
let count = 0;
return function inner() {
count++;
console.log(count);
};
}
const counter = outer();
counter(); // 输出:1
counter(); // 输出:2
7.8 立即执行函数
立即执行函数表达式(Immediately Invoked Function Expression,IIFE)是在定义之后立即执行的函数。常用于创建独立的作用域。
(function(形参) {
console.log('I am an IIFE!');
})(实参);
7.9 this 关键字
this 关键字在函数中指向调用它的对象,箭头函数中的 this 是从外层上下文继承的。
const person = {
name: 'John',
greet: function() {
console.log(`Hello, my name is ${this.name}`);
}
};
person.greet(); // 输出:Hello, my name is John
八,Object对象
JavaScript 中的 Object 对象是用于存储键值对数据的基本构造。它是所有对象的顶级对象,几乎所有的 JavaScript 对象都是从 Object 派生的。Object 提供了许多有用的方法来处理对象,操作键值对,以及继承和原型链相关的功能。
8.1 什么是 Object?
Object 是 JavaScript 中最基础的对象类型,用来存储键值对。键(或属性名)是字符串或 Symbol 类型,而值可以是任何类型的数据,包括其他对象、数组、函数等。
8.2 如何创建对象
创建对象的方法有多种,以下是常见的几种方式:
8.2.1 对象字面量
这是最常用和最简单的方式,用花括号 {} 创建对象,并指定属性。
const person = {
name: 'Alice',
age: 25,
greet: function() {
console.log('Hello, my name is ' + this.name);
}
};
console.log(person.name); // 输出: Alice
person.greet(); // 输出: Hello, my name is Alice
8.2.2 new Object() 构造函数
这是另一种创建对象的方式,但在现代 JavaScript 中,使用这种方法较少,通常更倾向于对象字面量。
const person = new Object();
person.name = 'Alice';
person.age = 25;
person.greet = function() {
console.log('Hello, my name is ' + this.name);
};
8.2.3 Object.create() 方法
Object.create() 允许从一个现有对象作为原型创建一个新对象。
const prototypePerson = {
greet: function() {
console.log('Hello, I am ' + this.name);
}
};
const person = Object.create(prototypePerson);
person.name = 'Bob';
person.greet(); // 输出: Hello, I am Bob
8.3 对象属性的访问与操作
8.3.1 访问属性
-
点语法:通过点(
.)访问对象的属性。console.log(person.name); // 输出: Bob -
方括号语法:通过方括号和字符串访问属性,适用于动态属性名或含特殊字符的属性名。
console.log(person['name']); // 输出: Bob const key = 'name'; console.log(person[key]); // 输出: Bob
8.3.2 修改属性
可以通过直接赋值修改对象的属性。
person.name = 'Charlie';
console.log(person.name); // 输出: Charlie
8.3.3 添加属性
对象是动态的,可以随时添加新属性。
person.gender = 'male';
console.log(person.gender); // 输出: male
8.3.4 删除属性
使用 delete 运算符可以删除对象的属性。
delete person.age;
console.log(person.age); // 输出: undefined
8.3.5 遍历对象
let obj={
uname: 'name',
age: 10,
gender: '男'
}
for(let k in obj){
console.log(k)//输出的是属性名 uname age gender
console.log(obj[k])//输出的是属性值:name 10 男
}
8.4 对象的常用方法
JavaScript 提供了一些非常有用的 Object 对象方法。
8.4.1 Object.keys()
返回一个包含对象所有可枚举属性名的数组。
const keys = Object.keys(person);
console.log(keys); // 输出: ['name', 'gender']
8.4.2 Object.values()
返回一个包含对象所有可枚举属性值的数组
const values = Object.values(person);
console.log(values); // 输出: ['Charlie', 'male']
8.4.3 Object.entries()
返回一个包含对象所有键值对的二维数组,每个键值对是一个数组 [key, value]。
const entries = Object.entries(person);
console.log(entries); // 输出: [['name', 'Charlie'], ['gender', 'male']]
8.4.4 Object.assign()
将一个或多个源对象的所有可枚举属性复制到目标对象中。
const target = { a: 1 };
const source = { b: 2, c: 3 };
Object.assign(target, source);
console.log(target); // 输出: { a: 1, b: 2, c: 3 }
8.4.5 Object.freeze()
冻结对象,防止添加、删除或修改对象的属性。
const frozenObject = Object.freeze({ name: 'Alice' });
frozenObject.name = 'Bob'; // 无效,属性无法修改
console.log(frozenObject.name); // 输出: Alice
8.4.6 Object.seal()
封闭对象,不能添加或删除属性,但可以修改现有属性的值。
const sealedObject = Object.seal({ name: 'Alice' });
sealedObject.name = 'Bob'; // 可以修改
console.log(sealedObject.name); // 输出: Bob
delete sealedObject.name; // 无效,属性无法删除
console.log(sealedObject.name); // 输出: Bob
8.4.7 Object.create()
从指定的原型对象创建一个新的对象。
const animal = {
speak() {
console.log('Animal is speaking');
}
};
const dog = Object.create(animal);
dog.speak(); // 输出: Animal is speaking
8.5 对象的深浅拷贝
-
浅拷贝:只复制对象的引用,改变其中一个对象的属性会影响另一个对象。
const obj1 = { a: 1, b: 2 }; const obj2 = Object.assign({}, obj1); obj2.a = 99; console.log(obj1.a); // 输出: 1(obj2修改不会影响obj1) -
深拷贝:完全复制对象及其嵌套对象,两个对象之间没有任何联系。
const obj1 = { a: 1, b: { c: 2 } }; const obj2 = JSON.parse(JSON.stringify(obj1)); // 使用JSON方法进行深拷贝 obj2.b.c = 99; console.log(obj1.b.c); // 输出: 2(深拷贝后obj1和obj2无关联)
8.6 对象的继承和原型
每个对象都有一个与之关联的原型(prototype)。对象可以继承其原型对象上的属性和方法。
const animal = {
eats: true
};
const dog = Object.create(animal);
dog.barks = true;
console.log(dog.eats); // 输出: true (继承自 animal)
console.log(dog.barks); // 输出: true
九,Map集合
在 ES6(ECMAScript 2015)中,JavaScript 引入了新的集合类型 Map。Map 是一种用于存储键值对的数据结构,类似于对象(Object),但提供了更丰富的功能和更好的性能。下面我们将深入了解 Map 的特性、使用方法以及与其他集合类型的区别。
什么是 Map?
Map是一种 键值对(Key-Value)集合,其中的 键和值可以是任意类型,包括基本类型和引用类型。与对象不同,Map保留了键值对的插入顺序,提供了更高效的键值对操作方法。
9.1 创建 Map
有两种方式可以创建 Map:
-
创建空的 Map
const map = new Map(); -
使用初始化值创建 Map
const map = new Map([ ['name', 'Alice'], ['age', 30], [{ city: 'New York' }, 'Location'], ]);
9.2 Map 的基本方法
9.2.1 set(key, value)
添加或更新键值对。
map.set('name', 'Bob');
map.set(1, 'Number Key');
map.set(true, 'Boolean Key');
9.2.2 get(key)
根据键获取对应的值。如果键不存在,返回 undefined。
console.log(map.get('name')); // 'Bob'
console.log(map.get(1)); // 'Number Key'
console.log(map.get('unknown')); // undefined
9.2.3 has(key)
检查 Map 是否包含指定的键,返回 true 或 false。
console.log(map.has('name')); // true
console.log(map.has('age')); // false
9.2.4 delete(key)
删除指定的键值对,返回一个布尔值表示是否成功删除。
map.delete('name'); // true
console.log(map.has('name')); // false
9.2.5 clear()
清空所有的键值对。
map.clear();
console.log(map.size); // 0
9.2.6 size 属性
返回 Map 中键值对的数量。
console.log(map.size); // 输出当前键值对的数量
9.3 遍历 Map
Map 是可迭代的,支持多种遍历方式。
9.3.1 for...of 迭代
for (const [key, value] of map) {
console.log(`${key}: ${value}`);
}
9.3.2 forEach 方法
map.forEach((value, key) => {
console.log(`${key}: ${value}`);
});
9.3.3 遍历键或值
-
遍历所有的键
for (const key of map.keys()) { console.log(key); } -
遍历所有的值
for (const value of map.values()) { console.log(value); } -
遍历所有的键值对
for (const [key, value] of map.entries()) { console.log(`${key}: ${value}`); }
9.4 Map 与 Object 的区别
-
键的类型
- Map:键可以是任意类型,包括对象、函数、基本类型等。
- Object:键只能是字符串或
Symbol。
-
键的顺序
- Map:按照键值对插入的顺序维护。
- Object:键的顺序不确定,取决于引擎实现。
-
大小(Size)
- Map:使用
size属性获取键值对的数量。 - Object:需要手动计算键的数量,如使用
Object.keys(obj).length。
- Map:使用
-
性能
- Map:在频繁添加、删除键值对的情况下,性能更好。
- Object:性能相对较差,特别是在处理大量键值对时。
-
迭代性
- Map:本身是可迭代的,直接使用
for...of。 - Object:需要使用
Object.keys()、Object.values()或Object.entries()。
- Map:本身是可迭代的,直接使用
9.5 示例:使用对象作为键
const objKey = { id: 1 };
const map = new Map();
map.set(objKey, 'Object Key');
console.log(map.get(objKey)); // 'Object Key'
9.6 常见的 Map 操作示例
9.6.1 合并两个 Map
const map1 = new Map([
['a', 1],
['b', 2],
]);
const map2 = new Map([
['b', 3],
['c', 4],
]);
const mergedMap = new Map([...map1, ...map2]);
console.log(mergedMap);
// Map { 'a' => 1, 'b' => 3, 'c' => 4 }
9.6.2 将 Map 转换为数组
const map = new Map([
['a', 1],
['b', 2],
]);
const keyArray = [...map.keys()]; // ['a', 'b']
const valueArray = [...map.values()]; // [1, 2]
const entryArray = [...map.entries()]; // [['a', 1], ['b', 2]]
9.6.3 将数组转换为 Map
const arr = [
['a', 1],
['b', 2],
];
const map = new Map(arr);
console.log(map);
// Map { 'a' => 1, 'b' => 2 }
9.7 注意事项
-
键的相等性判断:
Map使用 SameValueZero 算法判断键是否相等,类似于===,但NaN被认为等于自身。map.set(NaN, 'Not a Number'); console.log(map.get(NaN)); // 'Not a Number' -
避免混淆类型:由于键可以是任意类型,确保在使用时类型一致,避免不必要的错误。
十,内置函数
JavaScript 提供了许多常用的内置对象,这些对象和类可以帮助开发者在各种场景下处理数据、操作 DOM、进行网络请求等。常用的内置对象包括:
10.1 String
-
String对象用于处理和操作文本数据。字符串是不可变的,且有许多用于字符串操作的方法。常用方法:
length:返回字符串的长度。toUpperCase():将字符串转换为大写。toLowerCase():将字符串转换为小写。slice():提取字符串的子字符串。replace():替换匹配的子字符串。split():将字符串拆分为数组。
示例:
const text = "Hello, World!"; console.log(text.toUpperCase()); // "HELLO, WORLD!"
10.2 Number
-
Number对象用于处理和操作数字,包括整数和浮点数。常用方法和属性:
isNaN():判断值是否为非数字。isFinite():判断值是否为有限数。parseFloat():将字符串转换为浮点数。parseInt():将字符串转换为整数。toFixed():将数字格式化为指定小数位的字符串。
示例:
const num = 123.456; console.log(num.toFixed(2)); // "123.46"
10.3 Math
-
Math是一个包含数学常量和函数的对象。它不作为构造函数使用,所有方法和属性都直接调用。常用方法:
Math.max():返回多个数中的最大值。Math.min():返回多个数中的最小值。Math.round():对数字进行四舍五入。Math.random():返回 0 到 1 之间的随机数。Math.floor():向下取整。
示例:
const randomNum = Math.random() * 10; console.log(Math.floor(randomNum)); // 0 到 9 之间的整数
10.4 Date
-
Date对象用于处理日期和时间。它可以创建、操作和格式化日期及时间。常用方法:
Date.now():返回当前时间的时间戳(自 1970-01-01 起的毫秒数)。getFullYear():返回年份。getMonth():返回月份(0-11)。getDate():返回日期(1-31)。getDay():返回星期几(0-6)。getTime():返回时间戳。
示例:
const now = new Date(); console.log(now.getFullYear()); // 当前年份
10.5 RegExp`(正则表达式)
-
RegExp对象用于定义和处理正则表达式,常用于文本匹配和替换。常用方法:
test():测试字符串是否匹配正则表达式。exec():返回匹配结果数组。match():返回所有匹配的字符串。replace():替换匹配的字符串。
示例:
const pattern = /hello/i; const result = pattern.test("Hello, World!"); console.log(result); // true
10.6 JSON
-
JSON对象用于解析和序列化 JSON 格式的数据(JavaScript Object Notation)。常用方法:
JSON.parse():将 JSON 字符串解析为 JavaScript 对象。JSON.stringify():将 JavaScript 对象序列化为 JSON 字符串。
示例:
const jsonString = '{"name": "Alice", "age": 25}'; const person = JSON.parse(jsonString); console.log(person.name); // 输出: Alice
10.7 Symbol
-
Symbol是一种独特且不可变的数据类型,通常用作对象属性的唯一标识符。示例:
const sym = Symbol('description'); const obj = { [sym]: 'value' }; console.log(obj[sym]); // 输出: value