js变量的生命周期

变量的生命周期

1.声明

全局变量:全局声明的变量
局部变量:函数内声明的变量,函数参数

声明局部变量的时候必须用var,否则产生的是全局变量

1 scope = "global";
2 function checkscope2() {
3     scope = "local";
4     myscope = "local";
5 }
6 checkscope2();
7 console.log(scope);//输出local,全局变量被修改
8 console.log(myscope);//输出local,全局命名空间被搞乱了

使用var声明的变量是不可配置的,即无法通过delete运算符删除

1 var truevar = 1;//不可配置的全局变量
2 fakevar = 2;
3 this.fakevar2 = 2;
4 delete truevar;//出错
5 delete fakevar;//执行成功
6 delete this.fakevar2;//执行成功

在函数内部中局部变量会遮盖同名的全局变量

1 var scope = “global”;//声明一个全局变量
2 function checkscope(){
3     var scope = “local”;//声明一个同名的局部变量
4     console.log(scope);//输出”local”
5 }

2.变量提升(变量声明提前)

即函数中声明的所有变量都被“提前”至函数体的顶部,这步操作是在代码开始运行之前的JavaScript引擎预编译时执行的。 
例:

1 var scope = “global”;
2 function f(){
3   console.log(scope);//输出”undefined”,而不是”global”
4   var scope = “local”;//变量在这里声明且赋初值,但变量本身在函数体内任何地方均是有定义的
5   console.log(scope);//输出”local”
6 }

实际上,上述的代码等价于:

1 var scope = “global”;
2 function f(){
3   var scope
4    console.log(scope);//输出”undefined”,而不是”global”
5    scope = “local”;//变量在这里声明且赋初值,但变量本身在函数体内任何地方均是有定义的
6    console.log(scope);//输出”local”
7 }

3.全局变量与局部变量的作用域

全局变量:当声明一个全局变量时,实际上是定义了全局对象window的一个属性,在任何地方都可以对其进行访问

局部变量:局部变量在声明它的函数体内以及其所嵌套的函数体内是有定义的。

作用域链:

 1 var color = "blue";
 2 function changeColor(){
 3     var anotherColor = "red";
 4     function swapColors(){
 5         var tempColor = anotherColor;
 6         anotherColor = color;
 7         color = tempColor;
 8         // 这里可以访问 color、anotherColor和tempColor
 9     }
10     //这里可以访问color和anotherColor,但不能访问tempColor
11     swapColors();
12 }
13 // 这里只能访问 color changeColor();        

矩形表示特定的执行环境 
其中,内部环境可以通过作用域链访问所有的外部环境,但 外部环境不能访问内部环境中的任何变量和函数。。每个环境都 可以向上搜索作用域链,以查询变量和函数名;但任何环境都不能通过向下搜索作用域链而进入另一个执行环境。

对于上面的例子而言,其作用域链中包含 3个对象:swapColors()的变 量对象、changeColor()的变量对象和全局变量对象。swapColors()的局部环境开始时会先在自己的 变量对象中搜索变量和函数名,如果搜索不到则再搜索上一级作用域链,即changeColor()的作用域链

作用域链的延长 :

 1 var outer = {
 2     value : "outer",
 3     index : 0
 4 }
 5 function test() {
 6     var inner = "inner";
 7     with(outer){//将outer对象添加到此作用域,可以在其中直接使用其方法和属性
 8         value = inner;
 9     }
10 }
11 test();
12 console.log(outer.value);//输出"outer"

除了with,我们还可以使用catch延长作用域链

5.垃圾回收

标记清除(常用):

工作原理:是当变量进入环境时,将这个变量标记为“进入环境”。当变量离开环境时,则将其标记为“离开环境”。标记“离开环境”的就回收内存。

工作流程:

1.垃圾回收器,在运行的时候会给存储在内存中的所有变量都加上标记。

2.去掉环境中的变量以及被环境中的变量引用的变量的标记。

3.再被加上标记的会被视为准备删除的变量。

4.垃圾回收器完成内存清除工作,销毁那些带标记的值并回收他们所占用的内存空间。

引用计数:

工作原理:跟踪记录每个值被引用的次数。

工作流程:

1.声明了一个变量并将一个引用类型的值赋值给这个变量,这个引用类型值的引用次数就是1。

2.同一个值又被赋值给另一个变量,这个引用类型值的引用次数加1.

3.当包含这个引用类型值的变量又被赋值成另一个值了,那么这个引用类型值的引用次数减1.

4.当引用次数变成0时,说明没办法访问这个值了。

5.当垃圾收集器下一次运行时,它就会释放引用次数是0的值所占的内存。

弊端:在循环循环引用中变量的引用次数不会为零则变量不会被回收

1 function test(){
2     var a={};
3     var b={};
4     a.prop=b;//a的引用次数为2
5     b.prop=a;//b的引用次数为2
6 }

而为了解决这种问题,可以显性地切断引用,即将变量的值设为null

现在大部分的浏览器都是采用标记清除的垃圾回收机制,而IE的BOM和DOM中的对象是以引用计数方式进行垃圾回收的COM对象的形式存在的,所以会有导致变量不能被回收的现象。但是在IE9之后就取消了COM对象的形式。

原文地址:https://www.cnblogs.com/wament/p/10271091.html

时间: 2024-07-29 11:59:17

js变量的生命周期的相关文章

[转]Android静态变量的生命周期

原文地址:https://my.oschina.net/jerikc/blog/137207 Android是用Java开发,其静态变量的生命周期遵守Java的设计.我们知道静态变量是在类被load的时候分配内存的,并且存在于方法区.当类被卸载的时候,静态变量被销毁.在PC机的客户端程序中,一个类被加载和卸载,可简单的等同于jvm进程的启动和结束.那么在Android中呢?用的Dalvik vm也是一样的.不过Android不太突出的进程概念,所以对静态变量的生命周期就会感觉模糊,这种模糊对于值

变量的生命周期

变量不仅有其特定的作用范围,还有其存活的周期--生命周期.变量的生命周期指的是变量可被使用的一个时间段,在这个时间段内变量是有效的,一旦超出这个时间段变量就会失效,我们就不能够再访问到该变量的值了. PHP对变量的生命周期有如下规定. 局部变量的生命周期为其所在函数被调用的整个过程.当局部变量所在的函数结束时,局部变量的生命周期也随之结束. 全局变量的生命周期为其所在的".php"脚本文件被调用的整个过程.当全局变量所在的脚本文件结束调用时,则全局变量的生命周期结束. 有的时候某个自定

android中少用静态变量(android静态变量static生命周期)

在android中,要少用静态变量. 我现在做的一个应用中,之前的开发人员使用静态变量来存储cookie,这个全局的静态变量用来验证身份. 这时客户反应,应用长时间不使用,再次使用,会提示身份过期. 后来经查,问题基本确定在静态变量上. 上stackoverflow查了android中static变量的生命周期,有人这么说 Lifetime of a static variable: A static variable comes into existence when a class is l

C++旧源码向新标准移植陷井(一)_局部栈变量的生命周期

之前在VC++6.0上面写了下面这样的代码: int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { int nRetCode = 0; //不重要的部分略过if (argc>1) {if (strcmp(argv[1],"createpcsstep") == 0) { CDlgCreateStepPcs dlg; dlg.DoModal(); break; } else if (strcmp(argv[1],"clea

[转] C++临时变量的生命周期

http://www.cnblogs.com/catch/p/3251937.html C++中的临时变量指的是那些由编译器根据需要在栈上产生的,没有名字的变量. 主要的用途主要有两类: 1) 函数的返回值, 如: 1 string proc() 2 3 { 4 5 return string("abc"); 6 7 } 8 9 10 11 int main() 12 13 { 14 15 proc(); 16 return 0; 17 18 } 其中第15行会产生一个临时变量.但并不

生命周期,作用域的定义;说明全局变量、静态变量、局部变量、const变量的生命周期、作用域

生命周期,作用域的定义:说明全局变量.静态变量.局部变量.const变量的生命周期.作用域: 生命周期:是一个变量存在的周期. 作用域:是一个变量可以被引用的范围.最常见的如:{}.static修饰符等等. 1)全局变量: 作用域:全局作用域(只需要在一个源文件中定义,就可以作用于所有的源文件): 生命周期:程序运行期一直存在: 引用方法:其他文件如果要使用,必须用extern 关键字声明要引用的全局变量: 内存分布:全局(静态存储区). 注意:如果再两个文件中都定义了相同名字的全局变量,则连接

Android中静态变量的生命周期

静态变量的生命周期,起始于类的加载,终止于类的释放.什么时候类会加载呢?我们知道,在app打开时,会创建一个进程,然后初始化一个dvm的实例,负责类的加载释放 和 垃圾回收等.换句话说,在进程创建之后,就会加载类,静态变量诞生了.那何时释放?当然是在类卸载的时候.同上面.在进程结束之前,静态变量就寿终正寝.我们知道,Android中,你是不知道何时进程会被Kill.所以1.不能保证静态变量会一直存在.(进程可能被Kill掉)2.每次打开app时静态变量的值都是初始值(进程没有被kill掉所以静态

函数变量的生命周期

#!/usr/bin/env python #coding:utf-8 #@Author:Andy # Date: 2017/6/14 # x = 1 # def foo(): # x = 10000 # print(x) # # foo() # print(x) 运行上面的代码会先后打印出:10000, 1.执行foo函数后,x=10000的生命周期在foo函数内部,当此函数执行完后即消失,接着执行print(x), 此时内部的x=10000已经销毁,只有全局变量x=1,所以打印1 x=1 d

asp.net静态变量的生命周期和线程安全

void Application_Start开始 void Application_End结束的,本来这就是对的 今天要做一个全局的应用,想确认一下,在网上一找,我的天,说什么的都有 大概分三种 1.Application_Start——Application_End 2.Session_Start——Session_End 3.类生命周期结束 我用4个机器做了一个测试发现静态变量值一直是不变的,并没有因为其它用户登录而被销毁,确认应该是Application级的 静态类在首次访问时会调用静态构