JS场景应用

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 错误,当访问一个可能为 nullundefined 的对象的属性时,使用 ?. 可以简化判断逻辑。如果链中的某个环节为 nullundefined,表达式会直接返回 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 开始)

    arduino 复制代码
    const 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 开始)

    rust 复制代码
    const 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(无法检测)
相关推荐
isyangli_blog5 小时前
(3-1) Html
前端·html
Yan-英杰5 小时前
Amazon SES + NestJS 实战:零成本打造高送达率邮箱验证方案
java·服务器·前端·网络·数据库·ai
weixin_456904275 小时前
Vue电商数据分析大屏开发
前端·vue.js·数据分析
玖笙&6 小时前
✨Vue 静态路由详解:构建应用的导航骨架(4)
前端·javascript·vue.js
这是个栗子6 小时前
(二)Vue.js 指令、事件与计算属性
前端·javascript·vue
黑客飓风6 小时前
Chrome性能优化指南
前端·chrome·性能优化
pc大老6 小时前
如何修复 Google Chrome 上的白屏问题
前端·网络·chrome·浏览器·谷歌
xqlily6 小时前
Chrome性能优化指南大纲
前端·chrome·性能优化
FreeBuf_6 小时前
Chrome高危类型混淆0-Day漏洞(CVE-2025-10585)技术分析
前端·chrome