经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » JavaScript » 查看文章
诡异的 javascript 变量
来源:cnblogs  作者:micemik  时间:2022/1/17 11:05:24  对本文有异议

诡异例子:

function DelayExe() {

  var a = 10;

  setTimeout( function Print() { console.log(a); },  1000  );

}

 

以C++的观点来看:一旦函数DelayExe()执行完毕,变量 a 就不复存在,函数 Print() 根本引用不到变量a,必然抛出异常。

但是,在 js 中,在 DelayExe() 执行完毕 1000ms 后执行 Print() 函数,Print() 函数居然能正确引用 a。是不是很诡异?

  

概念和原理:

举个例子:

一个64位整型变量,在 C++ 程序中,只占8字节。

 一个64位整型变量,在 js 中,占有以下空间:

M1:8字节,表达数值

M2:引用计数器,若是 5,表示有 5 个函数引用该变量。

 

每当一个函数引用该变量时,js 引擎就递增变量的引用计数器

每当一个函数用完该变量后,js 引擎就递减变量的引用计数器。若变量的引用计数器递减为 0,说明已没有函数用到该变量,该变量才会被删除。

 

由此可见:

C1:js 中的变量,不仅包含数值,还包含引用计数器。

C2:变量是否存在,取决于其引用计数器的值。

C3:js 引擎根据引用计数器的值决定是否删除变量,是否从内存中清除变量。

 

实际用例:

function DelayExe() {

  var a = 10;

  setTimeout( function Print() { console.log(a); },  1000  );

}

 

以C++的观点来看:

变量 a 是函数DelayExe() 的局部变量,函数 DelayExe() 执行完毕,变量 a 就被删除,不再占用存储空间。

 

但是,js 的情况截然不同:

S1:执行函数 DelayExe()

S2:执行到语句 setTimeout() 时,做如下处理:

S2.1:在内存中分配一块空间,存储函数 Print(),

S2.2:由于函数 Print() 引用了变量 a,递增变量 a 的引用计数器

S2.3:安排函数 Print() 在 1000ms 后被放入任务队列调度执行

S3:函数 DelayExe() 执行完毕。由于此时变量 a 的引用计数器 > 0,所以 js 引擎不将其不删除,变量 a 依然存在。

S4:1000ms 后执行函数 Print(),执行完毕后,函数 Print() 不再引用变量 a,js 引擎递减变量 a 的引用计数器。此时,变量 a 的引用计数器递减为 0,不再被任何函数引用,于是 js 引擎才将其从内存中删除。

 

结论:

C1:js 变量的存在性,与变量的定义位置无关。

C2:js 变量是否存在,是否占用存储空间,取决于有没有被函数引用。

C2.1:若没有被任何函数引用,变量就被删除。

C2.2:若至少被一个函数引用,变量就存在。

C3:若一个变量被一个函数引用,但这个函数一直未被调用执行,那么这个变量就一直存在。

原文链接:http://www.cnblogs.com/micemik/p/15765872.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号