js 面试题

目录

Promise调用

Set

递归

有一个楼梯,每次可以走1个台阶或2个台阶,总共有几种走法

计算1~100之和

数组

求数组中最大值

迭代(遍历)数组

扁平化数组

使用flat

toString()

手写递归

使用while

数组倒序

对象

对象属性遍历

扁平化对象


Promise调用

Promise中的resolve和reject不会影响Promise其他代码的运行,也不会影响promiseFun实例中链式的调用

比如:下面的new Promise()调用了reject(),promise中的代码正常运行,实例中的链式调用,会先走catch的调用,后面的.then()也会依次调用,直至回调完所有的.then()

const promiseFun = (...reg) => {
 
  return new Promise((resolve,reject) => {
    console.log('1')
    reject()
    console.log('2')
    resolve()
    console.log('test')
  })
}
onMounted(() => {
  promiseFun({a:1}).then(() => {
    console.log('1')
  }).catch(() => {
    console.log('2')
  }).then(() => {
    console.log('3')
  }).catch(() => {
    console.log('4')
  }).then(() => {
    console.log('5')
  }).catch(() => {
    console.log('6')
  }).then(() => {
    console.log('7')
  }).catch(() => {
    console.log('8')
  })
})

结果:1 2 test 2 3 5 7

如果先调用resolve(),Promise()中的代码正常运行,实例中的链式调用,只会调用.then()也就只有完成状态,不会调用.catch()

const promiseFun = (...reg) => {
  return new Promise((resolve,reject) => {
    console.log('1')
    resolve()
    console.log('2')
    reject()
    console.log('test')
  })
}

结果:1 2 test 1 3 5 7

Set

集合数据类型,也具有增删改查等属性,但和数组不同,不会有重复的数据,

let data = [
  {
    id: 1,
    name:'title1'
  },
  {
    id: 2,
    name:'title2'
  },
  {
    id: 3,
    name:'title3'
  },
  {
    id: 4,
    name:'title4'
  },
]
let a1 = new Set(data.map((item) => item.id))
console.log('a1:',a1) 
// 使用has判断id为2的值是否存在
// console.log(a1)// true
// 使用has判断id为6的值是否存在
// console.log(a1.has(6))// false
// 获取set的length
console.log('length:',a1.size)
// 往set中添加数据
a1.add({id:5,name:'title5'})
console.log('after:',a1)

递归

有一个楼梯,每次可以走1个台阶或2个台阶,总共有几种走法

function n1(n){
​
  if (n === 1 ) return 1
​
  if (n === 2 ) return 2
​
  console.log('n:',n)
​
  return n1(n - 1) + n1(n - 2)
​
}
​
 console.log('总共有',n1(4), '种走法') // 总共有 5 种走法

计算1~100之和

// 求1~100和
const numb = (n) => {
  if(n === 1) return 1
  return numb(n - 1) + n
}
​
​// 步骤解析:
// 参数为1时
// 函数走到if(n === 1) return 1 返回1,后面的return不会执行
// 参数为2时
// 函数走到if(n === 1) n不等于1,执行下面的return,回调函数自己
// numb(2-1=1)回到参数为1的时候,return 为1,这时候numb(n-1) + n,即1+2=3,
// 参数为3时
// 函数走到if判断,执行下面的return,回调函数自己numb(3-1=2),也就到了参数为2的状态了,以此类推。
​
console.log("求1~100和:",numb(100))    // 求1~100和: 5050
这个函数通过递归的方式实现了求和的功能。每次递归调用都会将问题规模缩小(即n减1),直到达到基本情况(n等于1)。在达到基本情况后,递归开始逐层返回,每层都将当前的n值加到之前的结果上,最终得到从1到n的总和。

例如,调用numb(5)的过程如下:

  • numb(5) 调用 numb(4) 并加上5

  • numb(4) 调用 numb(3) 并加上4

  • numb(3) 调用 numb(2) 并加上3

  • numb(2) 调用 numb(1) 并加上2

  • numb(1) 返回1(递归终止)

然后,这些调用依次返回并累加:

  • numb(2) 返回 1+2=3

  • numb(3) 返回 3+3=6

  • numb(4) 返回 6+4=10

  • numb(5) 返回 10+5=15

因此,numb(5) 的结果是15,这也就是1到5的和。

数组

求数组中最大值
// 数组求和
let arr:Array<number> = reactive([10,2,3,46,986,982,5,90,6])
​
const findMax = (arr:Array<number>):number => {
  if (arr.length == 0) return null
  if (arr.length == 1) return 1
  if (arr.length === 2) {
    return arr[0] >= arr[1] ? arr[0] : arr[1]
  }
  let length1 = Math.floor(arr.length/2)
  let left = findMax(arr.slice(0,length1))
  let right = findMax(arr.slice(length1))
  return left >= right ? left : right
}
​
console.log('获取数组中最大值:',findMax(arr)) 
// 获取数组中最大值: 986

步骤解析

1:函数中先判断入参length为0,1和2的情况,直接return

2:Math.floor()向下取整,获取值,截取数据

3:调用函数本身重走第一步第二步,再到第三步,在length为2时取最大值

4:最终的两个值再进行比较,取最大值;

迭代(遍历)数组
// 迭代数组
let arr:Array<number> = reactive([10,2,3,46,986,982,5,90,6])
​
const iteration = (arr:Array<number>):number => {
  if (arr.length == 0 || arr.length == 1) return arr[0]
  console.log(arr[0])
  iteration(arr.slice(1))
}
iteration(arr)  // 10,2,3,46,986,982,5,90,6
步骤解析:

1:判断数组length为0或为1时,返回下标为0的值

3:数组length大于2时,使用slice截取不是第一位的值,再次调用函数本身进行,依次类推,迭代数组

扁平化数组
使用flat

创建一个新的数组,并根据指定深度递归地将所有子数组元素拼接到新的数组中

​
let arr = [1,[2,[3,4,5,[6,[7,8,9,10]]]]]
console.log(arr.flat(2)) // [1,2,3,4,5,[6,[7,8,9,10]]]
console.log(arr.flat(3)) // [1, 2, 3, 4, 5, 6, [7, 8, 9, 10]]
console.log(arr.flat(Infinity)) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
toString()
let arr = [1,[2,[3,4,5,[6,[7,8,9,10]]]]]
​
console.log('使用toString:',arr.toString())
let arr1 = arr.toString().split(',').map((item) => {
  return item
})
console.log('扁平化后的数组arr:',arr1) //  ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
​
手写递归
// 递归
const iteration = (arr:any[]): Array<number> =>{
  let arrResult = []
  for (let i in arr) {
    if (Array.isArray(arr[i])){
      arrResult = arrResult.concat(iteration(arr[i]))
    } else {
     arrResult.push(arr[i])
    }
  }
   return arrResult
}
console.log('扁平化之后的数组:',iteration(arr))
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

reduce

// 扁平化数组
let arr = [1,[2,[3,4,5,[6,[7,8,9,10]]]]]
​
const iteration = (arr) => {
  return arr.reduce((result,value) => Array.isArray(value) ? result.concat(iteration(value)) : result.concat(value),[])
}
​
​
console.log('iteration 之后的数据:',iteration(arr))
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

步骤解析:

1: 使用reduce遍历数组

2: 判断当前的入参是不是数组,是的话,拼接函数返回值

3: 不是数组的话,直接拼接

使用while
// while
const iteration = (arr) => {
  let result = []
  
  while(arr.length !== 0){
     console.log('arr:',arr)
    console.log('arr.length:',arr.length)
    
    let [first,...rest] = arr
    if (Array.isArray(first)) {
      // 第一项是数组,就解构
      arr = [...first,...rest]
    } else {
      // 循环数据,把第一项不是数组的值添加到result中
      // 把数组类型的值赋值给arr,依次循环,直到数组穷尽
      result.push(first)
      arr = [...rest]
    }
  }
  return result
}
​
console.log("扁平化后的数组:",iteration(arr))
//  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

数组倒序

let arr:Array<number> = reactive([10,22,3,46,986,982,5,90,6])
​
const iteration = (arr:Array<number>):Array<number> =>{
​
  if (arr.length == 0 || arr.length == 1) return arr
​
  return [...iteration(arr.slice(1)),arr[0]]
​
}
​
console.log(iteration(arr))

步骤解析:

1:判断length为0或1的,直接返回原数组

2:return 取数组下标为1的值,传给函数本身,走第一步

3:使用扩展运算符把函数return的值进行拼接+下标为0的值

对象

对象属性遍历

let object1 = {
  id:1,
  value:'标题1',
  obj:{
    id:2,
    value:'标题2',
    obj:{
        id:3,
        value:'标题3',
        obj:{
            id:4,
            value:'标题4',
            obj:{
                id:5,
                value:'标题5',
                obj:{
                    id:6,
                    value:'标题6',
                },
            },
        },
    },
  },
}
​
interface Iobj  {
  id: number
  value: string
​
}
interface Iobj1 {
  obj:Iobj
}
const ergodic = (obj:Iobj1) => {
  for(let k in obj) {
    if (obj.hasOwnProperty(k)) {
      if (typeof obj[k] == 'object') {
        ergodic(obj[k])
      } else {
        console.log(`${k}:${obj[k]}`)
      }
    } 
  }
}
​
console.log('打印:',ergodic(object1))

步骤解析:

1:先循环对象

2:通过hasOwnProperty判断对象里面是否有属性

3: 通过typeof检查对象是不是对象

4:如果是对象再调用函数自身,重复前面1,2,3的步骤

5:如果不是对象,就打印数据

扁平化对象

const oldObject = {
    "A": '1', 
   
    "B":{
        "title": 'Hello world', 
        "tipes": 3, 
        "description":{
            "title": 7, 
            "tipes":{
                "title": 7, 
                "" : 2
            }
         }
      },
    "A1": 12, 
}
​
​
const filterObj = (oldObject) => {
  // 初始化一个新的对象,用来存储扁平化的数据
  let newObject = {}
  iteration(oldObject,newObject,'')
  return newObject
  function iteration (currentObject,newObject,privateKeyName) {
    for (let key in currentObject){
      let value = currentObject[key]
      // 遍历对象,判断是不是对象,是对象就再次调用函数自身,不是就给newObject添加
      if (value.constructor !== Object) {
        if (privateKeyName == null || privateKeyName == '') {
          newObject[key] = value
        } else {
          // 异常场景:当前的key可能为空字符串,就拿上级的privateKeyName作为新key
          // 如果当前的key不为null或'',就做拼接
          if (key === null || key === ''){
            newObject[privateKeyName] = value
          } else {
            newObject[privateKeyName + '.' + key] = value
          }
        } 
      } else {
        // key是个对象,判断上级的privateKeyName是否为null或空字符串
        // 是的话,就把当前的key作成新的key
        // 上级的privateKeyName不为null或空字符串,就做拼接给下个对象
        if (privateKeyName === null || privateKeyName === '') {
          iteration(value,newObject,key)
        } else {
          iteration(value,newObject,privateKeyName + '.' + key)
        }
      }
    }
  }
} 
​
 console.log(filterObj(oldObject))
​
// {
//     "A": "1",
//     "B.title": "Hello world",
//     "B.tipes": 3,
//     "B.description.title": 7,
//     "B.description.tipes.title": 7,
//     "B.description.tipes": 2,
//     "A1": 12
// }

个人理解,递归的意思就是,在函数里面调用自身,前提是不满足函数之前的判断条件,才会进入再次调用函数本身的逻辑。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/940199.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

在租用服务器上配置环境

使用的是并行计算云&#xff0c;现在有活动&#xff0c;可以用到明年3月多。50元入会&#xff0c;有500元的卷。 注册完会员后&#xff0c;按照图里说的领卷即可&#xff0c;卷会发送到邮箱里&#xff0c;按照要求兑换就好。下面是具体使用流程。 可以在不开机的情况下&#…

run postinstall error, please remove node_modules before retry!

下载 node_modules 报错&#xff1a;run postinstall error, please remove node_modules before retry! 原因&#xff1a;node 版本出现错误&#xff0c;我的项目之前是在 12 下运行的。解决方法&#xff1a; 先卸载node_modules清除缓存将node版本切换到12重新下载即可

基于蓝牙通信的手机遥控智能灯(论文+源码)

1.系统设计 灯具作为人们日常生活的照明工具为人们生活提供光亮&#xff0c;本次基于蓝牙通信的手机遥控智能灯设计功能如下&#xff1a; &#xff08;1&#xff09;用户可以通过蓝牙通信模块的作用下&#xff0c;在手机端遥控切换智能灯不同的工作模式&#xff1b; &#x…

IDEA搭建SpringBoot,MyBatis,Mysql工程项目

目录 一、前言 二、项目结构 三、初始化项目 四、SpringBoot项目集成Mybatis编写接口 五、代码仓库 一、前言 构建一个基于Spring Boot框架的现代化Web应用程序&#xff0c;以满足[公司/组织名称]对于[业务需求描述]的需求。通过利用Spring Boot简化企业级应用开发的优势&…

[HNCTF 2022 Week1]你想学密码吗?

下载附件用记事本打开 把这些代码放在pytho中 # encode utf-8 # python3 # pycryptodemo 3.12.0import Crypto.PublicKey as pk from hashlib import md5 from functools import reducea sum([len(str(i)) for i in pk.__dict__]) funcs list(pk.__dict__.keys()) b reduc…

OneCode:开启高效编程新时代——企业定制出码手册

一、概述 OneCode 的 DSM&#xff08;领域特定建模&#xff09;出码模块是一个强大的工具&#xff0c;它支持多种建模方式&#xff0c;并具有强大的模型转换与集成能力&#xff0c;能够提升开发效率和代码质量&#xff0c;同时方便团队协作与知识传承&#xff0c;还具备方便的仿…

【UE5】pmx导入UE5,套动作。(防止“气球人”现象。

参考视频&#xff1a;UE5Animation 16: MMD模型與動作導入 (繁中自動字幕) 问题所在&#xff1a; 做法记录&#xff08;自用&#xff09; 1.导入pmx&#xff0c;删除这两个。 2.转换给blender&#xff0c;清理节点。 3.导出时&#xff0c;内嵌贴图&#xff0c;选“复制”。 …

[x86 ubuntu22.04]投影模式选择“只使用外部”,外部edp屏幕无背光

1 问题描述 CPU&#xff1a;G6900E OS&#xff1a;ubuntu22.04 Kernel&#xff1a;6.8.0-49-generic 系统下有两个一样的 edp 屏幕&#xff0c;投影模式选择“只使用外部”&#xff0c;内部 edp 屏幕灭&#xff0c;外部 edp 屏幕无背光。DP-1 是外部 edp 屏幕&#xff0c;eDP-1…

【zlm】 webrtc源码讲解三(总结)

目录 setsdp onwrite ​编辑 play 参考 setsdp onwrite play 参考 【zlm】 webrtc源码讲解_zlm webrtc-CSDN博客 【zlm】 webrtc源码讲解&#xff08;二&#xff09;_webrtc 源码-CSDN博客

Python拆分Excel - 将工作簿或工作表拆分为多个文件

在日常工作中&#xff0c;我们经常需要处理包含大量数据的Excel文件。这些文件可能包含不同的表格、图表和工作表&#xff0c;使得数据管理和分析变得复杂。为了提高效率和准确性&#xff0c;我们可以将一个Excel文件或其中某一个工作表按需求拆分为多个文件&#xff0c;以便更…

作业Day4: 链表函数封装 ; 思维导图

目录 作业&#xff1a;实现链表剩下的操作&#xff1a; 任意位置删除 按位置修改 按值查找返回地址 反转 销毁 运行结果 思维导图 作业&#xff1a;实现链表剩下的操作&#xff1a; 1>任意位置删除 2>按位置修改 3>按值查找返回地址 4>反转 5>销毁 任意…

Docker:Dockerfile(补充四)

这里写目录标题 1. Dockerfile常见指令1.1 DockerFile例子 2. 一些其他命令 1. Dockerfile常见指令 简单的dockerFile文件 FROM openjdk:17LABEL authorleifengyangCOPY app.jar /app.jarEXPOSE 8080ENTRYPOINT ["java","-jar","/app.jar"]# 使…

jmeter中的prev对象

在jmeter中通过beanshell、JSR223的各种处理器编写脚本时&#xff0c;都会看到页面上有这样的说明 这些ctx、vars、props、OUT、sampler、prev等等都是可以直接在脚本中使用的对象&#xff0c;由jmeter抛出 今天主要讲一下prev的使用 SampleResult prev jmctx.getPreviousRe…

数据库管理系统——数据库设计

摘要&#xff1a;本博客讲解了数据库管理系统中的数据库设计相关内容&#xff0c;包括概念结构设计&#xff1a;E-R模型&#xff0c;逻辑结构设计&#xff1a;E-R模型到关系设计等内容。 目录 一、数据库设计和数据模型 1.1.数据库设计概述 1. 2.数据库结构概述 1.3.数据库…

Mac配置 Node镜像源的时候报错解决办法

在Mac电脑中配置国内镜像源的时候报错,提示权限问题,无法写入配置文件。本文提供解决方法,青测有效。 一、原因分析 遇到的错误是由于 .npm 目录下的文件被 root 用户所拥有,导致当前用户无法写入相关配置文件。 二、解决办法 在终端输入以下命令,输入管理员密码即可。 su…

【原生js案例】前端封装ajax请求及node连接 MySQL获取真实数据

上篇文章&#xff0c;我们封装了ajax方法来请求后端数据&#xff0c;这篇文章将介绍如何使用 Node.js 来连接 MySQL&#xff0c;并对数据库进行操作。 实现效果 代码实现 后端接口处理 const express require("express"); const connection require("../da…

使用FakeSMTP创建本地SMTP服务器接收邮件具体实现。

以下代码来自Let’s Go further节选。具体说明均为作者本人理解。 编辑邮件模版 主要包含三个template: subject&#xff1a;主题plainBody&#xff1a; 纯文本正文htmlBody&#xff1a;超文本语言正文 {{define "subject"}}Welcome to Greenlight!{{end}} {{def…

在Linux系统安装配置 MySQL 和 hive,hive配置为远程模式

前提&#xff1a;已安装配置好了Hadoop环境&#xff0c;因为hive的底层是Hadoop 1 Mysql安装 搜索Centos7自带的mariadb rpm -qa|grep mariadb 卸载mariadb rpm -e mariadb-libs-5.5.64-1.el7.x86_64 --nodeps 再搜索一次看看是否还存在 rpm -qa|grep mariadb 安装mysql 创…

【JetPack】Room数据库笔记

Room数据库笔记 ORM框架&#xff1a;对齐数据库数据结构与面向对象数据结构之间的关系&#xff0c;使开发编程只考虑面向对象不需要考虑数据库的结构 Entity : 数据实体&#xff0c;对应数据库中的表 <完成面向对象与数据库表结构的映射> 注解&#xff1a; 类添加注解…

OpenHarmony-4.HDI 框架

HDI 框架 1.HDI介绍 HDI&#xff08;Hardware Device Interface&#xff0c;硬件设备接口&#xff09;是HDF驱动框架为开发者提供的硬件规范化描述性接口&#xff0c;位于基础系统服务层和设备驱动层之间&#xff0c;是连通驱动程序和系统服务进行数据流通的桥梁&#xff0c;是…