无声静候 2022-05-04 13:55:44
说一下我个人理解,先说结论,可以使用
事件代理作用主要是 2 个
- 将事件处理程序代理到父节点,减少内存占用率
- 动态生成子节点时能自动绑定事件处理程序到父节点
这里我生成了十万个 span 节点,通过 performance monitor 来监控内存占用率和事件监听器的数量,对比以下 3 种情况
- 不使用事件代理,每个 span 节点绑定一个 click 事件,并指向同一个事件处理程序
<div> <span v-for="(item,index) of 100000" :key="index" @click="handleClick"> {{item}} </span> </div>
- 不使用事件代理,每个 span 节点绑定一个 click 事件,并指向不同的事件处理程序
<div> <span v-for="(item,index) of 100000" :key="index" @click="function () {}"> {{item}} </span> </div>
- 使用事件代理
<div @click="handleClick"> <span v-for="(item,index) of 100000" :key="index"> {{item}} </span> </div>
可以看到使用事件代理无论是监听器数量和内存占用率都比前两者要少
同时对比 3 个图中监听器的数量以及我以往阅读 vue 源码的过程中,并没有发现 vue 会自动做事件代理,但是一般给 v-for 绑定事件时,都会让节点指向同一个事件处理程序(第二种情况可以运行,但是 eslint 会警告),一定程度上比每生成一个节点都绑定一个不同的事件处理程序性能好,但是监听器的数量仍不会变,所以使用事件代理会更好一点
上面有回答说react/vue框架已经帮我们实现了统一的事件代理,为何说这里的第1,2种写法属于非事件代理(vue中)?
无声静候 2022-05-04 13:54:13
promise里用try cath的你们不觉得诡异的么
无声静候 2022-05-04 09:58:22
let list = [{ id: '1', children: [{ id: '11', children: [{ id: '111' }, { id: '112' }] }] }]; function fn(value) { // 回溯的标记 let _p = Symbol('parent'); // 找到子节点 let result; function _fn(arr, p) { for (let i = 0; i < arr.length; i++) { arr[i][_p] = p; if (arr[i].id === value) { result = arr[i]; return; } !result && arr[i].children && _fn(arr[i].children, arr[i]) } if (result) return; } _fn(list, null); let tmp = []; if (!result) return null; while (result) { tmp.unshift(result.id); result = result[_p]; } return tmp; }
思路是找到子节点,再回溯找父节点
复杂度是O(n),循环n次子节点,但是需要额外空间记录父节点引用
- 共 1 页
- 1
1.IIFE中的函数是一个函数表达式,不是函数声明。
区分函数声明和表达式最简单的方法是看function关键字出现在声明中的位置(不仅仅是一行代码,而是整个声明中的位置)。如果function是声明中的第一个词,那么就是一个函数声明,否则就是一个函数表达式。比如这里的第一个词是"(",不是function,所有这里的函数是一个函数表达式。
2.函数声明中的的函数名被绑定在它声明所在的作用域中。函数表达式中的函数名被绑定在函数自身的函数体中。
在IIFE中的函数名不会污染外部作用域。
这里函数名"b"只在函数内部有效,它是函数内部的局部变量。
3.在函数表达式的内部只能通过函数名访问该函数,但是不能通过函数名对该函数重新赋值
第 33 题:下面的代码打印什么内容,为什么?