一篇文章带你了解JavaScript中的变量,作用域和内存问题

2023-10-27

file

作者 | Jeskson

来源 | 达达前端小酒馆

1

在JavaScript中的变量分别区分为两种:

一种为基本类型值,一种为引用类型值。

基本类型值指的是简单的数据段

引用类型值为可能由多个值组成的对象

file

引用类型的值是保存在内存中的对象,JavaScript不允许直接操作对象的内存空间,实际上操作对象的引用而不是实际对象。

file

var dada = new Object();
undefined
dada.name = "dada";
"dada"
console.log(dada.name);
VM158:1 dada
undefined

file

var da1 = "da1";
undefined
da1.age = 12;
12
console.log(da1.age);
VM272:1 undefined
undefined

基本类型的值添加属性,是不管用的,只能给引用类型的值动态地添加属性,才是有用的。

2

复制变量值

就是从一个变量向另一个变量复制 基本类型值 和 引用类型值

var da1 = 12;
var da2 = da1;

file

da1中保存的值是12,使用da1的值来初始化da2时,da2中也保存了值12,但是d2中的值12和da1中的值12是完全独立的。这两个变量可以参与任何操作互不影响。

从一个变量向另一个变量复制引用类型的值:

引用类型的值实际上是一个指针,是指向存储在堆中的一个对象,引用类型的复制,是将指向引用同一个对象,所以改变其中一个变量,另一哥变量也会受到影响。

var da3 = new Object();
var da4 = da3;

da3.name = "dada";
console.log(da4.name);

file

da3和da4指向同一个对象,da3添加name属性后,da4来访问这个属性,因为两个变量指向同一个对象,所以输出结果为dada。

3

参数传递:

在JavaScript中所有函数的参数都是按值传递的,参数按值传递的意思,和复制一样的,把函数外的值传递到函数内部。

function addNum(num){
 num = num   1;
 return num;
}
var da5 = 12;
var result = addNum(da5);
console.log(da5);
console.log(result);

file

函数addNum有一个参数num,这个参数实际为函数的局部变量。调用这个函数,变量da5作为参数被传递给了这个函数,这个变量的值为12,所以参数num为12在这个addNum()函数中使用。

function setName(obj) {
 obj.name = "dada";
}
var da6 = new Object();
setName(da6);
console.log(da6.name);

file

检测类型:

typeof操作符是用来检测一个变量是否是基本数据类型,如果变量的值为一个对象或null,那么这个typeof操作符下返回的就是object。

var da7 = "dada";
var da8 = 12;
var da9;
var da10 = null;
var da11 = new Object();

console.log(typeof da7);
console.log(typeof da8);
console.log(typeof da9);
console.log(typeof da10);
console.log(typeof da11);

file

instanceof操作符,是用来干什么的呢?判断是什么类型的对象。

// 前提先定义person
console.log(person instanceof Object);
console.log(person instanceof Array);
console.log(person instanceof RegExp);

注意,所有的引用类型的值都是Object的实例,所以检测引用类型的值和Object构造函数时,instanceof操作符都是返回true。instanceof操作符检测基本类型的值,返回的则都是false。因为instanceof检测的都是什么类型的对象。

4

作用域:

当代码在一个环境中执行时,会创建变量对象的一个作用域链,这个作用域链的用途是 保证对执行环境有权访问的多有变量和函数的有序访问。全局执行环境的变量对象都是作用域链中的最后一个对象。

标识符解析是沿着作用域链一级一级地搜索标识符的过程。

var da12 = "dada"

function changeDa(){
 if(da12 === "dada"){
  da12 = "da";
 }else{
  da12 = "da1";
 }
}

changeDa();

console.log(da12);

file

函数changeDa()的作用域链包含两个对象:

它自己的变量对象,和,全局环境的 变量对象。

它自己的 定义着的arguments对象

var da12 = "dada"

function changeDa(){
 var anotherDa = "dadada";
 
 function daDa(){
  var tempDa = anotherDa;
  anotherDa = da12;
  da12 = tempDa;
  // 可以访问 tempDa, anotherDa,da12
 }
 // 这里只能访问 da12,anotherDa
 daDa();
}
// 这里只能访问da12;
changeDa();

file

分析执行环境,有3个,一个为全局环境,一个为changeDa()的局部环境,一个为daDa()的局部环境。

全局环境中有一个变量da12,和一个函数changeDa()。

changeDa()的局部环境中有什么?

一个变量anotherDa,一个名为daDa()的函数。这个函数可以访问全局变量中的da12。

daDa()的局部环境中有什么?

一个变量tempDa,该变量只能在这个环境中访问。

无论是全局环境还是changeDa()的局部环境都无法访问tempDa。

file

file

file

为什么内部的daDa()可以访问其他两个环境中的所有变量呢?

因为那是它们两个的环境是它的父执行环境。

内部环境可以通过作用域链访问所有的外部环境,但是外部环境不能访问内部环境中的任何变量和函数,内部环境都可以向上搜索作用域链,查变量和函数名,不能向下搜索作用域链进入另一个环境。

对于daDa()函数,其中作用域链包含3个对象:

daDa()的变量对象,changeDa()的变量对象,全局变量对象。

过程:

daDa()函数的局部环境,会先开始搜索自己的变量对象中的变量和函数名,如果找不到,会向上搜索上一级的作用域链。

对于changDa()中的环境:

它包含两个对象::一为它自己的变量对象,二为全局变量对象。

即它不能访问daDa()函数的局部环境。

5

执行环境分两种:

一种为全局作用域,一种为局部作用域。

如何理解 try catch 延长了作用域链?

with语句和 try catch 都可以延长作用域链

with比较好理解,而且一般有性能问题,也不推荐用

try catch 是捕获Error对象的时候 会新开一个作用域吗?

还是说 catch的大括号内就是一个能访问到error对象的块级作用域?

try中的代码捕获到错误以后,会把异常对象推入一个可变对象并置于用域的头部,在catch代码块内部,函数的所有局部变量将会被放在第二个作用域对象中,catch中的代码执行完,会立即销毁当前作用域。

执行环境(变量对象可谓是它的衍生物)、作用域、作用域链

file

作用域:函数当前执行环境。

作用域链:执行环境产生的变量对象构成。 作用域链是保证函数在执行时能够正确访问需要的变量和函数。

作用域链最外层就是全局作用域

file

var i = 0;
function dada(){
    console.log(i);
}
undefined
dada();
VM656:3 0
undefine

在函数中是没有存在i的,但是在调用这个函数时会返回为0,这是为什么呢?这就是函数作用域链的作用。

延长一: try catch

file

file

(function(window){
   try{
       throw Error("出错误了");
   }catch(e){
      alert(e);  //alert("Error: 出错误了")
   }
   console.log(e);  //undefind
})(window);

在执行catch语句块时,JavaScript自动把其执行环境添加作用域链中,但是该语句块执行完后又自动把该执行环境(变量对象)移除。

alert(e) ==  alert("Error:出现错误");
console.log(e)  ==  undefined;

IE结果:

alert(e)  =>  alert("Error: 出错误了");   

console.log(e) =>   
object Error: 
出错误了{description: "出错误了",message: "出错误了",name: "Error"}

延长二:with

file

function da(){
    console.log(location.href); 
} 

function da(){ 
    with(location){ 
        console.log(href); 
    } 
}

两种方式是等价的:

前提是非严格模式下, 因为严格模式下不支持 with这种方式。

file

延长作用域的表现

file

什么是作用域链?

我的理解就是,根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问。

想要知道js怎么链式查找,就得先了解js的执行环境。

每个函数运行时都会产生一个执行环境,而这个执行环境怎么表示呢?

js为每一个执行环境关联了一个变量对象。环境中定义的所有变量和函数都保存在这个对象中。

没有块级作用域:

if(true) {
 var da = "dada";
}
console.log(da);

file

file

function add(num1,num2){
    var num = num1   num2;
    return num;
}
undefined
var result = add(1,2);
undefined
console.log(result);
VM962:1 3
undefined

file

向上查询:

file

var da = "dada";

function getDa(){
 var da = "dadada";
 return da;
}

console.log(getDa());

JavaScript中最常用的垃圾收集方式是标记清除,另一种不太常见的垃圾策略叫做引用计数。

基本类型值和引用类型值:

基本类型值在内存中占据固定的空间,保存在栈内存中,从一个变量向另一个变量复制基本类型的值,会创建这个值的一个副本,引用类型的值为对象,保存在堆内存中。

包含引用类型值的变量实际上包含的并不是对象本身,而是一个指向对象的指针。

typeof操作符判断的是一个值是哪种基本类型,instanceof操作符判断的是一个值是哪种引用类型。

执行环境分:

全局执行环境,函数执行环境。

每次进入一个新的执行环境时,都会创建一个用于搜索变量和函数的作用域链。

❤️ 不要忘记留下你学习的脚印 [点赞 收藏 评论]

作者Info:

【作者】:Jeskson

【原创公众号】:达达前端小酒馆。

【福利】:公众号回复 “资料” 送自学资料大礼包(进群分享,想要啥就说哈,看我有没有)!

【转载说明】:转载请说明出处,谢谢合作!~

大前端开发,定位前端开发技术栈博客,PHP后台知识点,web全栈技术领域,数据结构与算法、网络原理等通俗易懂的呈现给小伙伴。谢谢支持,承蒙厚爱!!!

若本号内容有做得不到位的地方(比如:涉及版权或其他问题),请及时联系我们进行整改即可,会在第一时间进行处理。

请点赞!因为你们的赞同/鼓励是我写作的最大动力!

欢迎关注达达的CSDN!

这是一个有质量,有态度的博客

前端技术栈

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

一篇文章带你了解JavaScript中的变量,作用域和内存问题 的相关文章

  • 吴恩达深度学习课程笔记(二):Logistic逻辑回归中损失函数(Loss Function)和成本函数(Cost Function)证明及推导

    偷个懒先上传图片吧 有需要再写文档吧 初衷只是给自己以后回顾 也希望能够帮助需要的人 吴恩达的深度学习课程看下来 目前给我的感受是大佬是真的关注我们这些底子差的人 已经讲到非常详细和细致了 连导数都讲解了还有函数的推到说明 建议像我一样学习
  • 数据结构——单链表-删除操作

    include
  • 建立客户端和服务端互连简单的聊天操作

    服务端 package JAVA API num18 socket import java io import java net ServerSocket import java net Socket import java util Ar
  • 如何提高网页的加载速度 ——DNS优化和代码优化

    1 DNS预读取 网站多个子域名 第三方CDN 百度谷歌统计 其他网站的图片等资源 DNS查找耗时 DNS预读取技术能够加快打开速度 方法是在head标签里面写上几个link标签 例如 对网站提前解析DNS 由于它是并行的 不会堵塞页面渲染
  • 数据分箱6——分箱结果进行WOE转化

    WOE的具体公式与含义请参考 特征筛选7 WOE Weight of Evidence IV值 Information Value 筛选特征 有监督筛选 WOE转化可以将分箱的阈值覆盖原有的值 一般来讲并不会改变预测精度 但是可以为可解释性
  • Softing的OPC UA C++ SDK全面升级:具有高功能性和易用性

    为支持反向连接 Reverse Connect 和访问全局发现服务器 Global Discovery Server GDS Softing的OPC UA C Software Development Kit SDK 已全面升级 OPC U
  • ARM Mali系列GPU驱动panfrost组成

    Alyssa Rosenzweig于2018年创立开源小组 通过对用户空间的3D驱动 kernel空间的ARM驱动进行逆向操作 重新构建panfrost驱动 在XDC2020会议上ARM宣布 开始接纳panfrost开源驱动并向其提供应有的
  • data-ajax=“false“

    1 概述 最近在做一个项目 由于涉及到跨平台性 所以采用了jquerymobile这个框架 在开发过程中 一开始为了图测试方便 采用了chrome浏览器来测试运行 现叙述如下问题 当在first html中 有个链接如 a href sec
  • Android TextView文字过长将后面View挤出屏幕解决方案

    前言 需求 横排两个 TextView 第一个 TextView 宽度自适应 第二个 TextView 宽度固定且跟随在 TextView 后面 第二个View可为任意View 宽度需已知 需要第一个View margin出相应宽度给第二个
  • 【写一个操作系统】3—汇编语言学习及Makefile入门

    目录 汇编代码 制作启动区程序 Makefile 今天的主要任务是通过对helloos nas核心代码汇的理解进行编语言的学习 还有就是Makefile的学习 汇编代码 主要是对上次的汇编文件helloos nas核心部分的学习 核心部分的
  • 服务器修改tomcat日志级别,远程 服务器tomcat日志监控

    远程 服务器tomcat日志监控 内容精选 换一换 MRS集群的日志保存路径为 var log Bigdata 日志分类见下表 MRS日志目录清单见下表 启用多实例功能后 如果系统管理员添加了多个HBase Hive和Spark服务的实例
  • PDManer数据库建模工具介绍

    pdmaner PDManer元数建模 是一款多操作系统开源免费的桌面版关系数据库模型建模工具 相对于PowerDesigner 他具备界面简洁美观 操作简单 上手容易等特点 支持Windows Mac Linux等操作系统 也能够支持国产
  • 寻找数列(构造+拓扑)

    寻找一个有n个整数的数列 满足下列条件 其中任意连续p个数之和是正数 其中任意连续q个数之和是负数 若无法找到 则输出 No 否则输出一个数值最小的数列 输入 n p q 输出 n个整数 样例 输入 5 4 3 输出 2 2 5 2 2 设
  • 通过BAT脚本批量修改文件名

    通过BAT脚本批量修改文件名 一 生成命名文件名列表 二 在excel中对应的行输入修改后的文件名 在这里插入图片描述 https img blog csdnimg cn 20201012102112886 png x oss proces
  • 这几天心里颇不宁静,采的不是信号,而是寂寞

    原文来自微信公众号 工程师看海 这几天心里颇不宁静 今晚在院子里坐着乘凉 忽然想起往日一同攻坚的战友 在这满月的光里 该是另一番样子吧 我们制定的uV级别信号的采集方案 从原理到模拟环境测试 一切都OK 然而真正到现场采集信号时却发现 压根
  • python获取时间日期列表集合

    python获取时间日期列表集合 以前过去以后未来 安装datedays pip install datedays import datedays if name main print 测试时间 datedays getnow print
  • python-获取当前目录/上级目录/上上级目录...

    获取文件 在其他人使用你的代码时 常常因为目录层级的问题为无法运行程序 所以在引起其他模块文件时 尽量采取绝对路径的方式导 python官方建议尽量的使用绝对目录 而不是相对目录 获取当前文件的绝对路径 os path abspath fi
  • 公式微分后,为什么是偏导的相加

    二郎在研究一个公式中 会涉及分析变量对最终结果产生影响时 注 最终结果 这里确实是最后需要获得的结果 数学公式一定要和物理对应 输入放在一边 输出放在一边 否则都放在一边 就全成自变量了 变量对最终结果影响 既然涉及了分析 那么我们就先说为
  • c++中分文件编写

    c 中分文件编写 本文内容来自某视频教程 分文件格式编写格式 h中写类的成员函数声明 cpp中写成员函数实现 代码案例 所有代码写在一个文件中 如下是一段没有分文件编写的代码 即将所有代码写在一个源文件中 如图所示 以下代码实现了利用全局函

随机推荐

  • nginx转发wss

    做了一个tp6 swoole的项目 没找到swoole开启ssl的资料 想起以前做过转发可以实现 就新建了一个站 然后转发到swoole的端口 也能实现wss的访问 下面是配置文件 upstream wss server 127 0 0 1
  • ERP、SCM、CRM的区别和联系?

    ERP 企业资源计划 SCM 供应链管理系统 CRM 客户关系管理 是当前企业信息系统三大热门话题 无论是ERP SCM 还是CRM其根本目标都在于提高企业管理水平 提高企业核心竞争力 本文怡海软件将分别从其含义 区别 联系 集成方面进行简
  • Unity Scroll View踩坑记录

    Unity要想实现游戏中的背包滑动效果 最简单的方法就是使用ScrollView这个组件 这个组件可以实现拖动滑动的效果 如上图所示 我希望将这些Item实现背包的排版效果 第一步 现将所有的Item移到Content下 此时我们会发现部分
  • Java集合——Java8之HashMap

    一 前言 在分析jdk1 8后的HashMap源码时 发现网上好多分析都是基于之前的jdk 而Java8的HashMap对之前做了较大的优化 其中最重要的一个优化就是桶中的元素不再唯一按照链表组合 也可以使用红黑树进行存储 总之 目标只有一
  • Python爬取某短视频热点

    随着短视频的大火 不仅可以给人们带来娱乐 还有热点新闻时事以及各种知识 刷短视频也逐渐成为了日常生活的一部分 本 文以一个简单的小例子 简述如何通过Pyhton依托Selenium来爬取短视频 仅供学习分享使用 如有不足之处 还请指正 涉及
  • pyspark环境安装历史难题终于解决

    path JAVA HOME里面的D JAVA 1 jdk1 8 0 152 bin一定要全并且对应上 踩坑记录 已解决 报错 WARN ProcfsMetricsGetter Exception when trying to comput
  • 基于Java的OA系统的设计与实现

    源码及论文下载 http www byamd xyz tag java 摘 要 学习和研究办公自动化中涉及到的知识和技术是实现办公自动化系统的前提条件 通过学习研究 掌握了其中的关键技术之后 结合自身的理解 对其做出了相应的表述 同时也成功
  • 【第03例】IPD体系进阶

    目录 前言 专栏目录 具体内容 IPD 相关专栏推荐 专栏列表 作者简介 前言 今天继续来讲讲 IPD 中涉及的几个评审点 ADCP 是英文 Av
  • 彻底理解coookie、session、token

    一 发展史 1 很久很久以前 web基本上就是文档的浏览而已 既然是浏览 作为服务器 不需要记录谁在某一段时间里都浏览了什么文档 每次请求都是一个新的HTTP协议 就是请求加响应 尤其是我不用记住是谁刚刚发了HTTP请求 每个请求对我来说都
  • Linux下的Oracle连接

    1 进入Oracle su oracle 2 开启监听器 oracle localhost root lsnrctl status oracle localhost root lsnrctl start oracle localhost r
  • 微信小程序自定义 tab-bar(基于 wepy)

    背景 微信小程序提供的原生 tab bar 功能简单 样式单一 无法满足业务需求 项目中使用的是 wepy 1 x 框架 实现原理与原生类似 方案 一 使用组件 在每个Tab页引入 修改全局配置 app wpy export default
  • CloudCompare--安装和简单的使用方法

    CloudCompare 安装和简单的使用方法 CloudCompare工具是一个非常好的处理点云数据的开源工具 有个不错的框架 很多公司对该工具进行二次开发以满足公司需要 第一次使用CloudCompare感觉非常好用 有兴趣的可以多了解
  • C语言进阶知识点(持续跟新)

    还是有点儿进阶的知识点 1 大段 小段内存模型 int val 0x12345678 int p1 val char p2 char p1 printf x n p2 p2 printf x n p2 short p3 val printf
  • windows server 2012 双网卡配置

    别用route 命令 在使用最新版的windows server 2012的时候 当存在两个或者多个网段的时候 就可以采用双网卡的方式来添加和配置路由 具体的设置方法如下 网段1 192 168 0 0 网段2 192 168 1 0 20
  • Go的 context 包的使用

    文章目录 背景 简介 主要方法 获得顶级上下文 当前协程上下文的操作 创建下级协程的Context 场景示例 背景 在父子协程协作过程中 父协程需要给子协程传递信息 子协程依据父协程传递的信息来决定自己的操作 这种需求下可以使用 conte
  • 337. House Robber III

    The thief has found himself a new place for his thievery again There is only one entrance to this area called the root B
  • 我们来浅谈代码语言的魅力

    01 浅谈 V8 Hidden Classes 和 Inline Caches Javascript 是动态的 基于属性链的语言 V8 是流行的 JavaScript 运行引擎 我们知道在运行时可以改变对象的属性和类型 为了定位对象的属性和
  • pb使用记录 关于pbt、pbr、pbd

    pb使用记录 关于pbl pbt pbr pbd 最近使用pb修改程序 遇到一些基础问题 之前有过了解但是几年没有碰过PB有些忘了 简单记录一下 1 关于pbl pbt pbr pbd pbt powerbuilder target 是8以
  • Java代码的静态编译和动态编译中的问题比较(1)

    Java 应用程序的性能经常成为开发社区中的讨论热点 因为该语言的设计初衷是使用解释的方式支持应用程序的可移植性目标 早期 Java 运行时所提供的性能级别远低于 C 和 C 之类的编译语言 尽管这些语言可以提供更高的性能 但是生成的代码只
  • 一篇文章带你了解JavaScript中的变量,作用域和内存问题

    作者 Jeskson 来源 达达前端小酒馆 1 在JavaScript中的变量分别区分为两种 一种为基本类型值 一种为引用类型值 基本类型值指的是简单的数据段 引用类型值为可能由多个值组成的对象 引用类型的值是保存在内存中的对象 JavaS