javascript的变量、作用域和内存问题
基本类型和引用类型的值
执行环境
垃圾收集
ECMAScript 变量可能包含两种不同数据类型的值:基本类型值和引用类型值。
基本类型值指的是简单的数据段
引用类型值指那些可能由多个值构成的对象
基本数据类型:Undefined、Null、Boolean、Number 和 String。这 5 种基本数据类型是按值访问的,因为可以操作保存在变量中的实际的值。
引用类型的值是保存在内存中的对象,在操作对象时,实际上是在操作对象的引用而不是实际的对象。为此,引用类型的值是按引用访问的。
动态的属性:定义基本类型值和引用类型值的方式是类似的:创建一个变量并为该变量赋值。
但是,当这个值保存到变量中以后,对不同类型值可以执行的操作则大相径庭。
对于引用类型的值,我们可以为其添加属性和方法,也可以改变和删除其属性和方法。
参数传递:ECMAScript 中所有函数的参数都是按值传递的,看下面这个例子:
function setName(obj) {
obj.name = "Nicholas";
obj = new Object();
obj.name = "Greg";
}
var person = new Object();
setName(person);
alert(person.name); //"Nicholas"
执行环境和作用域:
执行环境(execution context,为简单起见,有时也称为“环境”)是 JavaScript 中最为重要的一个概念。
执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为。
每个执行环境都有一个与之关联的变量对象(variable object),环境中定义的所有变量和函数都保存在这个对象中。虽然我们编写的代码无法访问这个对象,但解析器在处理数据时会在后台使用它。
当代码在一个环境中执行时,会创建变量对象的一个作用域链(scope chain)。
作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。作用域链的前端,始终都是当前执行的代码所在环境的变量对象。如果这个环境是函数,则将其活动对象(activation object)作为变量对象。
全局执行环境是最外围的一个执行环境。
在 Web 浏览器中,全局执行环境被认为是 window 对象,因此所有全局变量和函数都是作为 window 对象的属性和方法创建的。
某个执行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义也随之销毁。
每个函数都有自己的执行环境。当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。而在函数执行之后,栈将其环境弹出,把控制权返回给之前的执行环境。
活动对象在最开始时只包含一个变量,即 arguments 对象(这个对象在全局环境中是不存在的)。作用域链中的下一个变量对象来自包含(外部)环境,而再下一个变量对象则来自下一个包含环境。这样,一直延续到全局执行环境;全局执行环境的变量对象始终都是作用域链中的最后一个对象。
标识符解析是沿着作用域链一级一级地搜索标识符的过程。搜索过程始终从作用域链的前端开始,然后逐级地向后回溯,直至找到标识符为止(如果找不到标识符,通常会导致错误发生)。例如下面的例子:
var color = "blue"; function changeColor() {
if (color === "blue") {
color = "red";
} else {
color = "blue";
}
} changeColor(); alert("Color is now " + color);
在这个例子中,函数 changeColor() 的作用域链包含2个变量对象:第一个变量对象是它自己的 arguments,第二个变量对象是全局的变量对象。
var color = "blue"; function changeColor() { var anotherColor = "red"; function swapColors() {
var tempColor = anotherColor;
anotherColor = color;
color = tempColor;
// 这里可以访问 color、anotherColor 和 tempColor
} // 这里可以访问 color 和 anotherColor,但不能访问 tempColor
swapColors();
} // 这里只能访问 color
changeColor();
以上代码共涉及 3 个执行环境:全局环境、changeColor()的局部环境和 swapColors()的局部环境。
全局环境中有一个变量 color 和一个函数 changeColor()。
changeColor()的局部环境中有一个名为 anotherColor 的变量和一个名为 swapColors()的函数,但它也可以访问全局环境中的变量 color。
swapColors()的局部环境中有一个变量 tempColor,该变量只能在这个环境中访问到。
延长作用域链
就是当执行流进入下列任何一个语句时,作用域链就会得到加长:
try - catch 块的 catch 块中
with 语句
这两个语句都会在作用域链的前端添加一个变量对象。
没有块级作用域
javascript的变量、作用域和内存问题的更多相关文章
- 浅谈javascript中变量作用域和内存(2)
1.无块级作用域 javascript没有块级作用域,这会让其他程序员在理解js代码上很痛苦.在其他很多语言,比如C,大括号括起来的代码块都有自己的作用域 举个例子 if(true) { var na ...
- 浅谈javascript中变量作用域和内存(1)
先理解两个概念:基本类型和引用类型的值 1.基本类型和引用类型的值 (1)定义: 基本类型:指简单的数据段,比如按值访问的js五种基本数据类型undefined.null.boolean.number ...
- 第一百零六节,JavaScript变量作用域及内存
JavaScript变量作用域及内存 学习要点: 1.变量及作用域 2.内存问题 JavaScript的变量与其他语言的变量有很大区别.JavaScript变量是松散型的(不强制类型)本质,决定了它只 ...
- [转]深入理解JavaScript的变量作用域
1.JavaScript的作用域链 2.函数体内部,局部变量的优先级比同名的全局变量高. 3.JavaScript没有块级作用域. 4.函数中声明的变量在整个函数中都有定义. 5.未使用var关键字定 ...
- 深入理解JavaScript的变量作用域(转载Rain Man之作)
在学习JavaScript的变量作用域之前,我们应当明确几点: JavaScript的变量作用域是基于其特有的作用域链的. JavaScript没有块级作用域. 函数中声明的变量在整个函数中都有定义. ...
- 深入理解JavaScript的变量作用域
在学习JavaScript的变量作用域之前,我们应当明确几点: JavaScript的变量作用域是基于其特有的作用域链的. JavaScript没有块级作用域. 函数中声明的变量在整个函数中都有定义. ...
- JavaScript函数变量作用域
变量作用域 在JavaScript中,用var申明的变量实际上是有作用域的. 如果一个变量在函数体内部申明,则该变量的作用域为整个函数体,在函数体外不可引用该变量. 如果两个不同的函数各自申明了同一变 ...
- Javascript之变量作用域
分析: 无论是强类型语言c#.c++.java等语言,还是弱类型语言如Javascript,所有变量可以抽象为两种类型,即局部变量和全局变量. 全局变量:整个作用域可见. 局部变量:局部可见,退出作用 ...
- javascript的变量作用域--对比js、php和c的for循环
为什么要写这篇文章呢?主要是给自己提个醒,js的水很深,需要小心点儿才能趟过去,更何况自己不是专业人士,那就得更加小心了. 看下面的js代码: <!DOCTYPE html> <ht ...
- JavaScript变量作用域和内存问题(二)
执行环境是js中特别重要的概念,是指变量或者函数可以访问其他数据,定义自己的行为.每个执行环境都有一个与之相对应的变量对象,执行环境中定义的所有变量和函数都保存在这个变量中,我们看不到这个变量,但是后 ...
随机推荐
- SendMessage()、WPARAM、LPARAM函数使用例子(转)
http://chujiaba.blog.163.com/blog/static/18991813720106209350592/ 2010-07-20 21:35:00| 分类: C | 标 ...
- centos6.4 安装erlang
erlang官网: http://www.erlang.org 下载程序去年:
- 第二百八十六天 how can I 坚持
bug不断啊,头疼. 今天早上到的倒是挺早. 中午吃的黄焖鸡,晚上加了会班. 勇江的鱼都死了,杨建的还剩3条,晚上到家都快十点了,还洗了衣服,没捞出来呢, 希望可以请下来假吧. 晾上衣服睡觉.
- CSS构造超链接
超链接边框 派生超链接 属性选择器超链接 动态超链接 图像翻转超链接 CSS工具提示 1.给链接加上边框 A:link { Color: #f00; Text- ...
- Java学习笔记(二):String
String 在Java中String是作为引用对象存在的一种数据类型,用来保存字符串. 实例化和赋值 //直接声明 String s1 = "Hello world!"; //通 ...
- Kicad使用经验谈
最近开始学习使用Linux上的开源软件KiCad来绘制电路图和PCB.学习这个还是比较快的,用了两天了,觉得还是蛮方便的. 在这两天的使用以及今后的使用过程中,一定会有很多想要谈的.所以,就写下这篇博 ...
- Java数据库编程(JDBC)
一.使用Java对数据库的操作步骤: 1.根据应用程序的数据库类型,加载相应的驱动: 2.连接到数据库,得到Connection对象: 3.通过Connection创建Statement对象: 4.使 ...
- android ipc通信机制之二序列化接口和Binder
IPC的一些基本概念,Serializable接口,Parcelable接口,以及Binder.此核心为最后的IBookManager.java类!!! Serializable接口,Parcelab ...
- JavaWeb学习篇之----容器Response详解
今天在来看一下Response容器的相关知识,其实这篇blog早就应该编写了,只是最近有点忙,所以被中断了.下面我们就来看一下Response容器的相关知识吧.Response和我们即将在后面说到的R ...
- PostgreSQL的 initdb 源代码分析之十八
继续分析: setup_conversion(); 展开: 其实质是: 运行命令:"/home/pgsql/project/bin/postgres" --single -F -O ...