博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
<笔记>变量、作用域和内存问题
阅读量:6452 次
发布时间:2019-06-23

本文共 2381 字,大约阅读时间需要 7 分钟。

JavaScript 中的变量只是在特定时间保存特定值的一个名字而已

基本类型和引用类型的值

ECMAScript 中值的类型有两种 :

  • 基本数据类型的值
    • 保存在栈内存中 , 可以直接访问和操作值本身
  • 引用数据类型的值
    • 在 ECMAScript 中 , 只有一个引用类型 , 就是对象
    • 引用类型的值包含三个概念 : 对象的引用、对象、对象的内存空间
    • 当我们声明一个变量并将一个对象赋值给这个变量的时候 , 我们实际上是把这个对象的引用赋值给了这个变量并且存储在和栈内存中 , 对象的值保存在开发人员不可直接访问的堆内存中

动态的属性

  • 对于引用类型的值 , 我们可以为其添加属性和方法 , 也可以改变和删除它的属性和方法
  • 对于基本类型的值 , 不能添加属性和方法

复制变量的值

  • 对于基本类型的值 , 复制的是具体的值
  • 对于引用类型的值 , 复制的是值在堆内存中的地址 , 如果这个时候改变引用类型的值 , 那么不论是被复制的变量还是复制后的变量 , 它们的值都会发生改变

传递参数

ECMAScript 中所有函数的参数都是按值传递的 , 也就是说把函数外部的值传递给函数内部的参数 , 就和把值从一个变量复制到另一个变量是一样的

  • 函数内部的参数是一个作用域为函数本身的局部变量
  • 如果是基本类型的值 , 那就是简单地复制值本身
  • 如果是引用类型的值 , 会把值的引用传递给参数 , 如果在函数内部改变了值 , 在外部的值也会相应的发生变化
function setName(obj){        obj.name = "oswald"    }    var person = {};    setName(person);    alert(person.name);         // "oswald"复制代码

检测类型

检测基本类型的值用 typeof 操作符 , 检测引用类型的值用 instanceof 操作符

如果变量是给定引用类型的实例 , 那么 instanceof 操作符就会返回 true , 通过原型链来判断

alert(person instanceof Object);        // person 是 Object (对象) 类型的值吗    alert(person instanceof Array);         // person 是 Array (数组) 类型的值吗    alert(person instanceof RegExp);        // person 是 RegExp (正则) 类型的值吗复制代码

执行环境和作用域

执行环境是 JavaScript 中最为重要的一个概念

  • 执行环境定义了变量或函数是否有权访问其他数据 , 决定了它们各自的行为 , 每个执行环境都有一个与之关联的变量对象 , 环境中定义的所有变量和函数都保存在这个对象中 , 我们编写的代码无法访问这个对象 , 但是解析器在处理数据时会在后台使用它
  • 全局执行环境是最外围的一个执行环境 , 在 Web 浏览器中 , 全局执行环境被认为是 window 对象
  • 每个函数都有自己的执行环境
  • 当代码在一个环境中执行时 , 会创建变量对象的作用域链 , 作用域链的作用就是保证对执行环境有权访问的变量和函数的有序访问 , 作用域链的最前端永远是当前环境的变量对象
  • 如果执行环境是函数 , 则将其活动对象作为变量对象 , 活动对象一开始只包含一个变量 , 即包含函数参数的 arguments 对象 , 这个对象只存在于函数内部
  • 作用域链中的下一个变量对象来自当前环境的上一级外部环境 , 依次向上直到找到全局执行环境 , 全局执行环境的变量对象永远是作用域链的最后一个对象
  • 标识符解析就是沿着作用域链一级一级搜索标识符的过程 , 直至找到全局执行环境

没有块级作用域

ES5 中没有块级作用域 , 所有使用 var 声明的变量都会被自动添加到最近的环境中 , 在函数内部声明的变量会被添加到函数的执行环境中 , 不使用 var 声明的变量会被添加到全局环境中

查询标识符

  • 查询标识符会从作用域链的最前端 , 也就是当前执行环境开始 , 搜索与给定名字匹配的标识符 , 如果当前环境没有 , 则沿着作用域链向上查找 , 一直找到全局环境 , 如果在这个过程中找到了 , 停止查找 , 如果全局环境中也没有找到 , 表示这个变量并未声明过
  • 如果不同环境中存在同名的标识符 , 只会使用第一个找到的标识符 , 父环境中的同名标识符并不会使用

垃圾收集

JavaScript 具有自动垃圾收集机制 , 执行环境会负责管理代码执行过程中使用的内存

标记清除

  • JavaScript 中最常用的垃圾收集方式就是标记清除 , 当变量进入环境时 , 将这个变量标记为 "进入环境" , 当变量离开环境时 , 将其标记为 "离开环境"
  • 垃圾收集器会给存储在内存中的所有变量打上标记 , 他会去掉环境中的变量以及被环境中的变量引用的变量的标记 , 然后剩下被标记的变量被视为将要删除的变量 , 因为环境中的变量已经无法访问它们了 , 最后垃圾收集器会销毁带有标记的值并回收它们所占的内存空间

管理内存

  • 我们在 JavaScript 中管理内存主要是为了防止内存泄漏使运行 JavaScript 的网页占用全部系统内存导致系统崩溃
  • 优化内存占用的方法就是为代码只保存必要的数据 , 一旦数据不再需要了 , 最好通过将其值设置为 null 的方法来解除引用 , 这个做法适用于全局变量、全局对象的属性以及循环引用变量的引用 , 因为局部变量在离开执行环境时会被自动解除引用
  • 解除引用的目的是为了让值脱离执行环境 , 从而可以在垃圾收集器下次运行时将其回收

转载地址:http://eagwo.baihongyu.com/

你可能感兴趣的文章
CC_UNUSED_PARAM 宏含义的解释
查看>>
leetcode124二叉树最大路径和
查看>>
AngularJS笔记整理 内置指令与自定义指令
查看>>
学习OpenCV——BOW特征提取函数(特征点篇)
查看>>
shell与正则表达式
查看>>
第三篇:白话tornado源码之请求来了
查看>>
10分钟搞定支付宝和微信支付的各种填坑
查看>>
表示数值的字符串
查看>>
JQUERY AJAX请求
查看>>
html css 伪样式
查看>>
超级账本Fabric区块链用弹珠游戏Marbles 部署
查看>>
Maven多模块项目
查看>>
Oracle、PostgreSQL与Mysql数据写入性能对比
查看>>
整理Java基础知识--选择与判断
查看>>
Linux查看程序端口占用情况
查看>>
jar包冲突案例分析.md
查看>>
控制圈复杂度的9种重构技术总结
查看>>
当软件项目全部能靠自己搞定了,也能接几万元的软件项目时,未必适合创业...
查看>>
数据分析--数字找朋友
查看>>
推荐好用的开源库或软件
查看>>