js数据存储
闭包
内部函数总是可以访问其外部函数中声明的变量,当通过调用一个外部函数返回一个内部函数后,即使该外部函数已经执行结束,但是内部函数引用外部函数的变量依然保存在内存中,我们就把这些变量的集合称为闭包
- 形成
- 一个函数返回另一个函数,返回的函数保持了对外部函数变量的访问权
- 在一个函数内部声明的函数被调用时,它依然能够访问其外部的变量
- 优点
- 数据封装
- 模块化
- 持久化存储
- 缺点
- 内存泄漏
- 调试困难
- 性能开销
- 常见用途
- 数据隐藏:通过闭包实现私有化变量和方法
- 函数工厂:用闭包创建具有特定环境的函数实例
- 模仿块级作用域
- 引起内存泄漏的原因
- 长时间持有大对象或者DOM元素的引用,没有及时释放
- 闭包和事件监听结合在一起,但是事件监听器没有被正确的移除
- 闭包被定时器引用,但是定时器没有被正确清除
- 闭包中包含对DOM元素的引用,而DOM元素反过来包含对闭包的引用造成循环引用,内存无法被垃圾回收
function circularReference() { let element = document.getElementById('myElement'); element.someProperty = function() { console.log(element.id); }; } circularReference();
总结
闭包本身不会导致内存泄漏,但是在特定的情况下,如果闭包长时间持有大对象,DOM元素,计时器或者事件监听器的引用而这些引用没有被正确清理就会导致内存泄漏。
浏览器的渲染机制,重绘重排
- 重绘: 某些元素的外观被改变,但是位置没有改变.例如颜色,
- 重排:重新生成布局,重新排列元素例如增删Dom,改变元素尺寸,浏览器窗口尺寸发生改变,内容变化(input输入。。),计算offsetWidth , offsetHeight
重绘不一定引起重排,但是重排一定引起重绘.
总结:
重排和重绘是浏览器关键渲染路径上的两个节点, 浏览器的关键渲染路径就是 DOM 和 CSSOM 生成渲染树,然后根据渲染树通过一个布局(也叫 layout)步骤来确定页面上所有内容的大小和位置,确定布局后,将像素 绘制 (也叫 Paint)到屏幕上。
其中重排就是当元素的位置发生变动的时候,浏览器重新执行布局这个步骤,来重新确定页面上内容的大小和位置,确定完之后就会进行重新绘制到屏幕上,所以重排一定会导致重绘。
如果元素位置没有发生变动,仅仅只是样式发生变动,这个时候浏览器重新渲染的时候会跳过布局步骤,直接进入绘制步骤,这就是重绘,所以重绘不一定会导致重排。
原型和原型链
每个函数都有一个prototype属性,被称作原型
prototype原型指向一个对象,所以被称为原型对象
javascript继承机制的设计思想就是,原型对象的所有属性和方法,都能被实例对象共享。
prototype对象有一个constructor属性,默认指向prototype对象所在的构造函数
- 当访问某个对象的属性的时候,会现在这个对象本身属性上查找,如果没有找到,就去它的原型(proto)去找,即它的构造函数的prototype查找,如果没有找到,就到原型的原型上去找(构造函数的prototype.proto)。如果直到最顶层的Object.prototype还是找不到,则返回undefined。这样一层层的查找就会形成一个链式结构,这就是原型链。
- 如果对象自身和它的原型都定义了一个同名属性,那么优先读取对象自身的属性,这叫做覆盖
- 所有引用类型的proto都指向他的构造函数的prototype
- JS 在创建对象(不论是普通对象还是函数对象)的时候,都有一个叫做proto 的内置属性,用于指向创建它的构造函数的原型对象。