JS笔试手撕题

2024-05-09 15:28
文章标签 笔试 js 撕题

本文主要是介绍JS笔试手撕题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

数据劫持

Vue2的Object.defineProperty()

Vue2的响应式是通过Object.defineProperty()拦截数据,将数据转换成getter/setter的形式,在访问数据的时候调用getter函数,在修改数据的时候调用setter函数。然后利用发布-订阅模式,在数据变动时触发依赖,也即发布更新给订阅者,订阅者收到消息后进行相应的处理

描述符分为数据描述符和存取描述符,只能是其中之一,不可两者同时存在
在这里插入图片描述
configurable:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性,默认值为false。
enumerable:表示能否通过for in循环访问属性,默认值为false
//数据描述符
1.writable:表示能否修改属性的值。默认值为false。
2.value:包含这个属性的数据值。默认值为undefined。
//存取描述符
1.get:在读取属性时调用的函数,默认值是undefined
2.set:在写入属性的时候调用的函数,默认值是undefined

  <script>function defineReactive(data) {if (!data || Object.prototype.toString.call(data) !== '[object Object]')returnfor (let key in data) {let val = data[key]Object.defineProperty(data, key, {configurable: true,//可配置enumerable: true,//可枚举set: function (newval) {console.log('调用set');if (newval === val) {return ;}console.log('属性值发生变化');val = newval},get() {console.log('调用get');return val},})if (typeof val === 'object') {defineReactive(val)}}}const data = {name: 'better',firends: ['1', '2']}defineReactive(data)console.log('data.friends[0]:', data.firends[0]);console.log('data.name:', data.name);data.name = 'lihua'console.log('更改后的data.name:', data.name);data.friends[0] = '100'// 在JavaScript中,数组是一种特殊的对象,因此直接对数组进行defineProperty并不能监听数组元素的变化。// 当我们尝试修改数组元素时,比如data.friends[0] = 100,实际上并不会触发set函数,也就无法实现数组元素的响应式更新。console.log('更改后的data.friends[0]:', data.firends[0]);</script>

在这里插入图片描述
弊端:
1.无法劫持对象的添加和删除操作,Vue2的解决方法(新增set和delete)
2.无法劫持到数组的api(push、pop…),Vue2的解决方法是重写数组的api
3.存在深层嵌套关系,通过无脑递归,但也会劫持到项目始终都不会用到的对象,造成性能损耗

Vue3的proxy(解决vue2响应式的弊端)

Proxy(代理):用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。
Reflect(反射):对源对象的属性进行操作

Vue3基于ES6新增的Proxy对象实现数据代理以及通过Reflect对源数据进行操作,它解决了Vue2中无法追踪数据新增或删除属性的问题。另外,Proxy可以直接监听数组,无需像Vue2响应式那样需要重写数组方法进行拦截

proxy详解

const p = new Proxy(target, handler)
//target:要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。
//handler:一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为。
 <script>function isObject(obj) {if (typeof obj !== "object" || !obj) {return false;}return true;}// vue3使用reactive定义响应式对象时返回的就是reactive的实例function reactive(obj) {// 对整个对象进行劫持return new Proxy(obj, {get(target, key) {console.log('get:', key);// proxy想要监听深层对象也需要进行递归处理,不过这里用懒加载,用不到的属性不用进行深层监听let res = Reflect.get(target, key)return isObject(res) ? reactive(res) : res;},set(target, key, value) {console.log('set:', key, value);return Reflect.set(target, key, value)},deleteProperty(target, key) {console.log('delete', key);return Reflect.deleteProperty(target, key)}})}let person = reactive({ name: 'zs', age: 18, job: { code: "前端" } })console.log('person.name:', person.name);// 直接对proxy实例操作person.name = '小张'console.log('------------');person.gender = '男'delete person.ageconsole.log('------------');console.log('测试对数组的监听');//数组的push方法,作为push的属性理应也该被劫持到let arr = reactive([1, 2, 3, 4, 5])arr.push(11)console.log('--------------------');console.log('对深层对象的测试');console.log('person.job.code:', person.job.code);person.job.code = "php"</script>

在这里插入图片描述

总结
优点

1.Proxy直接劫持整个对象,并返回一个新对象,我们可以只操作新的对象达到响应式的目的
2.Proxy可以直接监听数组的变化(push,shift,splice…)
3.Proxy有多达13中拦截方法,不限于apply、ownKeys、deleteProperty、has等等,这是Object.defineProperty所不具备的
4.Proxy懒加载,解决递归造成的性能问题

缺点

Proxy不兼容IE

闭包

 <script>function fn1() {debugger;let num = 999;function innerFn1() {debugger;console.log(num);}innerFn1()}fn1()</script>

在这里插入图片描述
函数依赖外部变量就形成闭包
在这里插入图片描述

闭包的应用场景

函数内部return出去一个函数,就是结合了闭包的应用场景之一,目的是为了让那个闭包持久化

    <script>function fn1() {debugger;let num = 999;function innerFn1() {debugger;console.log(num);}return innerFn1}let closure1=fn1();//闭包 num:999// 两个不同的闭包,因此闭包可以解决全局变量命名冲突问题let closure2=fn1();//闭包 num:999</script>
<script>// 面试题function fn3(a, b) {console.log('第二个参数的值是:', b);return {innerFn: function (c) {return fn3(c, a);}}}// 链式调用fn3(1).innerFn(2).innerFn(3).innerFn(4)// 1.外部调用 传递a:1 返回一个对象 形成闭包 (a:1)=>输出undefined// 2.传递c:2 执行函数,并返回一个对象  fn3(c,a) (c:2,a:1)=>输出1// 3.外部a:2,b:1,返回一个对象(a:2)// 4.参数c:3,执行fn(3,2)   外部:(a:3,b:2)=>输出2// 5.闭包(a:3)</script>

在这里插入图片描述

        // 面试题function fn(a, b) {debuggerconsole.log('第二个参数的值是:', b);return {//对象中的函数形成一个闭包fn: function (c) {debuggerreturn fn(c, a)}}}let obj = fn(1)// 一个新对象有一个闭包=>1个// 访问的都是同一个闭包obj.fn(2)obj.fn(3)obj.fn(4)

在这里插入图片描述

 <script>// 面试题function fn(a, b) {debuggerconsole.log('第二个参数的值是:', b);return {//对象中的函数形成一个闭包fn: function (c) {debuggerreturn fn(c, a)}}}// let obj = fn(1)// // 一个新对象有一个闭包=>1个// // 访问的都是同一个闭包// obj.fn(2)// obj.fn(3)// obj.fn(4)console.log('----------------');let a = fn(1).fn(2)a.fn(3).fn(4)a.fn(5).fn(6)</script>

在这里插入图片描述

这篇关于JS笔试手撕题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/973765

相关文章

使用Python获取JS加载的数据的多种实现方法

《使用Python获取JS加载的数据的多种实现方法》在当今的互联网时代,网页数据的动态加载已经成为一种常见的技术手段,许多现代网站通过JavaScript(JS)动态加载内容,这使得传统的静态网页爬取... 目录引言一、动态 网页与js加载数据的原理二、python爬取JS加载数据的方法(一)分析网络请求1

VSCode中配置node.js的实现示例

《VSCode中配置node.js的实现示例》本文主要介绍了VSCode中配置node.js的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着... 目录一.node.js下载安装教程二.配置npm三.配置环境变量四.VSCode配置五.心得一.no

JS+HTML实现在线图片水印添加工具

《JS+HTML实现在线图片水印添加工具》在社交媒体和内容创作日益频繁的今天,如何保护原创内容、展示品牌身份成了一个不得不面对的问题,本文将实现一个完全基于HTML+CSS构建的现代化图片水印在线工具... 目录概述功能亮点使用方法技术解析延伸思考运行效果项目源码下载总结概述在社交媒体和内容创作日益频繁的

Node.js 数据库 CRUD 项目示例详解(完美解决方案)

《Node.js数据库CRUD项目示例详解(完美解决方案)》:本文主要介绍Node.js数据库CRUD项目示例详解(完美解决方案),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考... 目录项目结构1. 初始化项目2. 配置数据库连接 (config/db.js)3. 创建模型 (models/

使用Node.js制作图片上传服务的详细教程

《使用Node.js制作图片上传服务的详细教程》在现代Web应用开发中,图片上传是一项常见且重要的功能,借助Node.js强大的生态系统,我们可以轻松搭建高效的图片上传服务,本文将深入探讨如何使用No... 目录准备工作搭建 Express 服务器配置 multer 进行图片上传处理图片上传请求完整代码示例

用js控制视频播放进度基本示例代码

《用js控制视频播放进度基本示例代码》写前端的时候,很多的时候是需要支持要网页视频播放的功能,下面这篇文章主要给大家介绍了关于用js控制视频播放进度的相关资料,文中通过代码介绍的非常详细,需要的朋友可... 目录前言html部分:JavaScript部分:注意:总结前言在javascript中控制视频播放

Node.js net模块的使用示例

《Node.jsnet模块的使用示例》本文主要介绍了Node.jsnet模块的使用示例,net模块支持TCP通信,处理TCP连接和数据传输,具有一定的参考价值,感兴趣的可以了解一下... 目录简介引入 net 模块核心概念TCP (传输控制协议)Socket服务器TCP 服务器创建基本服务器服务器配置选项服

mac安装nvm(node.js)多版本管理实践步骤

《mac安装nvm(node.js)多版本管理实践步骤》:本文主要介绍mac安装nvm(node.js)多版本管理的相关资料,NVM是一个用于管理多个Node.js版本的命令行工具,它允许开发者在... 目录NVM功能简介MAC安装实践一、下载nvm二、安装nvm三、安装node.js总结NVM功能简介N

前端原生js实现拖拽排课效果实例

《前端原生js实现拖拽排课效果实例》:本文主要介绍如何实现一个简单的课程表拖拽功能,通过HTML、CSS和JavaScript的配合,我们实现了课程项的拖拽、放置和显示功能,文中通过实例代码介绍的... 目录1. 效果展示2. 效果分析2.1 关键点2.2 实现方法3. 代码实现3.1 html部分3.2

JS 实现复制到剪贴板的几种方式小结

《JS实现复制到剪贴板的几种方式小结》本文主要介绍了JS实现复制到剪贴板的几种方式小结,包括ClipboardAPI和document.execCommand这两种方法,具有一定的参考价值,感兴趣的... 目录一、Clipboard API相关属性方法二、document.execCommand优点:缺点: