前端面试题---深拷贝、浅拷贝的实现和解构赋值

这篇具有很好参考价值的文章主要介绍了前端面试题---深拷贝、浅拷贝的实现和解构赋值。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一.如何在 JavaScript 中实现深拷贝和浅拷贝?

在 JavaScript 中实现深拷贝和浅拷贝可以采用不同的方法。下面分别介绍这两种拷贝方式的实现方式

1.浅拷贝(Shallow Copy)

浅拷贝(shallow copy)是一种复制对象或数组的操作,创建一个新的对象或数组,并将原始对象或数组的属性或元素的引用复制到新的对象或数组中。这意味着原始对象和拷贝对象会共享相同的引用类型数据,而不是创建新的引用类型数据。

浅拷贝只复制对象或数组的一层属性或元素,而不会递归地复制嵌套的对象或数组。当修改拷贝对象的属性或元素时,原始对象的对应属性或元素也会受到影响。因此,浅拷贝适用于简单的数据结构,但不适用于复杂的嵌套结构。

下面介绍几种常见的浅拷贝方法:

扩展运算符(Spread Operator)使用扩展运算符可以快速进行浅拷贝,将原始对象的属性或数组的元素展开到新的对象或数组中。

const originalObject = { name: 'John', age: 30 };
const shallowCopy = { ...originalObject };
//output:{ name: 'John', age: 30 }

const originalArray = [1, 2, 3];
const shallowCopy = [...originalArray];
//output:[1, 2, 3]

 Object.assign() 方法 使用 Object.assign() 方法可以将原始对象的属性复制到新的对象中。

const originalObject = { name: 'John', age: 30 };
const shallowCopy = Object.assign({}, originalObject);

const originalArray = [1, 2, 3];
const shallowCopy = Object.assign([], originalArray);

 Array.prototype.slice() 方法  对于数组,可以使用 slice() 方法来创建一个新的数组,并将原始数组的元素复制到新的数组中。

const originalArray = [1, 2, 3];
const shallowCopy = originalArray.slice();

2.深拷贝(Deep Copy)

深拷贝(deep copy)是一种复制对象或数组的操作,创建一个全新的对象或数组,并递归地复制原始对象或数组的所有属性或元素,包括嵌套的对象或数组。深拷贝创建的副本是完全独立的,对副本的修改不会影响原始对象或数组。

深拷贝适用于复杂的数据结构,包括嵌套的对象或数组。当需要对数据进行修改、操作或传递给其他函数时,深拷贝可以确保原始数据的完整性和不变性。

 下面介绍几种常见的深拷贝方法:

 递归复制

通过递归遍历对象或数组,并复制所有的属性或元素,可以实现深拷贝。

function deepCopy(obj) {
  if (typeof obj !== 'object' || obj === null) {
    return obj; // 非对象类型直接返回
  }
  
  const copy = Array.isArray(obj) ? [] : {};
  
  for (let key in obj) {
    if (Object.hasOwnProperty.call(obj, key)) {
      copy[key] = deepCopy(obj[key]);
    }
  }
  
  return copy;
}

const originalObject = { name: 'John', age: 30 };
const deepCopyObject = deepCopy(originalObject);

const originalArray = [1, 2, { nested: true }];
const deepCopyArray = deepCopy(originalArray);

JSON 序列化与反序列化

可以使用 JSON 对象的 stringify() 方法将原始对象或数组转换为 JSON 字符串,再使用 parse() 方法将 JSON 字符串转换为新的对象或数组。这种方法可以实现简单的深拷贝,但有一些限制,例如无法复制函数、正则表达式和特殊的对象类型。

const originalObject = { name: 'John', age: 30 };
const deepCopyObject = JSON.parse(JSON.stringify(originalObject));

const originalArray = [1, 2, { nested: true }];
const deepCopyArray = JSON.parse(JSON.stringify(originalArray));

需要注意的是,使用 JSON 序列化与反序列化的方式进行深拷贝时,原始对象或数组中的函数、正则表达式、特殊对象类型等会被忽略或转换为字符串,丢失原始的数据类型和行为。

无论使用哪种深拷贝方法,都要注意以下几点:

  • 循环引用:如果原始对象或数组存在循环引用(即某个属性或元素引用了对象或数组本身),在深拷贝过程中可能导致无限递归,需要额外的处理来解决循环引用问题。
  • 性能考虑:深拷贝可能涉及递归遍历大量的数据,对于大型对象或数组,深拷贝的性能可能较低。在处理大型数据时,可以考虑使用其他优化的深拷贝库或算法,如 Lodash cloneDeep() 方法。
const originalObject = { name: 'John', age: 30 };
const deepCopyObject = _.cloneDeep(originalObject);

const originalArray = [1, 2, { nested: true }];
const deepCopyArray = _.cloneDeep(originalArray);

二.数据解构

解构赋值(destructuring assignment)是一种通过解构语法将数组或对象的属性值赋给变量的方式。它在 JavaScript 中引入了一种简洁而强大的方式来从复杂的数据结构中提取值。

解构赋值可以应用于数组和对象,并且支持多种用法和语法。下面详细介绍解构赋值的各种用法

 数组解构赋值

通过数组解构赋值,可以将数组的元素值分别赋给对应的变量。

const [a, b, c] = [1, 2, 3];
console.log(a); // 输出 1
console.log(b); // 输出 2
console.log(c); // 输出 3

可以省略数组中的某些元素,只提取需要的部分。

const [a, , c] = [1, 2, 3];
console.log(a); // 输出 1
console.log(c); // 输出 3

还可以使用默认值来处理在解构过程中未定义的值。

const [a, b, c = 0] = [1, 2];
console.log(a); // 输出 1
console.log(b); // 输出 2
console.log(c); // 输出 0(使用默认值)

对象解构赋值

通过对象解构赋值,可以从对象中提取属性值并赋给对应的变量。

const { name, age } = { name: 'John', age: 30 };
console.log(name); // 输出 'John'
console.log(age); // 输出 30

可以使用别名来为提取的属性值指定新的变量名。

const { name: personName, age: personAge } = { name: 'John', age: 30 };
console.log(personName); // 输出 'John'
console.log(personAge); // 输出 30

也可以使用默认值处理在解构过程中未定义的属性值。

const { name, age = 0 } = { name: 'John' };
console.log(name); // 输出 'John'
console.log(age); // 输出 0(使用默认值)

函数参数的解构赋值

可以在函数参数中使用解构赋值,从传入的对象或数组中提取所需的值。

function greet({ name, age }) {
  console.log(`Hello, ${name}! You are ${age} years old.`);
}

const person = { name: 'John', age: 30 };
greet(person); // 输出 'Hello, John! You are 30 years old.'

其他高级用法

剩余运算符(Rest Operator):可以使用剩余运算符 ... 将剩余的数组元素或对象属性提取为一个新的数组或对象。

const [a, ...rest] = [1, 2, 3, 4, 5];
console.log(a); // 输出 1
console.log(rest); // 输出 [2, 3, 4, 5]

const { name, ...rest } = { name: 'John', age: 30, city: 'New York' };
console.log(name); // 输出 'John'
console.log(rest); // 输出 { age: 30, city: 'New York' }

嵌套解构赋值:可以在数组和对象的解构赋值中进行嵌套,以提取多层嵌套的值。

function greet({ name, details: { age } }) {
  console.log(`Hello, ${name}! You are ${age} years old.`);
}

const person = { name: 'John', details: { age: 30 } };
greet(person); // 输出 'Hello, John! You are 30 years old.'

解构赋值的嵌套用法可以在函数参数中灵活应用,以提取更复杂的数据结构。文章来源地址https://www.toymoban.com/news/detail-479400.html

function greet({ name, details: { age } }) {
  console.log(`Hello, ${name}! You are ${age} years old.`);
}

const person = { name: 'John', details: { age: 30 } };
greet(person); // 输出 'Hello, John! You are 30 years old.'

到了这里,关于前端面试题---深拷贝、浅拷贝的实现和解构赋值的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【ES6】—解构赋值

    解构赋值:解构赋值就是一种模式的匹配,只要等号两边的模式完全相同的,那么左边的变量就会被赋值对应右边的值 PS:数组解构赋值时,是通过索引的唯一性赋值的 (1). ES5 的写法 (2). ES6 的写法 ES6的写法 当左右两边的结构模式不匹配时,按照左边变量对应索引的位置赋值

    2024年02月12日
    浏览(39)
  • js中的解构赋值

    在JavaScript中,解构赋值是一种方便地从数组或对象中提取值并赋给变量的方法。 它允许你使用一种简洁的语法来快速访问和使用数据。 对于数组解构赋值,你可以使用方括号([])来指定变量名,并将其放在赋值语句的左侧。例如,假设有一个数组: 对于对象解构赋值,你

    2024年02月11日
    浏览(30)
  • JavaScript:解构赋值【数组】

    在JavaScript编程中,解构赋值是一项强大的技术,它能够让我们从数组中迅速提取数据并将其赋值给变量。本文将详细介绍数组解构赋值,以通俗易懂的方式帮助你掌握这一实用技巧。 1. 什么是解构赋值? 解构赋值是一种从复杂数据结构(如数组、对象等)中提取数据并赋值

    2024年02月13日
    浏览(37)
  • JS 解构赋值

    ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,被称为解构赋值。这种写法属于“模式匹配”。这种方式的出现大大提高了代码的扩展性。 从数组中提取值,按照对应位置,对变量赋值。匹配采用模式匹配,匹配的到就获取值,匹配不到就是 undefined。 我们

    2024年02月06日
    浏览(36)
  • JavaScript解构赋值常用操作

    所谓数组解构,就是获取数组中一部分有用的数据,例子: 数组解构还可以和 split 函数配合使用,优雅又高端: 解构也可以叫做“解构赋值”,其本质就是把数组的元素复制给变量,所以原数组没有发生任何的变化 在使用解构赋值的时候,希望得到数组的第 1 、 3 个元素,

    2024年02月16日
    浏览(31)
  • [ES6]解构与赋值

    解构赋值是对赋值运算符的扩展。 通过解构,可以更加简单的获取复杂对象的属性 解构的源,解构赋值表达式的右边部分 解构的目标,解构赋值表达式的左边部分 当变量名称与对象中的属性名称一致时,可简写 {attr} 使用解构方式获取对象参数中的对应属性,这样在函数内部

    2023年04月22日
    浏览(44)
  • ES实用的深度解构赋值方法

    ES6 中允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。 使用解构赋值可以将复杂的代码整理的更加干净整洁。 在没有使用解构之前,想要确定对象中的某些属性,那么就需要从对象中获取属性然后赋值给变量,这样会让代码显得非

    2024年02月03日
    浏览(40)
  • let、const、var的区别,解构赋值,箭头函数

    使用var声明的变量,其作用域为该语句所在的函数内,且存在变量提升现象。 使用let声明的变量,其作用域为该语句所在的代码块内,不存在变量提升。 使用const声明的是常量,在后面出现的代码块中,不能在修改改常量的值。 var let const 函数级作用域 块级作用域 块级作用域 变量提

    2024年02月05日
    浏览(54)
  • 【C++】:拷贝构造函数与赋值运算符重载的实例应用之日期类的实现

    🔑日期类的实现,将按以下声明依次进行,其中因为Print函数比较短,直接放到类里面让其变成内联函数 🔑而我们实现日期类经常要用到某月有多少天,在这里先把获得某月有多少天的函数实现出来。实现时先检查传参有没有问题,在注意把数组设置成静态的,出了作用域

    2024年02月08日
    浏览(66)
  • ES6之 变量的解构赋值 ➕ 扩展运算符(…)

    一看就懂,代码如下: 效果如下: 如下: 如下: 什么是扩展运算符(…运算符)? 就是展开语法 (Spread syntax), 可以在函数调用/数组构造时,将数组表达式或者 string 在语法层面展开;还可以在构造字面量对象时,将对象表达式按 key-value 的方式展开。(译者注: 字面量一般指

    2024年02月09日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包