首页 > 系统相关 >第4章 —— 变量、作用域与内存

第4章 —— 变量、作用域与内存

时间:2023-03-26 15:23:51浏览次数:40  
标签:变量 作用域 对象 引用 上下文 内存

4.1 原始值和引用值

原始值是最简单的数据,引用值是存储在内存中的对象。保存原始值的变量是按值访问的,引用值的变量是按引用访问的。

区别:

  • 原始值大小固定,保存在栈内存上;引用值是对象,保存在堆内存上。
  • 原始值不能添加属性,只有引用值可以动态添加属性。
  • 原始值的初始化可以只使用字面量形式;如果使用new,会创建一个对象的实例。
  • 原始值的复制会被复制到新的位置;引用值复制的是一个指针,与原来的指针指向内存中的同一个对象。

相同点:

  • 传递参数时都是按值传递!

  对引用值来说可以理解为在函数内部复制了一个指向原对象的指针,不影响函数外部原指针的指向。

  Ps:按值传递指外部的值会被复制到一个局部变量;按引用传递指值在内存中的位置会被保存在在一个局部变量,对本地变量的修改会反映到函数外部。

那么如何确定值的类型呢?

Typeof可以很好得判断值为原始类型还是引用类型,但他有两个缺点:

  1. typeof null === ‘object’
  2. 不能很好的判断时什么类型的对象

  基于上述缺点,ECMAScript提供了intanceof操作符,可以使变量沿着原型链查找自己是哪个具体类型的实例。

  哦对,typeof function === ‘function’,这是因为ECMA-262中规定,任何实现内部[[Call]]方法的对象都应该返回‘function’。

4.2 执行上下文和作用域

4.2.1 定义

上下文决定当前函数可以访问到哪些数据,每一个上下文都对应着一个变量对象,这个上下文中所定义的所有函数和变量都保存在这个对象上。

全局上下文对应的全局对象,也就是我们常说的window对象,所以我们定义的全局变量和函数,都是window对象的属性和方法。

当上下文中的代码在执行时,会创建变量对象的一个作用域链,它决定着代码在访问变量和方法时的顺序

代码正在执行的上下文对应的变量对象就是当前的活动对象,活动对象最初只有arguments一个变量(window对象没有)。

作用域链的最前端是当前执行上下文所对应的变量对象,下一个对象则是来自包含上下文,以此类推,直至全局上下文;作用域链的最后一个对象就是全局对象。

4.2.2 作用域链增强

指代码在执行到某些语句时,会在作用域链前端临时新增一个变量对象,在语句执行后该变量会被删除。

这类语句包括:try/catch中的catch语句和with语句。

相当于执行到这些语句时,语句内部自己独立成了一个上下文,从外部无法访问里面的变量和方法。

4.2.3 变量声明

创建上下文后,首先先为上下文对应的变量对象设置属性,也就是先看声明了哪些变量或函数,设置的顺序如下:

  1. 先创建arguments对象,并根据传入的实参为arguments对象设置属性和属性值;如果没有传入实参,则属性值为undefined;
  2. 执行所有函数声明,如果函数名与arguments属性有所冲突,则会覆盖arguments;
  3.  执行所有变量声明,如果与arguments有所冲突,则忽略该声明;
  4. 所有的var语句都放到最前面声明,至于var函数和var变量,规则和2、3一样;
  5. 只有arguments对象会在初始时复制,其他在声明后都赋值为undefined,到执行时,也就是变为活动对象时才能访问具体的属性值。

4.3 垃圾回收

JS垃圾回收主要用到两种回收策略:标记清除和引用计数。

标记清除:首先会标记内存中的所有变量,然后将还在执行上下文中的变量的标记去掉,清除掉还带有标记的变量。

引用计数:声明变量时给变量赋一个引用值为1,之后有将它赋给其他变量时,它的引用数+1,被覆盖时引用数-1。但会出现循环引用问题,导致大量内存没有被释放,甚至出现内存泄漏的问题。

4.4 内存管理与泄漏

内存优化方式:

  1. 手动解除引用,把不再使用的变量设为null,下一次垃圾清理时就会把它清除掉;
  2. 使用const和let,这个在块作用域比函数作用域早终止时有用;
  3. 浏览器会用隐藏类,可以利用此特性先创建再补充

内存泄漏:

内存泄漏是指不再使用的内存最终却未能释放,造成的原因主要有以下几种:

  1. 没有声明直接赋值,则变量变为一个全局变量;
  2. 错误的使用闭包;
  3. 定时器没有取消;
  4. DOM清空或删除后,事件未清除。

 

之前其实已经有很详细地看过这一章,但今天再看有发现了很多之前没有注意到的小细节,比如隐藏类这种,特别是这次才弄懂内存泄露到底是什么意思!

之前一直以为内存泄漏是安全问题,指其他人可以从外部访问变量,这次再看才知道指的竟然是内存占用。

标签:变量,作用域,对象,引用,上下文,内存
From: https://www.cnblogs.com/ivy225/p/17258735.html

相关文章

  • java----内存模型
    内存模型一个对象的内存图方法区开始运行,先找到Main函数,然后将这个方法入栈.new将会在堆空间中开辟空间,里面有成员变量和成员方法(注意,成员方法保存的是方法区的成员......
  • jvm内存模型
    jvm-内存模型1.内存模型JVM内存参数设置堆-Xms表示java虚拟机堆区内存初始内存分配的大小-Xmx表示java虚拟机堆区内存可被分配的最大上限新生区-Xmn表示java虚拟机年......
  • jvm-内存调优
    jvm-内存调优1.jvm内置命令jps列出正在运行的jvm虚拟机进程,并显示虚拟机执行朱磊名称以及这些进程的本地虚拟机唯一ID-q:仅输出进程id-m:输出main方法的参数-l:输......
  • Javascript之V8内存和垃圾回收讲解
    目录1Javascript内存1.1Javascript引擎1.2V8内存模型1.2.1栈1.2.2堆1.3内存生命周期1.3.1栈内对象生命周期1.3.2堆内对象生命周期2Javascript垃圾回收2.1引言2.2......
  • 类加载内存分析
    packageedu.wtbu;publicclassDemo01{publicstaticvoidmain(String[]args){Aa=newA();System.out.println(A.m);/*1.加......
  • 多线程操作共享资源(如全局变量)原理
    CPU对变量的计算分为三个步骤:1.从内存读取变量到寄存器(如add寄存器)2.将读取到的变量进行计算3.将寄存器中计算的值写入内存 如有两个线程(线程1和线程......
  • vue.js客服系统实时聊天项目开发(一)路由与子路由-全局变量-elementui搭建基本框架
    Vue应用程序设置一些基本配置,包括使用依赖项,设置路由,挂载组件等。这样就可以使用Vue框架开发应用程序了先来看看我的客服系统项目的package.json{"name":"VueLiveChat",......
  • 《内存泄漏检测工具》目录
    本篇为随笔《内存泄漏检测工具》的目录A篇VisualLeakDetectorA.1【VisualLeakDetector】简介A.2【VisualLeakDetector】安装VLDA.3【VisualLeakDetecto......
  • Linux安装JDK1.8并配置环境变量
    @目录一、下载JDK安装包二、安装JDK三、配置环境变量四、验证JDK是否安装成功Hello,大家好!今天分享Linux安装配置JDK1.8教程,本教程是学长在项目上线时撰写的,经过生产环境......
  • Linux系统下安装conda环境变量设置
    安装好conda后,设置环境变量vim~/.bashrc添加aliasliuzhenPython='/home/riki/anaconda3/bin/python'exportPATH="/home/riki/anaconda3/bin:$PATH"然后sources......