***1、Es6中的 Set 和 Map 的区别
1. 数据结构定义
Set:Set是一种集合(Collection)数据结构,它允许你存储任何类型的唯一值,无论是原始值还是对象引用。Set中的元素是无序的,且每个值只能出现一次。
Map:Map是一种键值对(Key-Value)的集合,其中的每个元素都是一个键值对。Map的键可以是任意值,包括函数、对象或任何原始类型。Map中的键值对是按插入顺序存储的,可以通过键快速检索值。
2. 存储方式
Set:以“[value, value]”的形式存储元素,即只存储值,不存储键。由于Set中的元素是唯一的,因此自动排除了重复的值。
Map:以“[key, value]”的形式存储元素,每个元素都包含一个键和一个值。Map允许键重复(但实际上,由于键的唯一性,这里指的是不同的键可以对应相同的值),但每个键只能映射到一个值。
3. 访问方式
Set:没有直接通过索引或键访问元素的方法。你可以使用
has()
方法来检查一个值是否存在于Set中,但不能直接通过值来获取它(除非遍历整个Set)。Map:可以通过
get()
方法和键来检索对应的值。这使得Map成为一种非常高效的数据检索结构。4. 主要方法和属性
数据结构 主要方法 主要属性 Set add(value)
:添加元素delete(value)
:删除元素has(value)
:检查是否存在元素clear()
:清空集合keys()
、values()
、entries()
:返回迭代器size
:集合的大小Map set(key, value)
:添加键值对get(key)
:通过键获取值has(key)
:检查是否存在键delete(key)
:删除键值对clear()
:清空Mapkeys()
、values()
、entries()
:返回迭代器size
:Map的大小5. 应用场景
Set:适用于需要存储不重复值的场景,如数组去重、检查值是否存在等。
Map:适用于需要存储键值对并快速检索值的场景,如存储用户信息、配置选项等。
6. 其他注意事项
在Set中,NaN被视为相等的值(即
Set
中只能存储一个NaN),这与===
运算符的行为不同(NaN === NaN
的结果是false
)。Map的键可以是任意值,包括函数、对象或原始类型,这使得Map在处理复杂数据结构时非常灵活。
综上所述,Set和Map在ES6中提供了两种不同的数据结构选择,以满足不同的编程需求。
2、什么是函数科里化
函数科里化(Currying)是一种将使用多个参数的函数转换成一系列使用一个参数的函数的技术。这些单参数函数返回的函数接收下一个参数,以此类推,直到所有参数都被应用,然后返回最终结果。函数科里化是一种重要的函数式编程技术,它有助于实现代码的模块化、重用和组合。
在函数科里化中,原始的接受多个参数的函数 f(a, b, c) 会被转换成接受一个参数的函数 g(a),它返回另一个函数 h(b),这个函数 h 又返回另一个函数 i(c),最终 i(c) 返回 f 的结果。因此,科里化后的函数可以表示为 g(a)(b)(c)。
function sum(a,b,c) { // 也可以写业务,但都归sum调用执行 return a + b + c; } sum(1,2,3); // 科里化: function sum(a) { return function(b) { // 可以写业务,调用才会执行 return function(c) { return a + b + c; } } } sum(1)(2)(3);
3、valueOf()、toString() 和 String()区别
valueOf()
和toString()
是 JavaScript 中 Object 原型上的两个方法,它们都被广泛用于类型转换和数据展示,但它们的用途和行为存在显著的区别。
1.
valueOf()
目的:
valueOf()
方法通常被 JavaScript 引擎内部调用,用于将对象转换为原始值。它主要用于类型转换的场景。返回值:返回对象的原始值。不同类型的对象会返回不同的原始值。
Date
对象会返回时间戳(毫秒数)Number
对象会返回其表示的数字String
对象会返回其字符串值,等等。- 如果对象没有原始值表示,则通常会返回对象本身。
用途:在需要对象原始值的情况下,比如使用
==
运算符比较对象与原始值时,JavaScript 引擎可能会尝试调用valueOf()
方法。然而,需要注意的是,==
运算符的行为可能很复杂,因为它还会尝试调用toString()
方法进行转换。
2.
toString()
目的:
toString()
方法被用来获取对象的字符串表示。这主要用于调试或日志记录,以及需要将对象以字符串形式展示给用户时。返回值:返回一个表示该对象的字符串。默认情况下,对于大多数对象,
toString()
方法会返回一个类似[object Type]
的字符串,其中Type
是对象的类型。但是,许多内置对象和自定义对象都可以重写这个方法以返回更具体的字符串表示。用途:
toString()
方法被广泛用于需要将对象转换为字符串的场景,比如使用+
运算符连接字符串和对象时,JavaScript 会自动调用对象的toString()
方法(如果对象是null
或undefined会报错
)。
3. String()
- 目的:不确定一个值是不是 null 或 undefined,可以使用 String()转型函数,
- 返回值:它始终会返回表示相应类型值的字符串。
String()函数遵循如下规则:
- 如果值有 toString()方法,则调用该方法(不传参数)并返回结果。
- 如果值是 null,返回"null"。
- 如果值是 undefined,返回"undefined"。
4、优化俩个for循环代码
let a = [ { id: 1, name: 'a' }, { id: 2, name: 'b' }, ]; let b = [ { id: 1, name: 'a' }, { id: 2, name: 'b' }, ]; a.forEach((item,index) => { b.forEach((item2,index2) => { if(item.id === item2.id && item.name === item2.name) { item.abc = true; } }) });
我们可以遍历
a
数组,并检查这个临时对象中是否存在对应的键。// 创建一个Map来存储b数组中元素的id和name组合 const bMap = new Map(); // 遍历b数组,将元素添加到Map中 b.forEach(item2 => { const key = `${item2.id}-${item2.name}`; // 创建一个复合键 bMap.set(key, true); // 值可以是任何,因为我们只关心键是否存在 }); // 遍历a数组,检查Map中是否存在对应的键 a.forEach(item => { const key = `${item.id}-${item.name}`; // 同样的复合键 if (bMap.has(key)) { item.abc = true; } });