ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

JavaScript高级程序设计--学习总结(第4章)

2021-05-15 23:34:19  阅读:131  来源: 互联网

标签:原始 变量 -- JavaScript 作用域 对象 引用 程序设计 上下文


第四章 变量、作用域与内存

1. 原始值与引用值

    ECMAScript变量可以包含两种不同类型的数据:原始值和引用值。在把一个值赋给变量时,JavaScript引擎必须确定这个值是原始值还是引用值。

原始值:原始值是存储在中的简单数据段,它们的值直接存储在变量访问的位置。原始值表示表示单一的数据,保存原始值的变量是按值访问,操作存储在变量内存中的实际值。ECMAScript 中设计了6种原始值:Undefined、Null、Boolean、Number、String和Symbol。

引用值:引用值是存储在中的对象,存储在变量处的值是一个指针,指向存储对象的内存处引用值表示表示有多个值(原始值或其他引用值)构成的对象。保存引用值的变量是按引用访问的。实际操作对象时,访问的是保存对象的内存地址,即该对象的引用(ECMAScript 不允许直接访问对象的内存空间)。

1.1 动态属性

    在定义方式上,原始值和引用值很类似,都是先创建一个变量,再给它赋一个值。二者真正的区别在于变量保存了值之后,对这个值如何操作。
    对于引用值而言,赋给变量后可以随时添加、修改和删除该变量的属性。而对于原始值原始值不能有属性,尽管给原始值添加属性不会报错。故 只有引用值可以动态添加后面可以使用的属性

注意:原始值的初始化可以只使用原始字面量形式。若初始化时使用 new 关键字创建了对象,则 JavaScript 会为其创建一个 Object 类型的实例,但其行为仍旧与原始值类似。

4.2 复制值

原始值与引用值在通过变量赋值时也不同。

    原始值变量存储在栈中,在通过变量把一个原始值赋给另一个原始值时,原始值会被复制到新变量的位置。此后新变量与原变量各自独立,互不干扰。改变其中一个变量的值不会使另一个变量值发生改变。
    引用值在被从一个变量赋给另一个变量时,是在新变量中存放指向原变量的指针,因此新变量与原变量都指向同一个对象,就是要被赋给新变量的值。此后,这个对象的值会使两个变量的值都发生改变。

4.3 传递参数

    ECMAScript中所有参数都是按值传递的,这意味着函数外的值会像变量值的复制一样被复制到函数内部的参数中。
根据变量值的复制方法可以知道:
        在按值传递参数时,值会被复制到一个局部变量,这完全可以实现;
        而按引用传递参数时,值在内存中的位置会被保留到一个局部变量,这意味着对该局部变量的修改会反映到函数外部(即使该局部变量所在函数的外部的原参数变量的值也发生改变),这在 ECMAScript 中是不可能实现的。
        故参数传递只能按值传递。

注意:ECMAScript 中函数的参数就是局部变量。

4.4 确定类型

typeof操作符:用于判断一个原始值变量的类型,是否为字符串、数值、布尔值或 undefined。
instanceof操作符:用于判断引用值变量是什么类型的对象,语法为 result = variable instanceof constructor。返回值为 true 或者 false.

根据引用值的定义(是由多个值构成的对象),所有的引用值都是 Object 类型的实例,因此通过 instanceof 操作符检测任何引用值是否是 Object 构造函数都会返回 true。 同样,原始值不是对象,故用 instanceof 检测任何原始值都会返回 false。

注意:typeof操作符在用于检测函数时也会返回 “function”。typeof 对正则表达式会返回 “function” 或者 “object”,取决于浏览器。

2. 执行上下文与作用域

执行上下文的概念在JavaScript中非常重要。变量的执行上下文决定了它们可以访问哪些数据,以及它们的行为。每个执行上下文都有一个关联的变量对象,该执行上下文中定义的所有变量和函数都在这个对象上。
全局上下文:全局上下文是最外层的执行上下文。在浏览器中,全局上下文就是window对象,因此所有通过 var 定义的全局变量和函数都会成为 window 对象的属性和方法,而使用 let 和 const 的顶级声明不会定义在全局上下文中,但在作用域链解析上效果相同。
执行上下文在其所有代码都被执行完毕后会被销毁,全局上下文在应用程序退出前才会被销毁,如关闭网页或退出浏览器。
每个函数调用都有自己的执行上下文。当代码执行流进入函数时,函数的上下文被推到一个上下文栈上。在函数执行完之后,上下文栈会弹出该函数上下文,将控制权返还给之前的执行上下文。ECMAScript 程序的执行流就是通过这个上下文栈进行控制的。
上下文中的代码在执行的时候,会创建变量对象的一个作用域链。这个作用域链决定了各级上下文中的代码在访问变量和函数时的顺序。代码正在执行的上下文的变量对象 始终位于作用域链的最前端。
如果上下文是函数,则其活动对象用作变量对象。活动对象最初只有一个定义变量:arguments。(全局上下文中没有这个变量。)作用域链中的下一个变量对象来自包含上下文,再下一个对象来自再下一个包含上下文。以此类推直至全局上下文;全局上下文的变量对象始终是作用域链的最后一个变量对象。
代码执行时的标识符解析是通过沿作用域链逐级搜索标识符名称完成的。搜索过程始终从作用域链的最前端开始,然后逐级往后,直到找到标识符。(如果没有找到标识符,那么通常会报错。)
局部作用域中定义的变量可用于在局部上下文中替换全局变量。

注意:函数参数被认为是当前上下文中的变量,因此也跟上下文中的其他变量遵循相同的访问规则。

2.1 延长作用域链

虽然执行上下文主要有 全局上下文函数上下文两种(eval()调用内部存在第三种上下文),但有其他方式来增强作用域链。某些语句会导致在作用域链前端临时添加一个上下文,这个上下文在代码执行后会被删除。通常在两种情况下会出现这个现象,即代码执行到下面任意一种情况时:
try/catch 语句的catch 块;
with 语句;
这两种情况下,都会在作用域链前端添加一个变量对象。对 with 语句来说,会向作用域链前端添加 指定的对象;对catch 语句而言,则会创建一个新的 变量对象,这个变量对象会包含要抛出的错误对象的声明。

2.2 没有块级作用域

JavaScript当中没有块级作用域。在其他的类C语言中,由花括号封闭的代码块都有自己的作用域(就是JS中的执行环境),因此可以在其中定义局部变量。而JavaScript当中最小的作用域为函数作用域。

2.1.1 声明变量

使用var声明的变量会自动被添加到最接近的环境中。而没有使用var关键字来声明变量时,变量会被添加到全局环境中。

2.1.2 查询标识符

在某个环境中引用一个标识符时,必须通过搜索来确定该标识符代表什么意义。执行过程会从当前的作用域链的前端开始,向上逐级查询。如果在局部环境中搜索到了,则该搜索过程就停止。而如果在局部中没有搜索到,则会继续沿作用域链向上搜索,直到全局环境为止。如果全局环境中也没有找到,说明该变量未声明。

3. 垃圾收集

JavaScript也具有自动垃圾收集机制,即执行环境会负责管理代码执行过程中使用的内存。
对于垃圾回收机制通常有两种策略:标记清除与引用计数。

3.1标记清除

标记清除是JavaScript中最常用的垃圾收集机制。当一个变量进入环境时,就被标记为“进入环境”,而当变量离开时,变被标记为“离开环境”。垃圾收集器定周期检查所有变量的标记,将标记为“离开环境”的变量内存回收。

3.2引用计数

引用计数跟踪记录了每一个变量被引用的次数,将引用这个变量的计数为0时,它便可以被回收。但是这个机制存在一个问题,那就是循环引用,两个变量之间可能存在对对方的引用,这样,虽然这两个变量都没有被使用了,但是由于他们的引用计数不为0,则他们永远不能被回收。当前的JavaScript引擎都不再使用这一方法了。

3.3性能问题

如果无节制地分配大量的内存,则在垃圾回收的时候会地性能造成影响,因此应该对内存的使用多加注意。

3.4管理内存

因为JavaScript是运行在浏览器上的,而Web浏览器通常被分配的内存是有限的。因此为了确保JavaScript的运行效率和让页面获得更好的性能,必须确保占用最少的内存。
优化内存占用的最佳方式就是为执行中的代码保存必要的数据。一旦数据不再有用,最好将其设置为null,这称为解除引用。为一个变量解除引用并不代表立即回收该变量的内存,解除引用的真正作用是使变量脱离执行环境,在下次进行垃圾回收时将其回收。

标签:原始,变量,--,JavaScript,作用域,对象,引用,程序设计,上下文
来源: https://blog.csdn.net/qq_51893876/article/details/116542296

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有