Genzhen

Results 68 comments of Genzhen

#### 1)什么是闭包 函数执行后返回结果是一个内部函数,并被外部变量所引用,如果内部函数持有被执行函数作用域的变量,即形成了闭包。 可以在内部函数访问到外部函数作用域。使用闭包,一可以读取函数中的变量,二可以将函数中的变量存储在内存中,保护变量不被污染。而正因闭包会把函数中的变量值存储在内存中,会对内存有消耗,所以不能滥用闭包,否则会影响网页性能,造成内存泄漏。当不需要使用闭包时,要及时释放内存,可将内层函数对象的变量赋值为null。 #### 2)闭包原理 函数执行分成两个阶段(预编译阶段和执行阶段)。 - 在预编译阶段,如果发现内部函数使用了外部函数的变量,则会在内存中创建一个“闭包”对象并保存对应变量值,如果已存在“闭包”,则只需要增加对应属性值即可。 - 执行完后,函数执行上下文会被销毁,函数对“闭包”对象的引用也会被销毁,但其内部函数还持用该“闭包”的引用,所以内部函数可以继续使用“外部函数”中的变量 利用了函数作用域链的特性,一个函数内部定义的函数会将包含外部函数的活动对象添加到它的作用域链中,函数执行完毕,其执行作用域链销毁,但因内部函数的作用域链仍然在引用这个活动对象,所以其活动对象不会被销毁,直到内部函数被烧毁后才被销毁。 #### 3)优点 1. 可以从内部函数访问外部函数的作用域中的变量,且访问到的变量长期驻扎在内存中,可供之后使用 2. 避免变量污染全局 3. 把变量存到独立的作用域,作为私有成员存在 #### 4)缺点 1. 对内存消耗有负面影响。因内部函数保存了对外部变量的引用,导致无法被垃圾回收,增大内存使用量,所以使用不当会导致内存泄漏 2. 对处理速度具有负面影响。闭包的层级决定了引用的外部变量在查找时经过的作用域链长度 3. 可能获取到意外的值(captured value) ####...

> 应用场景二说错了,都会弹出 3 是因为 var 的变量提升导致 i 提升成了函数作用域的变量而不是 for 作用域内的变量。解决方法不是创建闭包而是将 var 改成 let 防止循环变量提升成函数变量。 @Genzhen 感谢提出见解 闭包可以缓存值,不被回收,也是这种场景的一种解决方案,在没有let之前,也是经常采用的

#### 1)XSS:跨站脚本攻击 就是攻击者想尽一切办法将可以执行的代码注入到网页中。 ##### 存储型(server端): - 场景:见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等。 - 攻击步骤: - i)攻击者将恶意代码提交到目标网站的数据库中 - ii)用户打开目标网站时,服务端将恶意代码从数据库中取出来,拼接在HTML中返回给浏览器 - iii)用户浏览器在收到响应后解析执行,混在其中的恶意代码也同时被执行 - iv)恶意代码窃取用户数据,并发送到指定攻击者的网站,或者冒充用户行为,调用目标网站的接口,执行恶意操作 ##### 反射型(Server端) 与存储型的区别在于,存储型的恶意代码存储在数据库中,反射型的恶意代码在URL上 - 场景:通过 URL 传递参数的功能,如网站搜索、跳转等。 - 攻击步骤: - i)攻击者构造出特殊的 URL,其中包含恶意代码。 -...

```js let input = [ { id: 1, val: "学校", parentId: null, }, { id: 2, val: "班级1", parentId: 1, }, { id: 3, val: "班级2", parentId: 1, }, {...

例如 `[{id:1, parentId: 0}, {id:2, parentId:1},{id:3, parentId:1}]` 把这个数组从顶级分类递归查找子分类,最终构建一个树状数组。结果输出如下 `[{id:1, parentId: 0,children:[{id:2, parentId:1},{id:3, parentId:1}]}]` parentId为0 的是根节点 代码实现 ```js // 输入 const tempArr = [{ id: 1, parentId: 0 }, { id:...

数组转树的其中一种,排序数组转二叉搜索树 ```js /** * function TreeNode(val) { * this.val = val; * this.left = null; * this.right = null; * } */ var sortedArrayToBST = function (nums) { if (!nums.length)...

**答案** 0 1 2 **解析** 使用`let`关键字声明变量`i`:使用`let`(和`const`)关键字声明的变量是具有块作用域的(块是`{}`之间的任何东西)。 在每次迭代期间,`i`将被创建为一个新值,并且每个值都会存在于循环内的块级作用域。 ```js // 下面代码输出什么 for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i), 1); } ``` > 答案:3 3 3,由于JavaScript中的事件执行机制,setTimeout函数真正被执行时,循环已经走完。...

> 意义不大 @lgwebdream 感谢发表自己的见解 理论的储备还是需要的,不一定每个人都知道这点知识,像在没有 let 之前 这个for 循环还是经常出现在面试题中的

```js /** * @param {string} s * @return {number} */ var lengthOfLongestSubstring = function (s) { const arr = [...s] let res = 1; let result = arr.reduce((total, cur, i,...

```js /** * 题目:字符串出现的不重复最长长度 * 整体思路: * 用一个滑动窗口装没有重复的字符,枚举字符记录最大值即可 * 对于遇到重复字符如何收缩窗口大小? * 我们可以用 map 维护字符的索引,遇到相同的字符,把左边界移动过去即可 * 挪动的过程中记录最大长度 */ var lengthOfLongestSubstring = function (s) { let map = new Map(); let i...