首页 > 其他分享 >???热乎的前端面试题(昨天)

???热乎的前端面试题(昨天)

时间:2023-04-15 16:34:46浏览次数:40  
标签:面试题 Vue obj key 前端 热乎 Object 数组 name

前言

系列首发于公众号『前端进阶圈』 ,若不想错过更多精彩内容,请“星标”一下,敬请关注公众号最新消息。

热乎的前端面试题(昨天)

1.Vue 响应式原理?

  • vue2
  • Vue2 中注意使用 Object.defineProperty() 方法来实现响应式,它为对象中的每一个属性都定义了一个 gettersetter,当数据发生变化时,会触发相应的更新操作,从而让视图也随之更新。
  • Vue2 中,数据对象通过 new Vue 中的 data 对象进行实例化,在实例化的过程中,Vue 会遍历这个数据对象使用 Object.defineProperty() 把他们转化为 getter/setter,当 getter/setter 接收到访问或修改时,会通过对应的 Watcher 及所依赖的 Watcher 进行更新。
  • vue3
  • 在 vue3 中主要使用了 Reactive APIProxy 来实现响应式
  • reactive() 函数会讲一个普通对象转换成响应式对象,这个函数内部使用了 ES6proxy 对象,讲的对象的 getter/setter, 并使用依赖收集,派发更新等机制。
  • 同时增加了 refcomputed 这两个响应式 API,让我们可更灵活的管理组件内的数据状态。

2.Vue是如何监听数组的变化的?

  • Vue 通过把数组的原生方法重写了
  1. 获取原生数组的原型方法,因为拦截后才能对数组添加拦截操作
  2. 对数组的原型方法使用 Object.defineProperty() 做一些拦截操作
  3. 把需要被拦截的数组类型的数据原型指向改造后的原型方法
const arrayProto = Array.prototype // 获取Array的原型

function def (obj, key) {
    Object.defineProperty(obj, key, {
        enumerable: true,
        configurable: true,
        value: function(...args) {
            console.log(key); // 控制台输出 push
            console.log(args); // 控制台输出 [Array(2), 7, "hello!"]

            // 获取原生的方法
            let original = arrayProto[key];
            // 将开发者的参数传给原生的方法,保证数组按照开发者的想法被改变
            const result = original.apply(this, args);

            // do something 比如通知Vue视图进行更新
            console.log('我的数据被改变了,视图该更新啦');
            this.text = 'hello Vue';
            return result;
        }
    });
}

// 新的原型
let obj = {
    push() {}
}

// 重写赋值
def(obj, 'push');

let arr = [0];

// 原型的指向重写
arr.__proto__ = obj;

// 执行push
arr.push([1, 2], 7, 'hello!');
console.log(arr);

3.vue 为什么不能检测数组变动?

  • 通常情况下,vue 通过对每一个键设置 getter/setter 来实现响应式,没有对数组的每个键设置响应式,而是直接对值递归设置响应式。主要考虑到性能问题。

4.canvas 生成图片模糊问题?

  • 没有使用整数坐标:可使用 Math.floor 将坐标强制转换为整数。
  • 线条宽度设置的太小,可将 lineWidth 设置为整数值

5.vue 的数据劫持?

  • Vue2:
  • 使用 Object.defineProperty() 的 getter/setter
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Vue2数据劫持Demo</title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
        <div id="app">
    <!-- 在这个demo中,我们首先创建了一个Vue实例,然后在mounted钩子函数中,遍历data对象的所有属性,并使用defineReactive方法来对每个属性进行数据劫持。在defineReactive方法中,我们使用Object.defineProperty方法来重新定义属性的set和get方法。在set方法中,我们实现了自己的逻辑,例如在属性变化时强制更新视图。
    接下来,我们在页面中展示了data中的一个属性message,并提供了一个按钮,点击按钮时会修改message属性的值。当message属性发生变化时,会触发我们自定义的set方法,从而实现了数据的响应式更新。
    需要注意的是,在这个demo中我们使用了Vue的forceUpdate方法来强制更新视图。这个方法会强制vue 重新渲染视图,从而显示最新的数据。虽然这个方法可以解决数据更新不及时的问题,但是它会导致性能上的一些损失。因此,在实际开发中,我们应该尽量减少使用
    forceUpdate方法,而是通过合理的设计数据结构来避免这个问题。 -->
            <p>{{ message }}</p>
            <button @click="changeMessage">Change Message</button>
        </div>
        <script>
            var vm = new Vue({
                el: "#app",
                data: {
                    message: "Hello world!",
                },
                mounted: function () {
                    var self = this;
                    Object.keys(this.$data).forEach(function (key) {
                        self.defineReactive(self.$data, key, self.$data[key]);
                    });
                },
                methods: {
                    defineReactive: function (obj, key, val) {
                        var self = this;
                        Object.defineProperty(obj, key, {
                            get: function () {
                                console.log("get " + key + ": " + val);
                                return val;
                            },
                            set: function (newVal) {
                                console.log("set " + key + ": " + newVal);
                                val = newVal;
                                self.$forceUpdate(); // 强制更新视图
                            },
                        });
                    },
                    changeMessage: function () {
                        this.message = "Hello Vue!";
                    },
                },
            });
        </script>
    </body>
</html>
  • Vue3:
  • 使用 proxy 来实现数据劫持
  1. proxy 可直接监听数组的修改
  2. proxy 可直接监听属性的新增和删除
  3. 在实现深层次监听的时候,不是一次性递归所有的属性为其添加监听,而是只有在数据对象属性被访问的时候才会添加
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Vue3数据劫持Demo</title>
        <script src="https://unpkg.com/vue@next"></script>
    </head>
    <body>
        <div id="app">
<!-- 在这个demo中,我们首先创建了一个data对象,其中包含一个属性message。然后,我们使用Proxy方法创建了一个名为reactiveData的代理对象,并在set方法中添加了自定义的逻辑。在这个demo中,我们只是简单地在控制台中输出了一些调试信息,但是在实际开发中,我们可以在set方法中添加任何我们需要执行的逻辑,例如更新视图或向服务器发送请求等。
接下来,我们使用Vue.createApp方法创建了一个Vue实例,并将reactiveData对象作为data选项传递给它。这样,我们就实现了对data对象中属性的监听。在页面中展示了data中的一个属性message,并提供了一个按钮,点击按钮时会修改message属性的值。当message属性发生变化时,会触发我们自定义的set方法,从而实现了数据的响应式更新。
需要注意的是,在这个demo中我们没有使用$forceUpdate方法来强制更新视图。这是因为Vue3中的数据响应式系统已经得到了优化,并且可以更好地处理数据更新的问题,因此我们不再需要手动强制更新视图。 -->
            <p>{{ message }}</p>
            <button @click="changeMessage">Change Message</button>
        </div>
        <script>
            const data = {
                message: "Hello world!",
            };
            const reactiveData = new Proxy(data, {
                set(target, key, value) {
                    console.log(`set \${key}: \${value}`);
                    target[key] = value;
                    return true;
                },
            });
            const app = Vue.createApp({
                data() {
                    return reactiveData;
                },
                methods: {
                    changeMessage() {
                        this.message = "Hello Vue!";
                    },
                },
            });
            app.mount("#app");
        </script>
    </body>
</html>

6.给定一个对象数组,如何根据另一个对象数组对另一个去重?

  • 可使用 filter 方法结合 map 和 includes 方法来实现根据另一个对象数组去重操作
let originalArr = [{name: 'John', age: 26}, {name: 'Mary', age: 22}, {name: 'Peter', age: 28}];
let filterArr = [{name: 'John', age: 26}, {name: 'Bob', age: 25}];

let filteredOriginalArr = originalArr.filter((obj) => {
  return !filterArr.map((item) => item.name).includes(obj.name);
});

console.log(filteredOriginalArr); // Output: [{name: 'Mary', age: 22}, {name: 'Peter', age: 28}]
// originalArr 表示要被筛选的对象数组
// filterArr 则是用来进行筛选的参照数组
// filter 方法将会按条件对 originalArr 进行筛选,并返回结果存储在 filteredOriginalArr 中。

特殊字符描述:

  1. 问题标注 Q:(question)
  2. 答案标注 R:(result)
  3. 注意事项标准:A:(attention matters)
  4. 详情描述标注:D:(detail info)
  5. 总结标注:S:(summary)
  6. 分析标注:Ana:(analysis)
  7. 提示标注:T:(tips)

往期推荐:

最后:

  • 欢迎关注 『前端进阶圈』 公众号 ,一起探索学习前端技术......

标签:面试题,Vue,obj,key,前端,热乎,Object,数组,name
From: https://blog.51cto.com/u_14399386/6192364

相关文章

  • 前端基础之JavaScript
    目录JS简介JS基础变量与常量基本数据类型数值(number)字符串的常用方法对象的常用方法forEach()splice()map()运算符流程控制函数内置对象JS简介全称JavaScript但是与Java一毛钱关系都没有之所以这么叫是为了蹭Java的热度它是一门前端工程师的编程语言但是它本身有很多逻辑错误(......
  • 个人部署【未实现Nginx前端资源部署】
    【未在Nginx上实现静态资源部署】虚拟机A作为服务器A:安装Nginx、安装Mysql作为主库虚拟机B作为服务器B:安装能采用shell脚本部署项目所需软件:jdkgitmavenjar、安装Mysql作为从库、安装Redis作为缓存。服务器B操作:第一步:使用gitclone命令将远程仓库的代码克隆下来第二步:上......
  • 前端pdf一次下载多个echarts图表
    //需下载pdf,html2canvas模块savePDF:function(){letobj1=document.getElementById("pieChart");letobj2=document.getElementById("homepage-bandwidth-container");letobj3=document.getElementById("homepage-iops-container");le......
  • #yyds干货盘点# LeetCode面试题:最小覆盖子串
    1.简述:给你一个字符串s、一个字符串t。返回s中涵盖t所有字符的最小子串。如果s中不存在涵盖t所有字符的子串,则返回空字符串""。 注意:对于t中重复字符,我们寻找的子字符串中该字符数量必须不少于t中该字符数量。如果s中存在这样的子串,我们保证它是唯一的答案。......
  • ajax面试题总结
    转载请注明出处:1.ajax异步和同步的区别Ajax是一种基于JavaScript语言和XMLHttpRequest对象的异步数据传输技术,通过它可以使不用刷新整个页面的情况下,对页面进行部分更新。同步和异步是指客户端发送请求时,主线程是否会阻塞等待服务器的响应返回。同步请求在发送请......
  • jvm面试题 一般有用 看1
                  ......
  • 前端CSS
    目录CSS介绍CSS语法CSS实例CSS注释学习css的步骤CSS的几种引入方式行内样式内部样式外部样式CSS选择器基本选择器id选择器类选择器标签选择器通用选择器组合选择器后代选择器儿子选择器毗邻选择器弟弟选择器属性选择器分组和嵌套分组嵌套伪类选择器伪元素选择器first-letterbefore......
  • 前端常用/不常用插件【想起来才会去更新】
    maptalks支持2d/3d地图渲染及操作,maptalks可支持1w左右图形渲染(再多了就会有一点点卡,和电脑性能也有关系)官网:www.maptalks.org 组件中的组件maptalks.three:可支持three及一些简单数据样式,具体的还没用过maptalks.snap:绘制图形可贴边操作maptalks.arcgistilelayerarcgis......
  • Web前端资源
    招聘要求前端工程师:1.熟练掌握HTML5、CSS3、JavaScript,Ajax,跨域等基础知识;2.熟练掌握VUE开发框架,熟悉ElementUI、Vant等UI框架的使用;3.掌握项目版本控制工具Git的使用;4.有APICloud开发经验更佳;Web前端画图招聘要求:1.熟练掌握ECharts画图功能,包括曲线图、热力图以......
  • 字节前端青训营笔记1.计算机网络
    数据交换方式分为电路交换与分组交换电路交换是指在通信时建立一条专用的物理连接,该连接将一直保持开放,直到通信结束。在此过程中,通信双方可以实时地交换信息,就好像它们直接连接在一起一样。传统的电话通信就是一个很好的例子。在电路交换中,通信资源一直被占用,因此当通信量很......