JavaScript常见问题

发布于 2024-06-16  156 次阅读


Map和Set的区别,Map和Object的区别

一、Map和Set的区别

一、Set集合

a.简述

1.Set 和 Map 主要的应用场景在于 数据重组 和 数据储存。

2.Set 是一种叫做集合的数据结构,Map 是一种叫做字典的数据结构。

b.集合 与 字典 的区别:

1.共同点:集合、字典 可以储存不重复的值

2.不同点:集合 是以 [value, value]的形式储存元素,字典 是以 [key, value] 的形式储存

3.集合(Set) 新的数据结构,类似于数组,成员唯一(内部元素没有重复的值)。且使用键对数据排序即顺序存储。

c.操作方法

1.add(value):新增,相当于 array里的push。

2.delete(value):存在即删除集合中value。

3.has(value):判断集合中是否存在 value。

4.clear():清空集合。

d.遍历方法(遍历顺序为插入顺序)

1.keys():返回一个包含集合中所有键的迭代器。

2.values():返回一个包含集合中所有值得迭代器。

3.entries():返回一个包含Set对象中所有元素得键值对迭代器

4.forEach(callbackFn, thisArg):用于对集合成员执行callbackFn操作,如果提供了 thisArg 参数,回调中的this会是这个参数,没有返回值。

二、字典(Map)

a.简述

1.是一组键值对的结构,具有极快的查找速度。

b.操作方法

1.set(key, value):向字典中添加新元素。

2.get(key):通过键查找特定的数值并返回。

3.has(key):判断字典中是否存在键key。

4.delete(key):通过键 key 从字典中移除对应的数据。

5.clear():将这个字典中的所有元素删除。

c.遍历方法:

1.Keys():将字典中包含的所有键名以迭代器形式返回。

2.values():将字典中包含的所有数值以迭代器形式返回。

3.entries():返回所有成员的迭代器。

4.forEach():遍历字典的所有成员。

三、 总结

Set

1.成员唯一、有序且不重复。

2.[value, value],键值与键名是一致的(或者说只有键值,没有键名)。

3.可以遍历,方法有:add、delete、has。

Map:

1.本质上是键值对的集合,类似集合。

2.可以遍历,方法很多可以跟各种数据格式转换。

二、Map和Object的区别

一.Map和Object 的区别

a.不同点

1.在 Object 中, key 必须是简单数据类型(整数,字符串或者是 symbol),而在 Map 中则可以是JavaScript 支持的所有数据类型,也就是说可以用一个 Object 来当做一个Map元素的 key。

2.Map 元素的顺序遵循插入的顺序,而 Object 的则没有这一特性。

3.Map 继承自 Object 对象。

b.Object 支持以下几种方法来创建新的实例:

const obj = {}

const obj = new Object()

const obj = Object.create(null)

c.Map 仅支持下面这一种构建方法:

const map = new Map([[1, 2], [2, 3]]); // map = {1 => 2, 2 => 3}

d.数据访问

Map

1.map.get(1); // 2访问元素

2.map.has(1); 判断某个元素是否在 Map 中可以使用

3.map.set(key, value); 新增一个数据

4.map.delete(1); 删除指定数据

5.map.clear(); 全部删除

Object 可以通过 . 和 [ ] 来访问

// 获取数据

obj.id;obj['id'];

// 新增/修改数据

obj['key'] = value;

obj.key = value;

// 删除数据delete obj.id;

Object 可以使用 Object.prototype.hasOwnProperty()

来判断某个key是否是这个对象本身的属性,从原型链继承的属性不包括在内。

f.获取sizeMap 自身有 size 属性,可以自己维持 size 的变化。

Object 则需要借助 Object.keys() 来计算

console.log(Object.keys(obj).length);

g.IteratingMap 自身支持迭代,Object 不支持。

如何确定一个类型是不是支持迭代呢? 可以使用以下方法:

console.log(typeof obj[Symbol.iterator]); // undefined

console.log(typeof map[Symbol.iterator]); // function。

二.总结:

何时使用 Map ,何时使用 Object?

1.虽然Map 在很多时候优于 Object,但是作为 JavaScript 最基础的数据类型,还是有很多情景更适合使用 Object。

2.当所要存储的是简单数据类型,并且 key 都为字符串或者整数或者 Symbol 的时候,优先使用 Object ,因为Object可以使用 字符变量 的方式创建,更加高效。

3.JSON 直接支持 Object,但不支持 Map

4.Map 是纯粹的 hash, 而 Object 还存在一些其他内在逻辑,所以在执行 delete 的时候会有性能问题。所以写入删除密集的情况应该使用 Map。

5.Map 会按照插入顺序保持元素的顺序,而Object做不到。

6.Map 在存储大量元素的时候性能表现更好,特别是在代码执行时不能确定 key 的类型的情况

数组的filter,every,flat的作用?

filter(): 创建一个新数组,新数组中的元素是由过滤指定数组中符合某条件的元素组成。

every(): 用于检测目标数组中的所有元素是否满足某项条件,如果都满足则返回true,只要有一个不满足,则返回false;

flat(): 返回一个新数组,新数据中的元素是将目标数组(多层数组)拉低一层,flat可以传参数,表示拉低几层,默认参数为1;

es6有哪些新特性

  1. 默认参数;
  2. 字符串模板;
  3. 解构赋值;
  4. class类的概念
  5. 各类型数据的扩展
  6. 箭头函数
  7. promise
  8. 模块的概念
  9. let,const,symbol创建变量,块作用域的概念
  10. Map和Set新数据结构。

说一下对promise的了解

  • promise是es6提出的一种解决异步编程的方法,相对于原来使用回调函数的方法,它具有更合理,更强大,更简洁等优点。
  • promise是一个构造函数,自创建开始就会执行。含有且只能含有三种状态:pending执行中,fulfilled执行成功,reject执行失败。状态之间的转化也只能是单向的:pending到fulfilled、pending到reject;
  • promise有一个方法.then,用于接受promise处理后的结果,含有两个参数,relative和reject,分别接受成功和失败的结果,他们是内置的回调函数,返回一个promise。.then方法可以链式调用。

Promise的all和race有什么区别

  • Promise.all()方法用于将多个Promise实例包装成一个新的Promise实例。新的promise对象的状态由内部的多个promise共同决定,只有内部promise都是fulfilled时新的promise实例才是fulfilled,其他情况都是reject状态;
  • Promise.race()方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。多个promise之中有一个实例率先改变状态,新的promise实例的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给新的promise实例的回调函数。

箭头函数和普通函数的区别

  • 箭头函数this指向父级作用域的this
  • call(),apply(),bind()无法改变箭头函数中this的指向
  • 不可以被当作构造函数
  • 不可以使用arguments对象
  • 箭头函数不支持new.target

let、var和const的区别?如果希望const定义的对象的属性也不能被修改该怎么做?

a.不存在变量提升
b.块级作用域
c.暂时性死区
d.不可重复声明
e.不会挂在window对象下面
f.const声明之后必须马上赋值,否则会报错
g.const声明的简单类型不可更改,复杂类型内部数据可以更改 

用数据劫持,Object.defineProperty和Proxy都可以实现const定义的对象的属性也不能被修改。
const a = { b:3 }

Object.defineProperty(a,'b',{
    writable:false,
})

a.b = 9
console.log(a) // {b:3}

堆和栈的区别

  • 堆和栈都是操作系统的内存,堆是动态分配内存空间,内存大小不一样,也不会自动释放,栈是自动分配内存空间, 大小固定,会自动释放;
  • js声明的变量,基本数据类型的分配到栈内存,复杂数据类型在堆内存。

闭包的原理

  • 闭包是在函数创建时创建的,即有函数创建就会生成闭包
  • 闭包其函数同一上下文中
  • 闭包包含该作用域下的所有变量/引用地址
  • 定义函数不会创建闭包,只有创建/执行函数同时才创建闭包;

闭包:有权访问另一个函数作用域中的变量的函数

场景:

a.事件函数的封装

b.用闭包模拟私有方法

c.在循环中给页面元素绑定事件响应函数

特点:

1.创建私有变量

2.延长变量的生命周期

存在什么问题:闭包本身会造成内部变量常驻内存

instanceof的实现原理

  • 获取实例对象的隐式原型
  • 获取构造函数的prototype属性
  • while 循环 -> 在原型链上不断向上查找
  • 在原型链上不断查找 构造函数的显式原型
  • 直到implicitPrototype = null 都没有找到,返回false
  • 构造函数的prototype属性出现在实例对象的原型链上返回true

new的实现原理

  • 实例化对象
  • 返回值的问题:构造函数中如果有值返回,那实例化后的对象就是这个返回值

数据类型有哪些?如何判断一个数据是否是数组

基本数据类型:string,number,Boolean,null,underfined,symbol

引用数据类型:object(function,array,正则等等)

如何判断一个变量是不是数组:

  • array.constructor === Array
  • array instanceof Array
  • Array.isArray(array)
  • Object.prototype.toString.call(array) === [object Array]

分别介绍一下原型、原型链、作用域和作用域链的含义和使用场景

什么是原型、原型链?

原型:每当定义一个数据类型的时候,都会天生自带一个prototype属性,这个属性指向函数的原型对象,并且这个属性是一个对象数据类型的值。

原型链:在JavaScript中通过prototype对象指向父类对象,直到指向Object对象为止,这样就形成了一个原型指向的联调,称为原型链。当访问一个对象的属性或方法时,它会在对象自身中寻找,如果有则直接使用,如果没有则会去原型对象中查找,如果找到则直接使用。

什么是作用域、作用域链?

作用域:作用域就是代码的执行环境,全局执行环境就是全局作用域,函数的执行环境就是私有作用域,它们都是栈内存。

作用域链:当代码在一个执行环境中执行时,会创建变量对象的一个作用域链(作用域形成的链条)

人生の意味は平凡ですか、それとも素晴らしいですか?
最后更新于 2024-06-22