• 作者:老汪软件技巧
  • 发表时间:2024-10-10 07:01
  • 浏览量:

我是All in AI的前端老兵shunwuyu,带班攻战互联网大厂面试十年了。春招、秋招,都感觉与同学们一样热血沸腾。我以同学的口吻写了面试系列,希望对大厂入职大厂有所帮助。

如果您喜欢我的面试系列,欢迎点赞,收藏,也欢迎加我V(shunwuyu), 入群一起交流。

前言

能在小红书里找到美团面试,大家惊愕了吧。我这个面试来自美团一位实习生的文章,说他要去上课了,可以内推面他的坑位。没想一投,面试就安排到位了。 大二升大三的第一次大厂面试,不求黄袍加身,但求面试官温柔待我。反正远程实习干着,大厂都面面。

面试题截图

自我介绍

可以看

判断数组的方法

    let arr = [1, 2, 3]; 
    console.log(arr instanceof Array); // true

function isArrayLike(obj) { 
    return obj != null && typeof obj === 'object' && 'length' in obj; 
}
let arr = [1, 2, 3]; 
console.log(isArrayLike(arr)); // true

小结: 普通考题,但能展现js基础能力,答题主要在于全面。

箭头函数和普通函数的区别js中的异步方法

JavaScript 是一种单线程语言,这意味着它在同一时间只能执行一个任务。然而,JavaScript 通过异步编程模型来处理耗时的操作,如网络请求、文件读写等,从而避免阻塞主线程。

JavaScript 的异步方法主要有三种:回调函数、Promise 和 Async/Await。

async/await原理概念:async/await 是基于 Promise 的语法糖,目的是简化异步代码的书写,避免回调地狱,提供一种更类似于同步代码的异步编程体验。async 函数:使用 async 关键字定义的函数总是返回一个 Promise 对象。即使函数内部没有明确返回 Promise,JavaScript 也会将返回值自动封装为 Promise.resolve()。await 表达式:await 用于暂停 async 函数的执行,等待一个 Promise 解析。await 后面必须是一个 Promise 对象或可转化为 Promise 的值。函数会在 Promise 解析完成后恢复执行,并返回 Promise 的结果。如果 Promise 被拒绝,await 会抛出异常,可以使用 try/catch 来捕获。事件循环:async/await 并不会阻塞主线程,而是将异步操作推入事件循环的微任务队列(microtask queue)。当同步代码执行完毕后,JavaScript 引擎会检查微任务队列并执行相应的回调,这就是为什么 await 不会阻塞整个程序。

总结:async/await 是基于 Promise 实现的语法糖,利用事件循环将异步任务放入微任务队列,使得异步代码看起来像同步代码,极大简化了代码的可读性。

事件冒泡机制

定义:事件冒泡是浏览器处理 DOM 事件的一种机制。当一个事件发生在一个元素上时,它首先会被该元素处理,然后事件会按照父子层级向上(从目标元素到根元素 document)依次触发父级元素的相同事件监听器,直到到达最顶层。

事件传播阶段:事件传播分为三个阶段:

默认行为:事件冒泡是浏览器的默认行为,但可以通过 event.stopPropagation() 来阻止事件进一步冒泡。

实际应用:

通个addEventListener的第三个参数,可以控制时间在哪个阶段触发。

addEventListener 的第三个参数可以是一个布尔值或一个对象,它的作用是指定事件监听器的选项,主要包括以下几种情况:

capture(布尔值):

options(对象): 第三个参数也可以是一个包含以下属性的对象,用于更精细地控制事件监听器的行为:

事件循环

可以查看

解构url

直接上

vue 生命周期

生命周期demo

请求数据应该放在哪个生命周期?为什么?

在 Vue 3 中,请求数据通常放在 onMounted 生命周期钩子中。原因是 onMounted 会在组件的 DOM 渲染完成后调用,这时可以安全地进行异步请求并更新组件的状态,而不会阻塞页面的初次渲染。

聊聊vue响应式数据的proxy

在 Vue 3 中,响应式系统采用了 Proxy 代替 Vue 2 中的 Object.defineProperty,以更灵活、强大的方式实现响应式数据。

let handler = { ownKeys(target) { console.log('Listing keys'); return Object.keys(target); } };

let handler = {
  getOwnPropertyDescriptor(target, prop) {
    console.log(`Getting descriptor for ${prop}`);
    return Object.getOwnPropertyDescriptor(target, prop);
  }
};

function lazyReactive(target) {
  const handler = {
    get(target, key, receiver) {
      const value = Reflect.get(target, key, receiver);
      if (typeof value === 'object' && value !== null) {
        // 懒代理:只有在访问时才代理嵌套对象
        return lazyReactive(value);
      }
      return value;
    },
    set(target, key, value, receiver) {
      const oldValue = Reflect.get(target, key, receiver);
      const result = Reflect.set(target, key, value, receiver);
      if (oldValue !== value) {
        // 触发视图更新
        updateView();
      }
      return result;
    }
  };
  return new Proxy(target, handler);
}
// 模拟视图更新
function updateView() {
  console.log('View updated');
}
const state = lazyReactive({
  count: 0,
  nested: {
    name: 'Vue 3',
    details: {
      version: '3.0.0'
    }
  },
  array: [1, 2, 3]
});
console.log('Initial state:', state);
state.nested.name = 'Vue 3.1'; // 懒代理,只在访问 nested 时代理
console.log('Updated nested.name:', state.nested.name);
state.nested.details.version = '3.1.0'; // 懒代理,只在访问 nested.details 时代理
console.log('Updated nested.details.version:', state.nested.details.version);
console.log('Final state:', state);

function reactive(target) { 
    return new Proxy(target, { 
        get(target, key, receiver) { 
            return Reflect.get(target, key, receiver); 
        }, 
        set(target, key, value, receiver) { 
            const result = Reflect.set(target, key, value, receiver); 
            console.log(`${key} changed to ${value}`); 
            return result; } }); } 
      const state = reactive({ count: 0 }); 
      state.count = 1; // 输出: count changed to 1 console.log(state.count); // 1 // 新增属性 state.newProp = 'new value'; console.log(state.newProp); // 'new value' // 新增属性会触发响应式 state.newProp = 'updated value'; // 输出: newProp changed to updated value console.log(state.newProp); // 'updated value'

有一串只有"["、"]"、"{"、"}"、"("、")" 判断是否是合法

function isValid(s) {
  // 用于存储左括号的栈
  const stack = [];
  
  // 括号对映射
  const mapping = {
    ')': '(',
    '}': '{',
    ']': '['
  };
  
  // 遍历字符串中的每个字符
  for (const char of s) {
    if (char in mapping) {
      // 如果是右括号,检查栈顶是否有匹配的左括号 #只是一个占位符
      const topElement = stack.length === 0 ? '#' : stack.pop();
      if (mapping[char] !== topElement) {
        return false;
      }
    } else {
      // 如果是左括号,将其推入栈中
      stack.push(char);
    }
  }
  
  // 检查栈是否为空(所有的左括号都应该匹配)
  return stack.length === 0;
}
// 示例用法
console.log(isValid("()")); // 输出 true
console.log(isValid("()[]{}")); // 输出 true
console.log(isValid("(]")); // 输出 false
console.log(isValid("([)]")); // 输出 false
console.log(isValid("{[]}")); // 输出 true

总结

最近我们挺多同学在小红书上找到一些面试线索的, 还有远程实习了, 大家也可以试试。