《JavaScript高级程序设计(第三版)》读书笔记01 变量、作用域和内存问题
程序员文章站
2022-07-12 18:14:59
...
第4章 变量、作用域和内存问题
4.1 基本类型和引用类型的值
-
基本类型:
- 有undefined,null,boolean,number,string.
- 值在内存中占据固定大小的空间,因此被保存在栈内存中。
- 从一个变量向另一个变量赋值基本类型的值,会创建这个值的一个副本。
- 确定值的基本类型使用typeof操作符。
-
引用类型:
- 值是对象,保存在堆内存中。
- 包含值的变量包含的不是对象本身,是指向对象的指针。
- 从一个变量向另一个变量复制引用类型的值,复制的是指针,因此两个变量指向同一个对象。
- 确定值是那种引用类型可使用instanceof操作符。
值的属性和方法:基本类型不能添加;引用类型可以增删改,如下:
var person = new Object();//类似java,new一个对象的实例
person.name = "Nicholas";//属性
alert(person.name);
复制变量值:
- 基本类型:新值新内存,相当于副本,两者互不影响。
- 引用类型:新建一个指针指向同一个对象,指针有新内存。两者互相影响。
var obj1 = new Object();
var obj2 = obj1;//新建了一个obj2指针,指向Object对象
obj1.name = "Nike";//改变一个变量
alert(obj2.name);//另一个也随之改变,输出"Nike"
传递参数
ECMAScript中所有函数的参数都按值传递。方法如同复制变量值。
访问变量有按值和按引用两种方式,参数只能按值传递。
在向参数传递引用类型的值时:把值在内存中的地址复制给一个局部变量,该局部变量的变化会反应在函数的外部。如下:
//基本类型
function addTen(num) {//函数addTen()有一个参数num,是函数的局部变量,20被复制给num
num += 10;
return num;
}
var count = 20;
var result = addTen(count);//调用函数时,变量count作为参数被传递给函数,值为20
alert(count);//20
//如果num 按引用传递,count=30
alert(result);//30
//引用类型
function setName(obj) {//3.变量person被复制给了obj
//obj和person引用的同一个对象,在堆内存中只有一个,而且是全局对象
obj.name = "Nike";//为obj添加属性,函数外部的person也有该属性
}
var person = new Object();//1.创建一个对象,保存在变量person中
setName(person);//2.变量被传递到setName()函数中
alert(person.name);//Nike
//验证引用类型参数按值传递而不是按引用传递
function setName(obj) {
obj.name = "Nike";
obj = new Object();//为obj重新定义一个对象(函数内部定义的对象为局部对象,函数执行完毕后会立即销毁)
obj.name = "Greg";//为该对象定义一个不同的name属性
}
//即使在函数内部修改了参数的值,但原始的引用仍然保持不变
var person = new Object();
setName(person);
alert(person.name);//Nike
如果person按引用传递,name会是Greg,但是是NIke证明按值传递。
检测类型
1、基本数据类型
typeof操作符是检测基本数据类型变量类型的最佳工具。若是引用数据类型(对象)或NULL,则返回object。
var s ="NIke";
var b = true;
var i = 22;
var u;
var n = null;
var o = new Object();
alert(typeof s);//string
alert(typeof b);//boolean
alert(typeof i);//number
alert(typeof u);//undefined
alert(typeof n);//object
alert(typeof o);//object
//如果值是null或者对象,类型为object
2、引用数据类型
instanceof。
- 语法:
result = variable instanceof constructor
。 - 意义:variable变量是constructor引用类型的实例吗?
- 结果:true/false
- 例子:
alert(person instanceof Object);
4.2 执行环境及作用域
定义
- 执行环境:定义了变量或函数有权访问的其他数据,决定了它们各自的行为。类型:
- 全局执行环境:是window对象,应用程序退出时(关闭网页或浏览器)会被销毁
- 函数执行环境:会被推入环境栈中,函数执行之后,栈将环境弹出。
- 作用域链:对执行环境有权访问的变量对象的有序访问。
- 变量对象:保存环境中定义的所有变量和函数。
- 每次进入一个新执行环境,都会创建一个作用域链。
- 作用域的前端(第1个):变量对象是当前执行的代码所在环境的
- 第2个:外部环境的
- 。。。。更外部的
- 最后一个:全局执行环境的
- 标识符解析:沿作用域链一级一级搜索标识符的过程,前端开始。
var color = "blue";//全局
function changeColor() {
if(color == "blue") {
color = "red";//可搜索到全局环境的变量对象
} else {
color = "blue";
}
}
changeColor();
alert("Now the color is "+color);//red
详解局部与全局环境和作用域链
//环境
//全局环境:有一个变量color和函数changeColor()
var color = "blue";
//局部环境2(changeColor()):有一个变量anotherColor和一个函数swapColors()
function changeColor() {
var anotherColor = "red";
//局部环境1(swapColors()):有一个变量temColor,该变量只能在该环境中访问
function swapColors() {
var tempColor = anotherColor;
anotherColor = color;
color = tempColor;
}
swapColors();
}
changeColor();
alert("Now the color is "+color);//red
//作用域链
window
color
changeColor()
anotherColor
swapColors()
tempColor
- 内外关系:内部环境可以通过作用域链访问所有的外部环境,但外部环境不能访问内部环境中的任何变量和函数。
- 例子1:swapColors()作用域链包含3个对象:swapColors()的变量对象、changeColor()的变量对象(变量和函数名)、全局变量对象。
- 例子2:changeColor()的作用域链不能访问swapColors()的
- 总结:xx的作用域链包括自己的对象和他外部外外部外..部的的环境里的变量对象
延长作用域链(略)
- try catch语句的catch块:创建一个新的变量对象。
- with语句:将制定的对象添加到作用域链中
没有块级作用域
- 使用var声明的变量会自动被添加到最接近的环境中。
- for 和 if中的变量声明会将变量添加到当前的执行环境
if(true){
var color = "blue";
}
alert(color);//blue
for (var i=0; i<10; i++) {
// doSomething(i);
}
alert(i);//10
function add(num1, num2) {
var sum = num1 + num2;
return sum;
}
var result = add(10, 20);
alert(sum);//因sum是局部变量,访问不到,导致错误。如果去掉var,结果为30
- 查询标识符:搜索作用域链,从前端开始,查到结束。
var color = "blue";//全局
function getColor(){
return color;
}
alert(getColor());//查到全局变量结束,blue
var color = "blue";
function getColor(){
var color = "red";//局部,在作用域链的前端
return color;
}
alert(getColor());//查到局部变量结束,red
4.3 垃圾收集
js有自动垃圾收集机制,原理是按照固定时间间隔找出不再继续使用的变量,释放其占用的内存。通常有2个策略:
1、标记清除
- 最常用。
- 变量进入环境标“进入环境”,离开环境标“离开环境”,最后内存清除
2、引用计数(略)
- 不常用
- 跟踪记录每个值被引用的次数,不同情况+1 -1,次数为0则内存清除
解除引用
- 定义:一旦数据不在有用,最好通过将其值设置为null来释放其引用。适用于大多数全局变量和全局对象的属性。
- 方法:手工解除。赋值为null。
- 意义:让值脱离执行环境,便于回收。
推荐阅读
-
JavaScript高级程序设计之变量,作用域和内存问题总结
-
一篇文章带你了解JavaScript中的变量,作用域和内存问题
-
《JavaScript高级程序设计(第三版)》读书笔记01 变量、作用域和内存问题
-
javascript 的变量、作用域和内存问题
-
JavaScript高级程序设计之变量,作用域和内存问题总结
-
一篇文章带你了解JavaScript中的变量,作用域和内存问题
-
JavaScript中变量、作用域和内存问题
-
JavaScript变量作用域和内存问题(二)_html/css_WEB-ITnose
-
简单谈谈javascript中的变量、作用域和内存问题_javascript技巧
-
javascript 的变量、作用域和内存问题