现在小厂实习都问的这么难了吗😱「万物心选一面(vue+小程序)」

发布于:2024-05-05 ⋅ 阅读:(14) ⋅ 点赞:(0)

h5是怎么和微信小程序通信的?不同H5页面怎么通信的?webview是谁提供的?

  1. web-view 是往小程序中嵌入h5的容器。会自动铺满整个小程序页面。微信小程序和 uni-app 都提供了 web-view 组件。
  2. 由于简历上有一段实习是移动端h5开发,让面试官误以为我做过微信小程序的内嵌h5页面,但其实实习中都是公司框架写的代码,页面也是直接嵌入公司的app中的,我并没有微信小程序开发的经验,现在整理答案也是死记硬背,mark一下看到的一篇讲的比较清楚的文章,以后学小程序了再来回顾。
  3. h5 页面间通信其实就是前端跨页面通信(吧?)当时第一反应回答的是使用LocalStorage, 面试官又提出用户修改个人信息后返回页面更新信息的情况,回答的是我之前做表单有类似的场景,是向后端提交后在后端更新了数据,回退到原先的页面的时候在 created/activated 的时候获取数据。

什么是微任务?什么是宏任务?

如果说哪些操作是宏任务,哪些操作是微任务,那大部分同学都是比较清楚的:

  • 宏任务:script(整体代码)/setTimout/setInterval/setImmediate(node 独有)/requestAnimationFrame(浏览器独有)/IO/UI render(浏览器独有)
  • 微任务:process.nextTick(node 独有)/Promise.then()/Object.observe/MutationObserver

这里面试官还追问了一句,Promise本身是微任务吗

那这两者有具体的定义吗?老规矩,直接 mdn 开搜。mdn 中可以找到微任务(microtask),但是并没有宏任务或者(macrotask)的信息。但是在中我们可以发现,在文档中只有taskmicrotask,对应的就是事件循环中的任务队列task queue和微任务队列microtask queue

文档中还提到了JavaScript 中的  和  都使用微任务队列去运行它们的回调函数,想来面试官的意思就是,Promise本身只是一个代理,Promise()是他的构造函数,真正被放进微任务队列的是Promise的then方法中的回调函数。

文档中对任务和微任务的定义也比较冗长,我想能区分哪些是微任务,哪些是宏任务,说出他们分别会被放在任务队列和微任务队列以及他们的执行顺序(事件循环会持续调用微任务直至队列中没有留存的,再去调用任务队列)应该足够面试了。

image.png

遍历对象有哪些方法,如果是对象的原型链上的属性会不会被遍历到?有什么办法可以排除原型链上的属性?

直接上代码测试一波:

Object.prototype.age=18;   // 修改Object.prototype  
const person ={ name: "小明" };

// 输出 name, age
for(key in person){
    console.log(key)  
}

// 输出 name
Object.keys(person).forEach(key=>{
    console.log(key);
})

// 输出 小明, 18
for(key in person){
    console.log(person[key])
}

// 输出 小明
Object.values(person).forEach(value=>{
    console.log(value);
})

// 输出 name: 小明
for (const [key, value] of Object.entries(person)) {
  console.log(`${key}: ${value}`);
}

很明显,for...in 会遍历到原型链上的属性,Object上的keysvaluesentires方法不会。 看看 mdn 怎么说:

for...in 语句以任意顺序迭代一个对象的除以外的属性,包括继承的可枚举属性

Object.keys()  静态方法返回一个由给定对象 自身 的可枚举的字符串键属性名组成的数组。 Object.entries()  静态方法返回一个数组,包含给定对象 自有 的可枚举字符串键属性的键值对。

Object.values()  静态方法返回一个给定对象的 自有 可枚举字符串键属性值组成的数组。

那么如果仍然想使用 for...in 来遍历对象,并且不想要原型链上的属性,我们可以使用 过滤掉它们:

for (key in person) {
    if (person.hasOwnProperty(key)) {
        console.log(key);
    }
}

如果指定的对象自身有指定的属性,则静态方法 Object.hasOwn()  返回 true。如果属性是继承的或者不存在,该方法返回 false

组件通信有哪些方法?依赖注入的数据是不是响应式的?有什么办法让他保持响应式的?

  • props / $emit
  • $emit / $on (eventBus)
  • provide / inject
  • $attrs / $listeners
  • ref / $ref
  • $parent / $children
  • vuex / pinia

vue更新dom是异步还是同步?如何不使用nexttick实现nexttick的功能?vue的更新是哪一种微任务?

Vue更新DOM是异步的。这意味着我们在修改完data之后并不能立刻获取修改后的DOM元素。Vue需要通过nextTick方法才能获取最新的DOM。

Vue在调用Watcher更新视图时,并不会直接进行更新,而是把需要更新的Watcher加入到queueWatcher队列里,然后把具体的更新方法flushSchedulerQueue传给nextTick进行调用。nextTick只是单纯通过Promise、setTimeout等方法模拟的异步任务。

如果你想要不使用nextTick实现nextTick的功能,你可以使用Promise、setTimeout等方法来模拟异步任务。例如,你可以使用 Promise.resolve().then(callback) 或者 setTimeout(callback, 0) 来实现类似于nextTick的功能。

至于Vue的更新是哪一种微任务,它取决于浏览器兼容性。Vue会根据浏览器兼容性,选用不同的异步策略。例如,如果浏览器兼容Promise,那么Vue就会使用Promise来实现异步更新。如果浏览器不兼容Promise但兼容MutationObserver,那么Vue就会使用MutationObserver来实现异步更新。如果浏览器既不兼容Promise也不兼容MutationObserver,那么Vue就会使用setImmediatesetTimeout来实现异步更新。

vue能监听到数组的push方法吗?直接给响应式变量赋值一个新的数组会被监听到吗?

这里讨论的都是vue2vue3当中这些问题都已经被proxy解决了。

Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

替换整个对象或数组就和操作其他类型的响应式数据没区别了,自然是可以检测到的。

如果要把数组api,比如push pop这些都改成async、await的异步函数要怎么做?怎么拿到这些方法?怎么传参?

这一问是我当时最蒙的,我到现在都不确定我是否领悟对了他要问什么,大致上的理解如下,如果有大佬知道的可以在评论区教学一下我这个小菜鸟。

// 保存数组原型上的push方法
const originalPush = Array.prototype.push;
// 重写数组原型上的push方法
Array.prototype.push = async function (...args) {
    // 模拟异步操作
    await new Promise(resolve => setTimeout(resolve, 500));
    return originalPush.apply(this, args);
}
async function test() {
  const arr = [1, 2, 3];
  await arr.push(4);
  console.log(arr); 
}
test(); // [1, 2, 3, 4],需要延迟定时器中设定的时间才能打印出来

在沸点一位大佬的提醒下,面试官可能想问的是这个

总结

总结就是一个字,菜。
虽然是问的有点细致,但基本上都只能回答上来每一问的第一问,后面的深入追问就懵逼了。原因是因为自己基本上都是直接对着面经和八股文准备的,没有实践过,也没有看过相关的文档。之后还是要坚持把JavaScript高级程序设计和vue设计与实现啃完,不说把这些问题记得滚瓜烂熟能对答如流,起码也要在在面试官引导下应该有思路。


网站公告

今日签到

点亮在社区的每一天
去签到