软通动力前端笔试面试题

笔试题

1. 实现一个深拷贝
function deepcopy(obj)
{
  if(typeof obj!=='Object'||obj===null)
    return obj
  else
  {  
    let newobj=Array.isArray(obj)? []:{}
    for(let key in obj)
    {
      if(obj.hasOwnProperty(key))  
      {
        newobj[key]=deepcopy(obj[key])
      }
    }
    return newobj
  }
}
2. 扁平化数组

指将嵌套的多维数组转换为一个一维数组

function flattenArray(arr)
{
  let newArray=arr.reduce((acc,curr)=>
  {
    if(Array.isArray(curr))
    {
      return acc.concat(flattenArray(curr))
    }
    else
      return  acc.concat(curr)
  },[])
  return newArray
}

const nestedArray = [1, [2, [3, 4], 5], 6];
const flattenedArray = flattenArray(nestedArray);
console.log(flattenedArray); // 输出 [1, 2, 3, 4, 5, 6]
3. 数组去重
//方法1
function removeRepeatArray(arr)
{
  let newArray=arr.reduce((acc,curr)=>
  {
    if(!acc.includes(curr))
      acc.push(curr)
    return acc
  },[])
  return newArray
}

//方法2
function removeRepeatArray(arr)
{
  return Array.from(new Set(arr))
}
4. 实现一个闭包
function closeFunc()
{
  let a=1
  function hh()
  {
    a++
    console.log(a)
  }
  return hh
}

const innerFunc = closeFunc(); // 调用 closeFunc,得到内部函数的引用
innerFunc(); // 执行返回的内部函数 hh,输出 2
innerFunc(); // 继续执行内部函数,输出 3

一面

1. 计算一个字符在字符串中出现的次数
//方法1
function countString(char,str)
{
  let count=0
  for(let i=0;i<str.length;i++)
  {
    if(char===str.charAt(i))
    count++
  }
  return count
}

//方法2
function countString(char,str)
{
  const regex=new RegExp(char,'g')
  let arr =[]
  arr=str.match(regex)
  return arr.length
}


const char = 'a';
const str = 'banana';
const count = countString(char, str);
console.log(count); // 输出 3
2. for of和for in 的区别

for...offor...in 是 JavaScript 中两种不同的迭代循环语句,它们在使用上有一些区别。

  1. for...of 循环:

    • 用于遍历可迭代对象(例如数组、字符串、Set、Map、Generator 等)的值。

    • 循环体内直接访问每个元素的值,而不是索引或键。

    • 不适用于遍历普通对象(Plain Object)。

    • 语法:

      for (const value of iterable) {
         // 循环体
      }
      
    • 示例:

      const arr = [1, 2, 3];
      for (const num of arr) {
         console.log(num); // 输出 1, 2, 3
      }
      
  2. for...in 循环:

    • 用于遍历普通对象(Plain Object)的可枚举属性。

    • 循环体内访问的是每个属性的键(属性名)。

    • 也可以用于遍历数组或类数组对象,但可能会出现意外结果,因为它遍历的是对象的键而不是索引。

    • 语法:

      for (const key in object) {
         // 循环体
      }
      
    • 示例:

      //遍历对象
      const obj = { a: 1, b: 2, c: 3 };
      for (const key in obj) {
         console.log(key); // 输出 a, b, c
      }
      
      //也可以遍历数组(会有问题)
      const arr = [8, 5, 9];
      for (const index in arr) {
        console.log(index); // 输出 0, 1, 2
      }
      //但是会有问题。
      //问题如下
      Array.prototype.customMethod = function() {
        console.log('Custom method');
      };
      const arr = [8, 5, 9];
      for (const index in arr) {
        console.log(index); // 输出 0, 1, 2, "customMethod"
      }
      //解答:因为for...in 循环遍历了数组的原型链上的属性
      
      //解决
      Array.prototype.customMethod = function() {
        console.log('Custom method');
      };
      const arr = [8, 5, 9];
      for (const index in arr) {
          if(arr.hasOwnProperty(index)) //判断是否是自身的属性,而不是原型上的属性
          {
            console.log(index); // 输出 0, 1, 2
          }
      }
      
      

总结:

  • for...of 用于遍历可迭代对象的值。
  • for...in 用于遍历对象的可枚举属性,也可用于遍历数组的键。
  • 在处理数组时,推荐使用 for...of,而在处理对象时,推荐使用 for...in
3. let const 的区别
  1. 可变性
    • let 声明的变量是可变的(mutable),意味着你可以重新赋值给这个变量。
    • const 声明的变量是不可变的(immutable),意味着一旦被赋值就不能再改变。
  2. 作用域
    • 无论是 let 还是 const 声明的变量都具有块级作用域,它们在定义它们的块中可见,并且在该块结束后将被销毁。
  3. 重复声明
    • 在同一个作用域内,let 允许你重新声明同名变量,而 const 则不允许。
  4. 初始化
    • let 声明的变量可以在声明后稍后初始化。
    • const 声明的变量必须在声明时进行初始化,且一旦初始化后就不能再重新赋值。
  5. 全局对象属性
    • letconst 声明的全局变量不会成为全局对象的属性(在浏览器中是 window 对象),而用 var 声明的全局变量会成为全局对象的属性。
4. filter使用方法

是 JavaScript 数组的一个高阶函数,用于筛选数组中满足条件的元素,返回一个新的数组。

const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let evenNumbers=numbers.filter((ele,index,Arry)=>
{
    console.log(ele,index,Arry)
    //ele 为当前元素值,index为索引,Arry为原数组
    return ele%2===0
})
console.log(evenNumbers);
5. 数组遍历有哪些方法
  • for循环
  • for of
  • for in 需要使用hasProperty判断
  • forEach
  • map
  • reduce
  • filter
6. vue2 vue3 响应式原理分析

Vue 2 和 Vue 3 的响应式原理有所不同。下面分别对 Vue 2 和 Vue 3 的响应式原理进行简要分析。

Vue 2 的响应式原理

Vue 2 使用了基于 Object.defineProperty 的劫持(Object.defineProperty-based Observer)来实现响应式。

  1. 数据劫持:Vue 2 在组件初始化时,会对组件的 data 数据进行递归遍历,并通过 Object.defineProperty 将每个属性转化为 getter/setter。这样一来,当访问或修改这些属性时,Vue 2 就能够监听到,并触发相应的依赖追踪和更新操作。
  2. 依赖追踪:Vue 2 通过在 getter 中收集依赖,在访问属性时将依赖关系建立起来。每个属性都有一个对应的依赖收集器(Dep),用于存储依赖关系。
  3. Watcher:在模板编译过程中,Vue 2 会解析模板中的表达式,并创建对应的 Watcher。Watcher 会在初始化时触发一次属性的 getter,从而建立起属性与 Watcher 之间的关联。当属性发生变化时,会通知相关的 Watcher 进行更新。
  4. 派发更新:当属性发生变化时,会触发对应的 setter,setter 中会通知属性对应的依赖收集器(Dep)派发更新。Dep 会遍历所有相关的 Watcher,并调用 Watcher 的更新函数,进而更新视图。
Vue 3 的响应式原理

Vue 3 使用了基于 ES6 的 Proxy 对象来实现响应式。相比 Vue 2 的劫持方式,Vue 3 的响应式原理更加简洁高效。

  1. Proxy 对象:Vue 3 在组件初始化时,创建了一个根级的响应式代理对象,该对象会代理组件的 data 数据。Proxy 对象可以拦截对代理对象的访问和修改操作。
  2. 依赖追踪:Vue 3 使用了一个全新的响应式引擎,利用了 JavaScript 语言自身的特性。在访问代理对象时,会收集依赖关系,并建立起属性与依赖之间的映射关系。
  3. Reactivity API:Vue 3 提供了一组 API(如 reactiverefcomputed 等)用于创建响应式数据,这些 API 在内部会使用 Proxy 对象来实现响应式。
  4. 副作用追踪:Vue 3 使用了类似于 React Hooks 的方式,通过 effect 函数来追踪副作用。effect 函数会在组件渲染时执行,并自动追踪其中访问的响应式数据,并建立起响应式数据与副作用之间的关联。
  5. 派发更新:当响应式数据发生变化时,会自动触发更新,重新执行相关的副作用函数,同时通知组件进行局部更新,以保持视图与数据的同步。

总的来说,Vue 2 和 Vue 3 都使用了不同的技术手段来实现响应式。Vue 2 使用了 Object.defineProperty 进行数据劫持,而 Vue 3 则利用了 ES6 的 Proxy 对象来实现响应式,使得代码更加简洁高效。

7. vue3升级优化分析

Vue 3 相对于 Vue 2 在性能和开发体验上都有一系列的优化和改进。以下是一些主要的升级优化分析:

  1. 更好的性能
    • 虚拟 DOM 重写:Vue 3 对虚拟 DOM 进行了重写,使其更加高效。新的虚拟 DOM 实现减少了许多不必要的操作,并提高了渲染性能。
    • 静态提升:Vue 3 在编译阶段能够识别出静态节点,并将其提升为常量,减少了运行时的开销。
    • Tree-shaking 支持:Vue 3 支持更好的 Tree-shaking,使得打包工具能够更好地优化代码,减少打包体积。
  2. 更小的体积
    • 模块化构建:Vue 3 的代码更加模块化,可以按需加载,从而减少了整体的体积。
    • Composition API 的模块化引入:Vue 3 的 Composition API 具有模块化的特性,使得开发者可以更加灵活地组织代码,从而减少了代码量。
  3. 更好的 TypeScript 支持
    • 全面支持 TypeScript:Vue 3 的代码基本上是用 TypeScript 编写的,因此对 TypeScript 的支持更加全面和友好。
    • 更好的类型推断:Vue 3 在编译时会生成更加准确的类型定义,使得开发时能够获得更好的类型推断和代码提示。
  4. 更灵活的组件设计
    • Composition API:Vue 3 引入了 Composition API,使得组件的逻辑可以更加灵活地组织,提高了代码的可维护性和可复用性。
    • Teleport 和 Suspense:Vue 3 新增了 Teleport 和 Suspense 这两个特性,使得开发者能够更灵活地控制组件的渲染位置和加载状态。
  5. 更好的开发体验
    • 更快的开发速度:通过 Composition API 和 TypeScript 的支持,使得开发者能够更快地编写和调试代码。
    • 更好的错误提示:Vue 3 对错误提示进行了改进,使得开发者能够更容易地定位和解决问题。

总的来说,Vue 3 在性能、体积、开发体验和灵活性等方面都有明显的优化和改进,是一个更加成熟和强大的框架。因此,对于使用 Vue 的项目来说,考虑升级到 Vue 3 是一个非常值得的选择。

  • 9
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值