详解js变量、作用域及内存

10、JavaScript 变量、作用域与内存管理详解 本文详细探讨了 JavaScript 中变量类型判断、执行上下文与作用域链的机制,以及内存管理中的垃圾回收算法和优化策略。内容涵盖 typeof 和 instanceof 的使用、作用域链的结构与查找机制、标记清除和引用计数两种主要垃圾回收算法,以及内存泄漏的常见原因和优化建议。通过深入理解这些核心概念,开发者可以编写更高效、可靠的 JavaScript 代码。 阅读详情

基本类型值有:undefined,NUll,Boolean,Number和String,这些类型分别在内存中占有固定的大小空间,他们的值保存在栈空间,我们通过按值来访问的。

(1)值类型:数值、布尔值、null、undefined。
(2)引用类型:对象、数组、函数。

如果赋值的是引用类型的值,则必须在堆内存中为这个值分配空间。由于这种值的大小不固定(对象有很多属性和方法),因此不能把他们保存到栈内存中。但内存地址大小是固定的,因此可以将内存地址保存在栈内存中。

<script type="text/javascript”>
    var box = new Object();  //创建一个引用类型
    var box = "trigkit4";   //基本类型值是字符串
    box.age = 21;    //基本类型值添加属性很怪异,因为只有对象才可以添加属性。
    alert(box.age);  //不是引用类型,无法输出;
</script>

简而言之,堆内存存放引用值,栈内存存放固定类型值。“引用”是一个指向对象实际位置的指针。

在这里需注意的是,引用指向的是具体的对象,而不是另一个引用。

这里写图片描述

这里的对象可以是字符串对象,数字对象,数组对象等。

<script type="text/javascript">
    var man = new Object();//man指向了栈内存的空间地址
    man.name = "Jack";
    var man2 = man;//man2获得了man的指向地址

    alert(man2.name);//两个都弹出Jack
    alert(man.name);
</script>

复制变量值


再看下面这个例子:

<script type="text/javascript">
    var man = new Object();//man指向了栈内存的空间地址
    man.name = "Jack";
    var man2 = man;//man2获得了man的指向地址

    man2.name = "ming";//因为他们都指向同一个object,同一个name,不管修改谁,大家都修改了
    alert(man2.name);//两个都弹出ming
    alert(man.name);
</script>

传递参数


ECMAScript中,所有函数的参数都是按值传递的

<script type="text/javascript">
     function box(num){      //按值传递
         num+=10;
         return num;
     }

     var num = 10;
     var result = box(num);
     alert(result);  //如果是按引用传递,那么函数里的num会成为类似全局变量,把外面的number替换掉
     alert(num);    //也就是说,最后应该输出20(这里输出10)
</script>

js没有按引用传递的,如果存在引用传递的话,那么函数内的变量将是全局变量,在外部也可以访问。但这明显是不可能的。

去掉var的局部变量

<script type="text/javascript">
      var name = "Jack";
      function setName(){
          name = "trigkit4";   //去掉var变成了全局变量
      }

      setName();
      alert(name);//弹出trigkit4
</script>

通过传参,也是局部变量

<script type="text/javascript">
      var name = "Jack";
      function setName(name){    //通过传参,也是局部变量
          alert(name);
      }

      setName("trigkit4");//弹出trigkit4
      alert(name);//弹出Jack
</script>

函数体内还包含函数,只有这个函数才可以访问内一层的函数

<script type="text/javascript">
     var name = "Jack";
      function setName(){
          function setYear(){    //setYear()方法的作用域在setName()内
              return 21;
          }
      }
      alert(setYear());//无法访问,出错 
</script>

可以通过如下方法进行访问:

<script type="text/javascript">
     var name = "Jack";
      function setName(){
          function setYear(){    //setYear()方法的作用域在setName()内
              return 21;
          }
          return setYear();
      }
      alert(setName()); //弹出21
</script>

再一个作用域例子:

<script type="text/javascript">
     var name = "Jack";
      function setName(){
          function setYear(){    //setYear()方法的作用域在setName()内
              var b = "hi";     //变量b的作用域在setYear()内
              return 21;
          }
          alert(b);//无法访问 
      }
</script>

当代码在一个环境中执行的时候,就会形成一种叫做作用域链的东西,它的用途是保证对执行环境中有访问权限的变量和函数进行有序访问(指按照规则层次来访问),作用域链的前端,就是执行环境的变量对象。

作用域

变量没有在函数内声明或者声明的时候没有带var就是全局变量,拥有全局作用域,window对象的所有属性拥有全局作用域;在代码任何地方都可以访问,函数内部声明并且以var修饰的变量就是局部变量,只能在函数体内使用,函数的参数虽然没有使用var但仍然是局部变量。

没有块级作用域

// if语句:

<script type="text/javascript">
    if(true){                   //if语句的花括号没有作用域的功能。
        var box = "trigkit4";
    }
    alert(box);//弹出 trigkit4
</script>

for循环语句也是如此。

变量的查询

在变量的查询中,访问局部变量要比全局变量来得快,因此不需要向上搜索作用域链。 如下例子:

<script type="text/javascript">
     var name = "Jack";
      function setName(){
           var name = "trigkit4";
           return name;  //从底层向上搜索变量
    }
    alert(setName());      
</script>

每个环境都可以向上搜索作用域链,以查询变量和函数名;但任何环境都不能通过向下搜索作用域链而进入另一个执行环境。在这里,如果去掉var name = “trigkit4”,那么将弹出“Jack”

内存问题


javascript具有自动垃圾回收机制,一旦数据不再使用,可以将其设为”null”来释放引用

循环引用

一个很简单的例子:一个DOM对象被一个Javascript对象引用,与此同时又引用同一个或其它的Javascript对象,这个DOM对象可能会引发内存泄露。这个DOM对象的引用将不会在脚本停止的时候被垃圾回收器回收。要想破坏循环引用,引用DOM元素的对象或DOM对象的引用需要被赋值为null。

闭包

在闭包中引入闭包外部的变量时,当闭包结束时此对象无法被垃圾回收(GC)。

var a = function() {
  var largeStr = new Array(1000000).join('x');
  return function() {
    return largeStr;
  }
}();

DOM泄露

当原有的COM被移除时,子结点引用没有被移除则无法回收。

var select = document.querySelector;
var treeRef = select('#tree');

//在COM树中leafRef是treeFre的一个子结点
var leafRef = select('#leaf'); 
var body = select('body');

body.removeChild(treeRef);

//#tree不能被回收入,因为treeRef还在
//解决方法:
treeRef = null;

//tree还不能被回收,因为叶子结果leafRef还在
leafRef = null;

//现在#tree可以被释放了。

Timers计(定)时器泄露

定时器也是常见产生内存泄露的地方:

for (var i = 0; i < 90000; i++) {
  var buggyObject = {
    callAgain: function() {
      var ref = this;
      var val = setTimeout(function() {
        ref.callAgain();
      }, 90000);
    }
  }

  buggyObject.callAgain();
  //虽然你想回收但是timer还在
  buggyObject = null;
}

调试内存

Chrome自带的内存调试工具可以很方便地查看内存使用情况和内存泄露:
在 Timeline -> Memory 点击record即可.

10、JavaScript变量、作用域与内存管理详解 本文详解了JavaScript中变量、作用域与内存管理的核心概念,包括函数参数按值传递的机制、基本类型与对象类型的区别、typeof与instanceof的使用、执行上下文和作用域链的工作原理,以及JavaScript的垃圾回收机制。同时,文章还提供了开发中的实践建议,帮助开发者更好地理解和优化JavaScript代码,提高代码性能与稳定性。 阅读详情

相关推荐

11、JavaScript 变量、作用域、内存管理与引用类型详解

本文详细解析了JavaScript中的变量类型、作用域机制、内存管理策略以及引用类型的操作与继承方式。重点探讨了JavaScript的垃圾回收机制(如标记清除和引用计数),并提出了内存管理的最佳实践,如解除引用和避免循环引用。同时,文章深入讲解了原始值与引用值的区别、数组的常用方法、对象和数组的操作,以及通过原型链实现继承的技术。通过本文,开发者可以掌握编写高效、稳定JavaScript代码的核心知识。

pink7的博客 136

js - 数据、内存和变量

2、数据、内存和变量 2.1、什么是数据 存储在内存中代表特定的信息的东西,本质上是一串二进制组成的,如01110011… 数据的特点是:可传递(var a=2;var b=a;)、可运算(var c = a+b;) 万物皆数据,函数也是数据 内存中所有操作的目标:数据(如能进行算术、逻辑、赋值、运行函数…) // 所有的内容都是数据,只要是数据就会占用内存。 var str = "abcdefg";// 分配内存给字符串。 var obj = {};// 分配内存给对象。 var arr

weixin_46022982的博客 233

智能车学习日记【二】————十字和斜入十字

智能车学习日记【二】————十字和斜入十字 文章目录 智能车学习日记【二】————十字和斜入十字 前言 一、普通十字补线 二、斜入十字 1.判断是否为斜入十字和斜入十字类型 2.找斜入十字拐点 总结 前言 经过了一个多月的学习,小白的我终于也是能较稳定调出了2.8m以上的四轮车,过程中也遇到了很多困难,其中就有十字补线和斜入十字补线。尤其是斜入十字也是困扰了我快一周,现在和大家分享一下我处理斜入十字的方法(我的方法其实还有很多漏洞需要改进,仅供大家参考理解一下,欢迎各位在评论区指点出可

bsefef的博客 2740

JavaScript 变量、作用域及内存详解

基本类型值有:undefined,NUll,Boolean,Number和String,这些类型分别在内存中占有固定的大小空间,他们的值保存在栈空间,我们通过按值来访问的。 (1)值类型:数值、布尔值、null、undefined。 (2)引用类型:对象、数组、函数。 如果赋值的是引用类型的值,则必须在堆内存中为这个值分配空间。由于这种值的大小不固定(对象有很多属性和方法),因此不能把他们保存到栈内存中。但内存地址大小是固定的,因此可以将内存地址保存在栈内存中。 <script type="t

高先生的猫 429

ROS2实战:手把手教你用CMake集成自定义DDS(以CycloneDDS为例)

本文详细介绍了如何在ROS2中通过CMake集成自定义DDS(以CycloneDDS为例),涵盖环境准备、源码编译、ROS2工作区集成、性能调优及常见问题排查。通过RMW中间件抽象层,开发者可以灵活切换DDS实现,提升系统实时性和可靠性。

weixin_29284201的博客 347

使用DeepSeek、MCP和AKShare实现智能金融问答系统技术方案

DeepSeek是由深度求索公司开发的大规模语言模型,最新版本DeepSeek-V3采用混合专家(MoE)架构,拥有671B参数,激活37B参数,在多项基准测试中表现优异3。要使用DeepSeek的API服务:访问DeepSeek平台注册账号获取API Key(形如AKShare是基于Python的金融数据接口库,提供股票、基金、期货、宏观经济等领域的海量数据。主要特点包括:免费开源,数据源丰富支持多种数据格式(DataFrame/JSON)持续更新维护安装命令。

Kin 3174

详解 JS 变量、作用域及内存

基本类型值有:undefined,NUll,Boolean,Number和String,这些类型分别在内存中占有固定的大小空间,他们的值保存在栈空间,我们通过按值来访问的。(1)值类型:数值、布尔值、null、undefined。(2)引用类型:对象、数组、函数。如果赋值的是引用类型的值,则必须在堆内存中为这个值分配空间。由于这种值的大小不固定(对象有很多属性和方法),因...

akm55593的博客 146

springcloud教程 -- 1.快速搭建入门级demo,看这一篇就够了

废话不多讲,跟紧我,开启你的SpringCloud初体验 首先回顾微服务的基本组成: [图片 here] 生产者:提供服务 消费者:消费服务 服务注册/发现中心:服务注册,发现,监控 所以,首先明白springcloud微服务的架构基础:生产者(client),消费者(client),服务注册/发现中心(server)

叶巨岩的博客 8万+

JS变量、作用域与内存详解

垃圾回收程序运行的时候会标记内存中存储的所有变量,然后它会将所有在上下文中的变量以及被在上下文中的变量引用的变量的标记去掉。在把引用值从一个变量赋给另一个变量时,存储在变量中的值也会被复制到新变量所在的位置。ECMAScript中所有函数的参数都是按值传递的,这意味着函数外的值会被复制到函数内部的参数中,就像从一个变量复制到另一个变量一样。每个函数调用都有自己的上下文,当代码执行流进入函数时,函数的上下文被推到一个上下文栈上,在函数执行完之后,上下文栈会弹出该函数上下文,将控制权返还给之前的执行上下文。

想不出简介 1000

安装部署 Guacamole 远程桌面网关

Guacamole 是Apache基金会提供的一组基于web的远程桌面访问工具,支持 VNC、RDP、SSH、 Telnet 等协议,支持远程透传音视频。

UsamaBinLaden6976498的专栏 1963

用AG9311芯片DIY一个多功能Type-C扩展坞:从原理图到PCB布局的保姆级指南

本文详细介绍了如何利用AG9311芯片DIY多功能Type-C扩展坞,涵盖从原理图设计到PCB布局的全过程。AG9311芯片作为高性价比的Type-C控制器,支持HDMI 2.0、USB 3.0、PD快充和千兆网口,适合硬件爱好者打造个性化扩展坞。文章还提供了调试技巧和进阶优化建议,帮助读者轻松完成项目。

weixin_42520909的博客 404

js变量、作用域及内存详解

js变量、作用域及内存详解 本文主要详细分析了JS变量,作用域以及内存问题,同时附上非常多的实例,方便大家理解这3个概念,是篇不可多得的文章,希望对大家有所帮助 javascript一共有七种数据类型:undefined,NUll,Boolean,Number和String,(后来在ES6中又加入了两种数据类型:set,map),这些类型分别在内存中占有固定的大小空间,他们的值保存在栈空间,我们

Quiet-Night的博客 839

YOLOv8安防监控实战:跌倒/闯入/徘徊实时检测(附TensorRT加速+声光报警部署代码)

精准性:针对跌倒/闯入/徘徊的行为特征优化,准确率达89.3%,误报率低于5次/天;实时性:TensorRT加速到50+FPS,报警延迟<1秒,满足安防“黄金响应时间”;低成本:无需专用AI芯片,RTX 3060或Jetson Orin就能跑,硬件成本比传统方案低60%;易部署:代码全开源,提供从模型训练到硬件联动的完整流程,2天即可搭起原型系统。如果你的安防监控还在“漏报误报”“响应慢”,建议先从跌倒检测的姿态过滤改起——用100张样本测试,再集成TensorRT加速,90%能看到明显改善。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 680

JavaScript变量、作用域及内存详解

基本类型值有:undefined,NUll,Boolean,Number和String,这些类型分别在内存中占有固定的大小空间,他们的值保存在栈空间,我们通过按值来访问的。 (1)值类型:数值、布尔值、null、undefined。 (2)引用类型:对象、数组、函数。 如果赋值的是引用类型的值,则必须在堆内存中为这个值分配空间。由于这种值的大小不固定...

weixin_34310785的博客 76

52-Halcon-- smooth_object_model_3d函数功能(滑处理3D对象模型)

Halcon中smooth_object_model_3d算子详解 该算子用于3D模型平滑处理,提供三种算法:'laplacian'(快速去噪)、'taubin'(高质量防收缩)和'low_pass'(频域滤波)。核心参数包括迭代次数(默认5)、平滑强度(0-1)和边缘保护选项。典型应用包括扫描数据去噪、CAD模型光顺和逆向工程优化。支持自适应平滑、结合模型简化等高级技巧,并可通过分块处理优化大型模型性能。参数组合需根据具体场景选择,如快速去噪推荐拉普拉斯方法(5次迭代,强度0.3),特征保持推荐低通滤波(

weixin_45590420的博客 873

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

javascript中创建变量时作用域和内存详解!

JS变量是松散型的(不强制类型)本质,决定了它只是在特定时间用于保存特定值的一个名字而已; 由于不存在定义某个变量必须要保存何种数据类型值的规则,变量的值及其数据类型可以在脚本的生命周期内改变; 一 变量及作用域 1.基本类型和引用类型 // JS变量包含两种不同的数据类型的值:基本类型值和引用类型值; // 1.基本类型值:保存在栈内存中的简单数据段;即这种值完全保存在内存中的一个位置

学无止境 2660

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

理解 JS 底层机制:作用域链、词法作用域与闭包的核心逻辑

本文聚焦JS底层机制,从V8引擎执行的编译与执行阶段切入,结合三段经典代码案例,解析调用栈、执行上下文的核心作用,深入阐释作用域链“从内到外”“静态绑定”的查找规则,点明词法作用域由函数声明位置决定的本质,进而拆解闭包的形成条件、底层逻辑与内存机制,帮助开发者理解变量访问、闭包驻存等问题,掌握编写高效JS代码的底层原理。

2302_80706750的博客 1425

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

【前端知识点】详解js变量、作用域及内存

基本类型值有:undefined,NUll,Boolean,Number和String,这些类型分别在内存中占有固定的大小空间,他们的值保存在栈空间,我们通过按值来访问的。 (1)值类型:数值、布尔值、null、undefined。 (2)引用类型:对象、数组、函数。 如果赋值的是引用类型的值,则必须在堆内存中为这个值分配空间。由于这种值的大小不固定(对象有很多属性和方法),因此不能把他

chaunceyw的博客 327
上一篇: 关于js中call、apply、bind方法的区别
下一篇: JavaScript:你可以赞扬批评嘲讽它,但却无法忽略
wu_Duo
博客等级 码龄10年 11粉丝 15原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值