1.JSON.parse
作用:将 JSON 格式的字符串转换为对应的 JavaScript 对象或值。
场景:后端接口会传入一大串字符串,前端需要将这些数据渲染到页面上,就要进行转换。
如:
scss
// JSON 格式的字符串
const jsonString = '{"name":"张三","age":25,"hobbies":["读书","运动"]}';
// 接收一个符合 JSON 格式的字符串作为参数,将其转换为 JavaScript 中的对应数据类型(对象、数组、字符串、数字、布尔值或 null)
const obj = JSON.parse(jsonString);
console.log(obj.name); // 输出: "张三"
console.log(obj.age); // 输出: 25
console.log(obj.hobbies[0]); // 输出: "读书"
如果传入的字符串不符合 JSON 格式规范,会抛出 SyntaxError
异常。
javascript
const jsonString = '{"name":"张三", age:25}'; // 这里 age 没有用双引号
try {
// 解析 JSON 字符串
const obj = JSON.parse(jsonString);
} catch (error) {
// 捕获并处理异常
if (error instanceof SyntaxError) {
console.error('JSON 格式错误:', error.message);
} else {
// 处理其他可能的异常
console.error('发生未知错误:', error);
}
}
用户友好方式:
javascript
function safeParseJson(jsonString, defaultValue = {}) {
try {
return jsonString ? JSON.parse(jsonString) : defaultValue;
} catch (error) {
// 捕获并处理异常
if (error instanceof SyntaxError) {
console.error('JSON 格式错误:', error.message);
} else {
// 处理其他可能的异常
console.error('发生未知错误:', error);
}
return defaultValue; // 解析失败时返回默认值
}
}
// 使用示例
const data = safeParseJson('获取到的数据', { name: '未知用户' });
JSON.parse()
是 JavaScript 中将 JSON 字符串 "还原" 为可操作的数据结构的关键方法,是前后端数据交互和数据存储时的常用工具。
在实际开发中,接口返回的 JSON 数据可能是对象({}
)或数组([]
),因此解析后通常需要用 Array.isArray()
判断是否为数组,再进行对应处理。
场景:JSON必须是数组格式,但是后端传入的字符串解析后的json不是数组格式。
- JSON 格式 是一个总称,包含了对象、数组、基础类型三种表现形式。
- JSON 数组格式 是 JSON 格式的子集,仅指用
[]
包裹的有序数据列表。
判断是否是数组,不是数组自动加入[].进行格式化显示。将数组数据带有[]展示出来。
typescript
let jsonData
try {
//解析成json
jsonData = JSON.parse(inputValue)
// 检查是否为数组
if (!Array.isArray(jsonData)) {
return new Promise((resolve) => {
ElMessageBox.confirm(
'输入的JSON必须是数组格式(节点集合),是否进行格式转换?',
'格式错误',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'error'
}
).then(() => {
// 用数组包裹对象并格式化显示
textareaValue.value = JSON.stringify([jsonData], null, 2)
resolve(true);
}).catch(() => {
console.log('用户取消格式转换')
resolve(false)
})
})
}
return true
} catch (e) {
const errorMsg = e instanceof Error ? e.message : String(e)
ElMessage.error(`输入内容不是合法的JSON格式!\n错误原因:${errorMsg}`)
return false
}
2.JSON.stringify()
将 JavaScript 值转换为 JSON 字符串的内置方法,对象放入一个数组中,然后转换为格式化的 JSON 字符串,最终结果会是一个包含原对象的 JSON 数组字符串。
javascript
// 第一个参数 `[jsonData]`:要转换的 JavaScript 值(这里将 `jsonData` 包装在数组中)
// replacer 参数,为 `null` 表示转换所有可序列化的属性
// 第三个参数 `2`: space 参数,表示使用 2 个空格进行缩进,使输出的 JSON 字符串更易读
JSON.stringify([jsonData], null, 2)
jsonData是{name: "John", age: 30}
[
{
"name": "John",
"age": 30
}
]
将非数组值转为数组格式如果原始数据不是数组,但你希望输出为 JSON 数组(包裹在 []
中),可以手动将其放入数组,这种写法会强制将结果包裹在数组中,即使原数据不是数组类型。
javascript
const data = { id: 1, name: "Alice" };
// 手动包裹为数组
const jsonArray = JSON.stringify([data], null, 2);
console.log(jsonArray);
// 输出:
// [
// {
// "id": 1,
// "name": "Alice"
// }
// ]
css
JSON.stringify(value[, replacer[, space]])
参数说明
value(必需):要转换为 JSON 字符串的值(可以是对象、数组、字符串、数字、布尔值或 null)
replacer(可选):
diff
- 若为函数:对每个键值对进行处理,返回值将被序列化
- 若为数组:仅包含数组中列出的属性才会被序列化
- 若为 null 或未提供:所有可序列化的属性都会被包含
space(可选):
diff
- 用于格式化输出的缩进空格数(1-10 之间的数字)
- 若为字符串:将用该字符串作为缩进(最多前 10 个字符)
- 若为 0、null 或未提供:输出将没有缩进和空格
javascript
// 带格式化
console.log(JSON.stringify(obj, null, 2));
// 输出格式化的JSON:
// {
// "name": "Alice",
// "age": 25,
// "isStudent": false
// }
javascript
// 使用replacer函数过滤属性
console.log(JSON.stringify(obj, (key, value) => {
return key === "age" ? undefined : value; // 排除age属性
}));
{"name":"Alice","isStudent":false}
javascript
const numbers = [1, 2, 3, 4, 5];
// 只保留偶数
const evenNumbersJson = JSON.stringify(numbers, (key, value) => {
// 注意:数组的索引会作为key,元素值作为value
return typeof value === 'number' && value % 2 === 0 ? value : undefined;
}, 2);
console.log(evenNumbersJson);
// 输出: [null, 2, null, 4, null]
// 注意:数组空位会被转为null
3.extends 继承
extends
关键字用于实现类的继承,是 ES6(ECMAScript 2015)引入的面向对象编程特性,用于创建一个子类并继承父类的属性和方法。
scala
class 子类名 extends 父类名 {
// 子类的构造函数和方法
}
1.子类会自动获得父类中定义的所有非私有属性和方法(ES6 中通过 #
定义私有成员,子类无法直接访问)。
2.子类可以在父类基础上添加新的属性和方法,或重写(覆盖)父类的方法
3.JavaScript 不支持多继承,一个子类只能直接继承一个父类,但可以通过其他方式(如混入 mixin
)实现类似多继承的效果。
scala
// 继承关系: A是子类(派生类),B是父类(基类)。A会自动获得B中定义的属性和方法(除了私有成员)。
// 代码复用:通过继承,A不需要重新实现 B 中已有的功能,可以直接使用或根据需要进行重写。
// 扩展功能: A可以在B的基础上添加新的属性和方法,实现特定于自身的功能。
class A extends B
// 父类
class B {
constructor(name) {
this.name = name;
}
// 父类的方法
speak() {
console.log(`${this.name} 发出声音`);
}
}
// 子类继承父类
class A extends B {
// 重写父类的方法
speak() {
console.log(`${this.name} 汪汪叫`);
}
// 子类新增的方法
fetch() {
console.log(`${this.name} 叼来了球`);
}
}
// 使用子类
const a = new A("旺财");
a.speak(); // 输出:"旺财 汪汪叫"(调用重写后的方法)
a.fetch(); // 输出:"旺财 叼来了球"(调用子类新增方法)
super关键字:在子类的构造函数中,必须先调用 super()才能使用 this,super()用于调用父类的构造函数。
scala
class A extends B {
constructor(name, color) {
super(name); // 调用父类构造函数
this.color = color; // 子类新增属性
}
}
4.constructor构造函数
constructor
是类被实例化(使用 new
关键字创建对象)时自动调用的方法,用于初始化实例的属性和执行初始化逻辑。
javascript
class Person {
// 构造函数
constructor(name, age) {
// 初始化实例属性
this.name = name;
this.age = age;
}
// 类的其他方法
sayHello() {
console.log(`Hello, I'm ${this.name}`);
}
}
// 创建实例时会自动调用 constructor
const person = new Person("Alice", 30);
person.sayHello(); // 输出: Hello, I'm Alice
arduino
const instance = new AssignmentNode(someNodes);
// 当通过 `new AssignmentNode(...)` 创建实例时,此时会自动调用上面的 constructor 方法
super(...)
用于调用父类的构造函数,将参数传递给父类。访问和调用父类(超类)的方法,主要在继承场景中使用。
在子类的 constructor
中,super()
用于调用父类的构造函数:
javascript
//父类
class Animal {
constructor(name) {
this.name = name;
}
eat() {
console.log(`${this.name} is eating`);
}
}
//子类 基础父类 Animal
class Dog extends Animal {
//new 时 接收传入值,constructor 会被自动调用。
constructor(name, breed) {
// 必须先调用 super() 才能使用 this
super(name); // 调用父类的 constructor
this.breed = breed; // 子类自己的属性
}
bark() {
console.log(`${this.name} is barking`);
}
}
const dog = new Dog("Buddy", "Golden Retriever");
dog.eat(); // 输出: Buddy is eating
dog.bark(); // 输出: Buddy is barking
scala
class Cat extends Animal {
constructor(name) {
super(name);
}
eat() {
// 调用父类的 eat 方法
super.eat();
console.log("Cats like fish");
}
}
const cat = new Cat("Whiskers");
cat.eat();
// 输出:
// Whiskers is eating
// Cats like fish
5.?.
被称为可选链操作符
作用是安全地访问嵌套对象的属性或方法 ,避免因中间某个属性不存在而导致的 TypeError
错误,当访问一个可能为 null
或 undefined
的对象的属性时,使用 ?.
可以简化判断逻辑。如果链中的某个环节为 null
或 undefined
,表达式会直接返回 undefined
,而不会抛出错误。
?.
不能用于赋值操作,例如 user?.name = "Bob"
会报错。
ini
const user = {
name: "Alice",
address: {
city: "Beijing"
}
};
要访问 `user.address.city`,需要先判断 `user` 和 `address` 是否存在:
const city = user && user.address && user.address.city;
可选链
const city = user?.address?.city;
const user = { name: "Alice" };
const city = user?.address?.city; // undefined(不会报错)
const arr = null;
const first = arr?.[0]; // undefined
const obj = {
func: () => "Hello"
};
const result = obj.func?.(); // "Hello"
const obj2 = {};
const result2 = obj2.func?.(); // undefined(不会报错)
6.对象解构
用于从对象或数组中提取属性 / 元素并赋值给变量。它能大幅简化代码,尤其适合处理复杂数据结构。
ini
const user = {
name: "张三",
age: 25,
gender: "男"
};
// 解构赋值
const { name, age, gender } = user;
console.log(name); // "张三"
console.log(age); // 25
console.log(gender); // "男"
等价于传统写法:
const name = user.name;
const age = user.age;
const gender = user.gender;
const { a, d, c } = table[index]
等价于更繁琐的写法:
const a = table[index].a;
const d = table[index].d;
const c = table[index].c;
想使用属性名作为变量名,可以用 新变量名: 原属性名
arduino
const user = { name: "李四", age: 30 };
// 将 name 重命名为 userName,age 重命名为 userAge
const { name: userName, age: userAge } = user;
console.log(userName); // "李四"
console.log(userAge); // 30
设置默认值
ini
const user = { name: "王五" };
// age 不存在时,默认值为 18
const { name, age = 18 } = user;
console.log(age); // 18(因为 user.age 未定义)
解构嵌套对象
arduino
const user = {
name: "赵六",
info: {
height: 180,
weight: 70,
address: { city: "北京" }
}
};
// 解构嵌套属性
const {
name,
info: {
height,
address: { city }
}
} = user;
console.log(name); // "赵六"
console.log(height); // 180
console.log(city); // "北京"
解构函数参数
javascript
// 传统写法
function V(user) {
console.log(user.name, user.age);
}
// 解构写法(更简洁)
function V({ name, age }) {
console.log(name, age);
}
V({ name: "常常", age: 1 }); // 输出:常常 1
可结合默认值使用(防止参数未传递时报错)
javascript
// 参数默认值 + 解构默认值
function printUser({ name = "匿名", age = 0 } = {}) {
console.log(name, age);
}
printUser(); // 输出:匿名 0(未传参时使用默认值)
数组解构
scss
const [a, b, c] = [10, 20, 30];
console.log(a); // 10
console.log(b); // 20
// 跳过元素
const [x, , y] = [1, 2, 3];
console.log(x); // 1
console.log(y); // 3
// 剩余元素(...)
const [first, ...rest] = [1, 2, 3, 4];
console.log(rest); // [2, 3, 4]
7.includes()
适合用于简单的包含关系检测
数组中的 includes()
用法
array.includes(searchElement[, fromIndex])
-
searchElement
:必需,要查找的元素 -
fromIndex
:可选,开始查找的索引位置(默认从 0 开始)arduinoconst fruits = ['apple', 'banana', 'orange']; // 检测是否包含 'banana' console.log(fruits.includes('banana')); // true // 检测是否包含 'grape' console.log(fruits.includes('grape')); // false // 从索引 2 开始查找 'orange' console.log(fruits.includes('orange', 2)); // true // 从索引 3 开始查找(超出数组长度,返回 false) console.log(fruits.includes('apple', 3)); // false
字符串中的 includes()
用法
string.includes(searchString[, position])
-
searchString
:必需,要查找的子字符串 -
position
:可选,开始查找的位置(默认从 0 开始)rustconst str = 'Hello, world!'; // 检测是否包含 'world' console.log(str.includes('world')); // true // 检测是否包含 'foo' console.log(str.includes('foo')); // false // 从索引 7 开始查找 'world' console.log(str.includes('world', 7)); // true // 从索引 8 开始查找 console.log(str.includes('world', 8)); // false
区分大小写
less
['Apple', 'banana'].includes('apple'); // false(大小写不同)
对于引用类型的值(如对象),includes()
检测的是内存地址是否相同
ini
const obj = { name: 'test' };
const arr = [obj];
console.log(arr.includes(obj)); // true
console.log(arr.includes({ name: 'test' })); // false(新对象,内存地址不同)
检测 NaN
(与 indexOf()
不同,indexOf()
无法检测 NaN
)
arduino
const nums = [1, 2, NaN, 4];
console.log(nums.includes(NaN)); // true
console.log(nums.indexOf(NaN)); // -1(无法检测)