欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

《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。
  • 意义:让值脱离执行环境,便于回收。
相关标签: 读书笔记