JavaScript面试题(二)

 34.arguments

  •  在JavaScript函数内部,arguments对象是一个类数组对象,它存储了函数被调用时传递的所有参数。
  • 动态参数列表:arguments对象可以接受任意数量的参数。这意味着你可以在调用函数时传递任意数量的参数,而不需要在函数定义中明确指定形式参数的个数。
  • 通过索引访问参数:可以通过arguments对象的索引来访问函数的参数。例如,arguments[0]表示第一个参数,arguments[1]表示第二个参数,以此类推。
  • 类数组对象:虽然arguments对象看起来像一个数组,但它并不是一个真正的数组。它没有数组特有的方法,如push()和pop(),但可以通过length属性获取参数的数量。

35.什么是纯函数

  • 返回值取决于参数
  • 不依赖于外部状态,也不改变外部状态的函数

36.匿名函数(IIFN)

  • 匿名函数,即没有名称的函数
  • 如果单独只写一个匿名函数,此时是不符合语法要求的 会报错。需要给 匿名函数包裹一个括号,使之成为表达式。
  • 被小括号包裹的内容会被js识别为一个函数表达式

37.什么是闭包函数

  • 在函数内部声明一个函数,并且使用了外部函数的变量,被称为闭包函数
  • 闭包函数的优点:实现私有属性和方法,减少对外界的污染;
  • 闭包函数的缺点:外部函数执行完之后,内部函数不会被销毁,造成变量长期贮存,占用内存空间
  • 解决闭包:使用call,apply,bind改变内部函数的this指向;内部函数改用箭头函数
  • 使用场景:防抖、节流、缓存、封装私有变量、函数柯里化等

38.函数柯里化

        概念:把一个接收多个参数的函数变成接收单一参数 并且返回能够接收新参数的函数

39.什么是递归函数

  • 一个函数直接或间接地调用自身,称为递归。
  • 常用场景:遍历属性结构、生成斐波那契数列、深拷贝

40.什么是回调函数

  • 在javascript中,回调函数指的是一个被作为参数传递给另一个函数的函数;
  • 回调函数本身不是异步的,但是可以通过异步机制(例如事件循环、Promises、async/await)来实现异步行为,例如定时器、延时器、axios请求、hooks、事件

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

  • this指向。箭头函数的this在定义时就已经确定,不会在运行时改变,它继承自外围作用域的this值;普通函数的this在运行时确定,可以通过call、apply、bind方法改变。
  • 原型属性。箭头函数没有原型属性;普通函数有原型属性
  • 构造函数。箭头函数不能作为构造函数使用,不能通过new关键字调用;普通函数可以作为构造函数使用。
  • 语法形式。箭头函数使用=>符号定义,而普通函数使用function关键字定义
  • 函数体语法。箭头函数的函数体可以省略括号,但有一定的限制。如果箭头函数的函数体只有一行语句,则可以省略大括号和return关键字;如果箭头函数的函数体多于一行语句,则必须使用大括号和return关键字;普通函数的函数体必须使用大括号。
  • arguments对象。箭头函数不绑定arguments对象,但可以通过剩余参数代替;普通函数有arguments对象,用于存储所有传递的参数
  • Generator函数。箭头函数不能作为Generator函数使用,不能使用yield关键字;普通函数可以作为Generator函数。

42.Generator函数

  • Generator函数是一种特殊类型的函数,它可以在执行过程中暂停并在需要时恢复执行。当Generator函数被调用时,它并不会立即执行,而是返回一个遍历器对象(Iterator),这个对象可以逐步遍历Generator函数的内部状态。
  • Generator函数使用步骤
    • Generator 函数使用 function* 声明,通过 yield 关键字产生一个值,并挂起函数的执行。
    • 可以通过调用 iterator.next() 方法逐一遍历迭代器对象,也可以为其传参,执行后标记为未完成。
    • 当运行到 iterator.return() 语句时,迭代器对象会被标记为“完成”,不再产生新的值。
  • iterator对象的方法:
    • next()逐一遍历迭代器对象
    • return()返回return的对象同时停止迭代
    • throw()中断迭代
  • 主要用途包括:解决回调地狱、迭代和生成无限序列、替代回调函数。

function* generator() {

  yield 'one';

  yield 'two';

  return 'done';

}

const iterator = generator(); //返回一个遍历器对象

console.log(iterator.next()); //{ value: 'one', done: false }

console.log(iterator.next()); //{ value: 'two', done: false }

console.log(iterator.next()); //{ value: 'done', done: true }

43.防抖和节流

  • 防抖(debounce)和节流(throttle)是性能优化中常用的两种技术,用以控制函数执行的频率,以减少计算资源的使用。
  • 防抖:指的是在一定时间内,对于频繁触发的事件,重新计算时间,只让其最后一次触发时执行。例如搜索框、页面改变大小。
  • 节流:指的是在一定时间内,对于频繁触发的事件,只让其执行一次,例如:触底加载、页鼠标不断点击时。

44.引用类型和值类型的区别

值类型基本数据类型
存储位置栈(stack)指针存放在 栈(stack)、实体存放在 堆(heap)
数据大小固定不固定
占用空间
存取速度
数据类型简单

复杂、可嵌套

访问方式按值访问按指针访问

45.什么是深拷贝和浅拷贝

  • 深拷贝。只复制对象内容,不复制对象的指针,拷贝出来的对象是一个全新的对象,修改这个新对象的时候,不会影响源对象。
  • 浅拷贝。只复制对象的指针,不复制对象的内容,拷贝出来的新对象指针还是指向原来的对象。修改这个新对象时,原来的对象也会被修改。引用类型的数据,默认都是浅拷贝。

46.深拷贝的方法

  • JSON.stringfy(JSON.parse())
    • 取不到值为 undefined 的 key;
    • 如果对象里有函数,函数无法被拷贝下来;
    • 无法拷贝copyObj对象原型链上的属性和方法;
  • 展开运算符:只能进行浅层的拷贝
  • Object.assign :只能进行浅层的拷贝
  • 递归实现深拷贝
    • 在递归过程中,需要记录已经遍历过的对象。
    • 需要处理不同数据类型(如数组和对象)。
  • 使用插件实现
    • lodash的cloneDeep函数
    • Immutable.js生成不可变数组或对象(Map不可变对象 List不可变数组)

47.什么是同步任务和异步任务

  • js是一门单线程语言,单线程意味着所有任务都需要排队,只有前一个任务执行完之后,才能执行下一个任务。这种情况显然是不合理的,比如说我挂起一个30秒的延时器,那么后面的任务就会被阻塞,导致cpu空闲且无法执行其他任务。针对这一情况,javascript把这些阻塞进程的任务统一放在了异步任务队列中等待执行,任务队列通知主线程某个异步任务可以执行了,这个异步任务就会被放在主线程中按顺序执行。
  • 同步任务(synchronous)就是主线程中的任务,按照顺序一个个的执行,比如:普通函数、new Promise()、console.log()等等
  • 异步任务 (asynchronous) 就是任务队列中的、会阻塞到进程的任务,只有“任务队列”通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。比如:DOM 事件回调、定时器回调、网络请求的回调、promise.then()、promise.catch()的回调。异步任务又分为宏任务和微任务:
    • 宏列队 macrotask queue:用来保存待执行的宏任务(回调),比如:DOM 事件回调、定时器回调、网络请求的回调
    • 微列队 microtask queue:用来保存待执行的微任务(回调),优先级高于宏任务,比如:promise.then()、promise.catch()、MutationObserver 、queueMiscrotask()

48.宏任务和微任务的区别

  • 执行优先级不同。宏任务的优先级相对较低,而微任务的优先级较高。
  • 执行时机不同。宏任务会被添加到事件队列中,在每个事件循环中执行一次;微任务会在当前宏任务执行完毕后立即执行,而不会添加到事件队列中,微任务的执行时机是在当前宏任务的末尾,在下一个宏任务之前。
  • 用途不同。宏任务通常包括定时器任务(如setTimeout、setInterval)、网络请求、用户交互事件(如点击、滚动等),这些是相对较大的任务,需要等待一定时间或特定的触发条件才会执行;微任务通常包括Promise回调、DOM变动观察器等,这些是相对较小的任务,适合在当前宏任务执行完毕后立即执行。
  • 总结:宏任务是事件循环中的较大任务,通常处理用户交互、渲染等任务;微任务是较小的任务,通常用于处理异步操作的结果,由于微任务具有较高的优先级,它们可以在用户交互之前或渲染之前得到及时处理。

49.Promise的作用

  • Promise的主要作用是处理异步操作。它允许你以更同步的方式编写异步代码,提高了代码的可读性和可维护性。
  • 处理异步任务结果。Promise区分成功(resolve)和失败(reject)的状态,使得错误处理更加明确和直接。
  • 避免回调地狱。Promise对象可以链式调用,减少嵌套回调的使用,避免代码过于复杂和难以管理。
  • 支持并发操作。例如,使用Promise.all()可以并行执行多个操作,等待所有操作完成后执行某些逻辑。
  • 便于代码的模块化和复用。通过将异步操作封装成Promise对象,可以提高代码的复用性和模块化程度。

50.promise的三种状态?怎么改变promise的状态

  • 等待中(Pending)。这是Promise的初始状态,表示异步操作尚未开始或结果尚未确定。
  • 已完成(Fulfilled)。当异步操作成功完成并返回结果时,Promise的状态变为Fulfilled。
  • 已拒绝(Rejected)。当异步操作执行失败时,Promise的状态变为Rejected。

51.Promise.then和Promise.catch

  • Promise函数有两个参数resolve和reject,当我们调用resolve()时,Promise函数会从等待状态变为成功状态,当我们调用reject()时,Promise函数会从等待状态变为失败状态。
  • .then():在promise函数中调用resolve()后执行的函数,用于处理执行成功的结果。可以通过resolve(参数)获得参数。
  • .catch():在promise函数中调用reject()后执行的函数,用于处理执行失败的结果。可以通过reject(参数)获得参数。
  • .then和.catch都属于异步任务中的微任务。

52.promise.all和promise.race的区别

  • Promise.allPromise.race都是用于处理多个Promise实例的方法,但它们的行为和用途有所不同。
  • Promise.all。接收一个Promise数组作为参数。只有所有结果都执行成功或失败的时候,才会变为成功状态或者失败状态,否则仍然会处于等待状态。如果所有Promise都执行成功,则返回所有执行成功的结果。如果有一个执行失败,就会返回第一个执行失败的结果。
  • Promise.race。接收一个Promise数组作为参数,返回的第一个执行成功的Promise结果。
  • romise.all适用于需要等待所有异步操作完成再进行下一步处理的场景,例如并行下载多个文件并将它们合并为一个文件;Promise.race适用于需要在多个异步操作中获取最先完成的结果的场景,例如设置超时机制或不知道哪个接口响应更快的情形。

53.proimse是同步还是异步

        Promise本身是同步的Promise是一个用于异步编程的对象,它允许你以同步的方式编写异步代码,但Promise对象本身在创建时立即执行,不会造成主线程的阻塞。然而,Promise的回调函数,如then()和catch(),是异步执行的,它们会在当前脚本的所有同步任务执行完毕后调用。

54.promise.then的交替执行

        如果是单个promise实例,即使有多个then,仍然会按照顺序执行。如果是多个promise实例同时调用.then,then会出现交替执行的情况。这个是编译器做的优化,主要是为了避免某一个promise占用的时间太长。

55.怎么解决回调地狱

  • promise实现链式调用
  • generator函数
  • async/await
  • 13
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王布尔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值