华为od 面试八股文_前端_03_含答案 忘是亡心i 2024-04-20 14:11 71阅读 0赞 **目录** 1:如何避免回流与重绘? 2:如何优化动画? 3:documentFragment 是什么?用它跟直接操作 DOM 的区别是什么? 4:聊聊你对节流与防抖的理解 5:实现下节流函数和防抖函数 6:JavaScript有哪些数据类型,它们的区别? 7:null和undefined区别 8:let、const、var的区别 9: new操作符的实现原理 10:map和Object有哪些区别? -------------------- #### 1:如何避免回流与重绘? #### **减少回流与重绘的措施:** * 操作DOM时,尽量在低层级的DOM节点进行操作 * 不要使用 `table`布局, 一个小的改动可能会使整个 `table`进行重新布局 * 使用CSS的表达式 * 不要频繁操作元素的样式,对于静态页面,可以修改类名,而不是样式。 * 使用absolute或者fixed,使元素脱离文档流,这样他们发生变化就不会影响其他元素 * 避免频繁操作DOM,可以创建一个文档片段 `documentFragment`,在它上面应用所有DOM操作,最后再把它添加到文档中 * 将元素先设置 `display: none`,操作结束后再把它显示出来。因为在display属性为none的元素上进行的DOM操作不会引发回流和重绘。 * 将DOM的多个读操作(或者写操作)放在一起,而不是读写操作穿插着写。这得益于**浏览器的渲染队列机制**。 浏览器针对页面的回流与重绘,进行了自身的优化——**渲染队列** **浏览器会将所有的回流、重绘的操作放在一个队列中,当队列中的操作到了一定的数量或者到了一定的时间间隔,浏览器就会对队列进行批处理。这样就会让多次的回流、重绘变成一次回流重绘。** 上面,将多个读操作(或者写操作)放在一起,就会等所有的读操作进入队列之后执行,这样,原本应该是触发多次回流,变成了只触发一次回流。 #### 2:如何优化动画? #### 对于如何优化动画,我们知道,一般情况下,动画需要频繁的操作DOM,就就会导致页面的性能问题,我们可以将动画的 `position`属性设置为 `absolute`或者 `fixed`,将动画脱离文档流,这样他的回流就不会影响到页面了。 #### 3:documentFragment 是什么?用它跟直接操作 DOM 的区别是什么? #### MDN中对 `documentFragment`的解释: > DocumentFragment,文档片段接口,一个没有父对象的最小文档对象。它被作为一个轻量版的 Document使用,就像标准的document一样,存储由节点(nodes)组成的文档结构。与document相比,最大的区别是DocumentFragment不是真实 DOM 树的一部分,它的变化不会触发 DOM 树的重新渲染,且不会导致性能等问题。 当我们把一个 DocumentFragment 节点插入文档树时,插入的不是 DocumentFragment 自身,而是它的所有子孙节点。在频繁的DOM操作时,我们就可以将DOM元素插入DocumentFragment,之后一次性的将所有的子孙节点插入文档中。和直接操作DOM相比,将DocumentFragment 节点插入DOM树时,不会触发页面的重绘,这样就大大提高了页面的性能。 #### 4:聊聊你对节流与防抖的理解 #### ![9e1ac7dbc82f471bad25576910d561bf.png][] * 函数防抖是指在事件被触发 n 秒后再执行回调,如果在这 n 秒内事件又被触发,则重新计时。这可以使用在一些点击请求的事件上,避免因为用户的多次点击向后端发送多次请求。 * 函数节流是指规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。节流可以使用在 scroll 函数的事件监听上,通过事件节流来降低事件调用的频率。 **防抖函数的应用场景:** * 按钮提交场景:防⽌多次提交按钮,只执⾏最后提交的⼀次 * 服务端验证场景:表单验证需要服务端配合,只执⾏⼀段连续的输⼊事件的最后⼀次,还有搜索联想词功能类似⽣存环境请⽤lodash.debounce **节流函数的适⽤场景:** * 拖拽场景:固定时间内只执⾏⼀次,防⽌超⾼频次触发位置变动 * 缩放场景:监控浏览器resize * 动画场景:避免短时间内多次触发动画引起性能问题 #### 5:实现下节流函数和防抖函数 #### function debounce(fn, wait) { var timer = null; return function() { var context = this, args = [...arguments]; // 如果此时存在定时器的话,则取消之前的定时器重新记时 if (timer) { clearTimeout(timer); timer = null; } // 设置定时器,使事件间隔指定事件后执行 timer = setTimeout(() => { fn.apply(context, args); }, wait); }; } // 时间戳版 function throttle(fn, delay) { var preTime = Date.now(); return function() { var context = this, args = [...arguments], nowTime = Date.now(); // 如果两次时间间隔超过了指定时间,则执行函数。 if (nowTime - preTime >= delay) { preTime = Date.now(); return fn.apply(context, args); } }; } // 定时器版 function throttle (fun, wait){ let timeout = null return function(){ let context = this let args = [...arguments] if(!timeout){ timeout = setTimeout(() => { fun.apply(context, args) timeout = null }, wait) } } } #### 6:JavaScript有哪些数据类型,它们的区别? #### ![c77b313e93e1408f8ffe2da74efa918b.png][] JavaScript共有八种数据类型,分别是 Undefined、Null、Boolean、Number、String、Object、Symbol、BigInt。 其中 Symbol 和 BigInt 是ES6 中新增的数据类型: * Symbol 代表创建后独一无二且不可变的数据类型,它主要是为了解决可能出现的全局变量冲突的问题。 * BigInt 是一种数字类型的数据,它可以表示任意精度格式的整数,使用 BigInt 可以安全地存储和操作大整数,即使这个数已经超出了 Number 能够表示的安全整数范围。 这些数据可以分为原始数据类型和引用数据类型: * 栈:原始数据类型(Undefined、Null、Boolean、Number、String) * 堆:引用数据类型(对象、数组和函数) 两种类型的区别在于**存储位置的不同:** * 原始数据类型直接存储在栈(stack)中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储; * 引用数据类型存储在堆(heap)中的对象,占据空间大、大小不固定。如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。 堆和栈的概念存在于数据结构和操作系统内存中,在数据结构中: * 在数据结构中,栈中数据的存取方式为先进后出。 * 堆是一个优先队列,是按优先级来进行排序的,优先级可以按照大小来规定。 在操作系统中,内存被分为栈区和堆区: * 栈区内存由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。 * 堆区内存一般由开发着分配释放,若开发者不释放,程序结束时可能由垃圾回收机制回收。 #### 7:null和undefined区别 #### 首先 Undefined 和 Null 都是基本数据类型,这两个基本数据类型分别都只有一个值,就是 undefined 和 null。 undefined 代表的含义是**未定义**,null 代表的含义是**空对象**。一般变量声明了但还没有定义的时候会返回 undefined,null主要用于赋值给一些可能会返回对象的变量,作为初始化。 undefined 在 JavaScript 中不是一个保留字,这意味着可以使用 undefined 来作为一个变量名,但是这样的做法是非常危险的,它会影响对 undefined 值的判断。我们可以通过一些方法获得安全的 undefined 值,比如说 void 0。 当对这两种类型使用 typeof 进行判断时,Null 类型化会返回 “object”,这是一个历史遗留的问题。当使用双等号对两种类型的值进行比较时会返回 true,使用三个等号时会返回 false。 #### 8:let、const、var的区别 #### **(1)块级作用域:**块作用域由 `{ }`包括,let和const具有块级作用域,var不存在块级作用域。块级作用域解决了ES5中的两个问题: * 内层变量可能覆盖外层变量 * 用来计数的循环变量泄露为全局变量 **(2)变量提升:**var存在变量提升,let和const不存在变量提升,即在变量只能在声明之后使用,否在会报错。 **(3)给全局添加属性:**浏览器的全局对象是window,Node的全局对象是global。var声明的变量为全局变量,并且会将该变量添加为全局对象的属性,但是let和const不会。 **(4)重复声明:**var声明变量时,可以重复声明变量,后声明的同名变量会覆盖之前声明的遍历。const和let不允许重复声明变量。 **(5)暂时性死区:**在使用let、const命令声明变量之前,该变量都是不可用的。这在语法上,称为暂时性死区。使用var声明的变量不存在暂时性死区。 **(6)初始值设置:**在变量声明时,var 和 let 可以不用设置初始值。而const声明变量必须设置初始值。 **(7)指针指向:**let和const都是ES6新增的用于创建变量的语法。 let创建的变量是可以更改指针指向(可以重新赋值)。但const声明的变量是不允许改变指针的指向。 <table> <thead> <tr> <th><strong>区别</strong></th> <th><strong>var</strong></th> <th><strong>let</strong></th> <th><strong>const</strong></th> </tr> </thead> <tbody> <tr> <td>是否有块级作用域</td> <td>×</td> <td>✔️</td> <td>✔️</td> </tr> <tr> <td>是否存在变量提升</td> <td>✔️</td> <td>×</td> <td>×</td> </tr> <tr> <td>是否添加全局属性</td> <td>✔️</td> <td>×</td> <td>×</td> </tr> <tr> <td>能否重复声明变量</td> <td>✔️</td> <td>×</td> <td>×</td> </tr> <tr> <td>是否存在暂时性死区</td> <td>×</td> <td>✔️</td> <td>✔️</td> </tr> <tr> <td>是否必须设置初始值</td> <td>×</td> <td>×</td> <td>✔️</td> </tr> <tr> <td>能否改变指针指向</td> <td>✔️</td> <td>✔️</td> <td>×</td> </tr> </tbody> </table> #### 9: new操作符的实现原理 #### (1)首先创建了一个新的空对象 (2)设置原型,将对象的原型设置为函数的 prototype 对象。 (3)让函数的 this 指向这个对象,执行构造函数的代码(为这个新对象添加属性) (4)判断函数的返回值类型,如果是值类型,返回创建的对象。如果是引用类型,就返回这个引用类型的对象。 #### 10:map和Object有哪些区别? #### <table> <thead> <tr> <th></th> <th>Map</th> <th>Object</th> </tr> </thead> <tbody> <tr> <td>意外的键</td> <td>Map默认情况不包含任何键,只包含显式插入的键。</td> <td>Object 有一个原型, 原型链上的键名有可能和自己在对象上的设置的键名产生冲突。</td> </tr> <tr> <td>键的类型</td> <td>Map的键可以是任意值,包括函数、对象或任意基本类型。</td> <td>Object 的键必须是 String 或是Symbol。</td> </tr> <tr> <td>键的顺序</td> <td>Map 中的 key 是有序的。因此,当迭代的时候, Map 对象以插入的顺序返回键值。</td> <td>Object 的键是无序的</td> </tr> <tr> <td>Size</td> <td>Map 的键值对个数可以轻易地通过size 属性获取</td> <td>Object 的键值对个数只能手动计算</td> </tr> <tr> <td>迭代</td> <td>Map 是 iterable 的,所以可以直接被迭代。</td> <td>迭代Object需要以某种方式获取它的键然后才能迭代。</td> </tr> <tr> <td>性能</td> <td>在频繁增删键值对的场景下表现更好。</td> <td>在频繁添加和删除键值对的场景下未作出优化。</td> </tr> </tbody> </table> [9e1ac7dbc82f471bad25576910d561bf.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/20/1b99695e7dd543b59c416639c3cdb3b7.png [c77b313e93e1408f8ffe2da74efa918b.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/20/2d4eb9b89f6f47079b664ad3427666ac.png
相关 华为od 面试八股文_Java_03_含答案 为了能让 HashMap 存取高效,尽量较少碰撞,也就是要尽量把数据分配均匀。我们上面也讲到了过了,Hash 值的范围值-2147483648 到 2147483647,... 拼搏现实的明天。/ 2024年04月20日 14:14/ 0 赞/ 96 阅读
还没有评论,来说两句吧...