当前位置: 首页 > news >正文

【JS第13期】变量、作用域、内存等问题

基本类型和引用类型

基本类型

  • 基本类型:String、Number、Boolean、undefined、null、symbol(es6)
  • 基本类型指的是简短的数据段,固定的空间大小,因此存储在栈中
  • 可以通过 typeof 判断基本类型
  • 从一个变量向另一个变量赋值时,实际上创建了一个副本

引用类型

  • 引用类型: Object
  • 引用类型指那些可能由多个值构成的对象,保存在堆中
  • 包含引用类型的变量实际上并不是对象本身,而是该对象的指针
  • 从一个变量向另一个变量赋值时,实际上复制的时指针,因此,两个不同变量都指向的同一个对象,我们通过一个变量修改对象,另一个变量的值也会改变
  • 可以通过 instanceof 判断对象是哪种引用类型(大致包括:Object、Function、Array、RegExp)
  • 所有的引用类型都是对象 如下
// 函数
fun instanceof Object // true
// 数组
arr instanceof Object // true
// 正则
reg instanceof Object // true
// 对象
obj instanceof Object // true
复制代码

执行环境及作用域

执行环境(也称作用域)定义了变量或函数有权访问的其它数据,决定了它们各自的行为。每个执行环境都有与之相关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中。虽然我们无法访问这个对象,但解析器在处理数据时会在后台使用它

  • 执行环境有全局执行环境、函数执行环境和块级作用域(es6)
  • 每次进入一个执行环境都会创建一个用于搜索变量和函数的作用域链
  • 函数执行环境除了可以访问当前作用域的变量及函数外,还可以访问它的父级、全局等变量及函数(可以说当前函数执行环境之上的整个作用域链)
  • 全局环境只能访问在全局定义的变量和函数

内存垃圾收集

js具有自动垃圾收集机制,也就是说,执行环境负责管理代码执行过程的内存。而在c或c++等语言中,需要开发人员自行处理内存

前面已经说到了,我们定义的变量、函数、对象等都是存储在栈或堆中,栈或堆其实就是在内存中分配的一部分空间。这些只有在执行阶段才会被使用,当执行完后,已经没有用了,所以,我们可以将这些占用的内存进行清理。一般实现垃圾收集的方案有2种:

标记清除

标记清除的原理是在运行时候会给存储在内存中的所有变量都加上标记。然后,它会去掉环境中的变量以及被环境中的变量引用的变量标记。而在此之后再被加上标记的变量则被视为准备删除的变量,然后通过那些标记进行内存清理工作。目前的浏览器已基本上使用的是标记清除。

引用计数

引用计数的原理是跟踪记录每一个变量值的引用次数,当声明一个变量并将值赋给该变量时,则这个引用次数加1;相反,如果该变量的值又取得了另一个值(重新赋值),则减1;当这个值的引用次数为0时,则该值没有再被使用,这样,当垃圾收集器下次运行时,就会释放那些引用次数为0的值所占的内存空间。目前,浏览器已基本上不用这种方式了,因为:循环引用同一个对象时,该值的引用次数不会为0,也就不会被清除,会导致严重的性能问题

ie中bom和dom中的对象就是使用c++以com(组件对象模型)对象的形式实现的,而com对象的垃圾回收机制采用的正是引用计数。因此,只要在ie中涉及到com对象,就会存在循环引用的问题。

为了解决这个问题,我们可以手动的将变量在不再使用的时候设置为null

ie9以上的浏览器通过将bom和dom对象转换称js对象来避免两种垃圾收集算法并存导致的问题,也清除了常见的内存泄露现象

性能问题

ie垃圾收集器是一个脚本中包含的变量超过默认的临界点时,会被触发垃圾回收机制。但当包含的变量足够多时,远远超过临界点时,则垃圾回收机制会循环调用,这样会导致性能问题。为了解决这个问题,在ie7发布的新版本中改变了这种方式,我的理解是这样的,在垃圾回收机制回收了较少的内存空间时,则这个临界点会加倍,如果回收后小于原先默认的临界点时,则将设为默认临界点

临界点可以理解为根据内存分配的空间,具体一点就是256个变量、4096个对象(或数组)字面量和数组元素或64kb的字符串。

管理内存

一旦数据不再使用,最好通过将其值设置为null来释放引用---这个做法叫做解除引用。这一做法适用于大多数全局变量和全局对象的属性。局部变量会在它们离开执行环境时自动解除引用

解除一个值的引用并不意味着自动回收该值所占用的内存,而是让值脱离执行环境,在下次垃圾收集器运行时将其回收

如有侵权,请发邮箱至wk_daxiangmubu@163.com 或留言,本人会在第一时间与您联系,谢谢!!

长按二维码关注我们,了解最新前端资讯

相关文章:

  • 在CentOS6.8下安装Docker
  • Codepen 每日精选(2018-3-25)
  • Laravel核心解读--Facades
  • 学习rsyslog总结
  • 中国电信携手 Orange Business Services 扩大战略合作 为企业提供无缝物联网体验
  • add_argument 图片路径
  • 组件化、模块化、集中式、分布式、服务化、面向服务的架构、微服务架构概念介绍...
  • spring @transactional 注解使用注意点
  • Python模块-time模块
  • Java并发编程(二)优势和风险
  • 聚焦2017中国网络安全年会
  • 电路中IC器件电压符号的解释
  • XVIII Open Cup named after E.V. Pankratiev. GP of Romania
  • 4199. [NOI2015]品酒大会【后缀数组+并查集】
  • 瞄准MSP市场风口,Bespin为企业转型保驾护航
  • 2017 前端面试准备 - 收藏集 - 掘金
  • Apache Spark Streaming 使用实例
  • C++回声服务器_9-epoll边缘触发模式版本服务器
  • css属性的继承、初识值、计算值、当前值、应用值
  • java正则表式的使用
  • LeetCode29.两数相除 JavaScript
  • Mac 鼠须管 Rime 输入法 安装五笔输入法 教程
  • pdf文件如何在线转换为jpg图片
  • Python中eval与exec的使用及区别
  • Redis提升并发能力 | 从0开始构建SpringCloud微服务(2)
  • Selenium实战教程系列(二)---元素定位
  • SpriteKit 技巧之添加背景图片
  • underscore源码剖析之整体架构
  • 爱情 北京女病人
  • 聊一聊前端的监控
  • 买一台 iPhone X,还是创建一家未来的独角兽?
  • 我与Jetbrains的这些年
  • HanLP分词命名实体提取详解
  • 翻译 | The Principles of OOD 面向对象设计原则
  • ​马来语翻译中文去哪比较好?
  • #Linux(make工具和makefile文件以及makefile语法)
  • #经典论文 异质山坡的物理模型 2 有效导水率
  • #我与Java虚拟机的故事#连载06:收获颇多的经典之作
  • $.ajax()参数及用法
  • (M)unity2D敌人的创建、人物属性设置,遇敌掉血
  • (pytorch进阶之路)CLIP模型 实现图像多模态检索任务
  • (草履虫都可以看懂的)PyQt子窗口向主窗口传递参数,主窗口接收子窗口信号、参数。
  • (七)c52学习之旅-中断
  • (转)c++ std::pair 与 std::make
  • .Net Core与存储过程(一)
  • .Net IOC框架入门之一 Unity
  • .NET 应用架构指导 V2 学习笔记(一) 软件架构的关键原则
  • .Net 应用中使用dot trace进行性能诊断
  • .Net环境下的缓存技术介绍
  • /usr/bin/perl:bad interpreter:No such file or directory 的解决办法
  • @data注解_一枚 架构师 也不会用的Lombok注解,相见恨晚
  • @ModelAttribute 注解
  • [ MSF使用实例 ] 利用永恒之蓝(MS17-010)漏洞导致windows靶机蓝屏并获取靶机权限
  • [20181219]script使用小技巧.txt
  • [BZOJ4566][HAOI2016]找相同字符(SAM)