javascript高级程序设计读书笔记(四)

变量,作用域,和内存的问题

javascript高级程序设计读书笔记(四)

变量,作用域,和内存的问题

变量

不存在定义一个变量就保存这种数据类型的值的规则,一个变量的值和数据类型可以在脚本的生命周期内改变。

  • 基本类型的值
  • 引用类型的值

基本类型的值

基本数据类型是按照值访问的,可以操作保存在变量里面实际的值

  • 字符串
  • 数值
    • NaN:特殊的数值型;isNaN():返回是否是不是数值
    • isNaN()被对象调用的时候,会首先调用对象的valueOf(),看其是否可以转为数值;不能,则基于这个返回值在调用toString(),再看是否是数值
  • 布尔值
  • undefined
  • null
    • 只要意在保存的变量还没有真正保存对象,就应该明确的让该变量保存null,体现出null是空对象指针。

字符串,数值和布尔值都有toString()方法,但undefinednull没有此方法,但是可以使用String(),这个方法可以传入基数,输出二进制或者八进制或者十六进制的字符串值

数据类型 转为true的值 转为false的值
Boolean true false
Number 任何非0数字,包括无穷大 0和NaN
String 任何非空字符串 ' '(空字符串)
Object 任何对象 null
Undefined 不适用 undefined

在内存中占据固定大小的空间,因此保存在栈内存里面

引用类型的值

是保存在内存中的对象,是按照引用来访问的,因为,JS是不允许直接访问内存中的位置,也就不能直接操作对象的内存空间,实际上是操作对象的引用

引用类型的值是对象,保存在堆内存

  • Object类型

    对象其实就是数据和功能的集合,Object类型是所有它的实例的基础,其所具有的任何的属性和方法同样都存在更具体的对象中。

两种值的不同点

  • 当定义一个引用类型的变量,可以为其动态的添加属性和方法,但是基本类型的变量就不可以,虽然操作是不会出现错误,返回undefined

  • 基本类型的变量的复制

    var num1=5;
    var num1=num2;
    
    • num1和num2是相互独立的,互不影响,在内存空间里面分配不同的空间
  • 引用类型值的复制:

    var obj1=new Person();
    var obj2=obj1;
    
    • 此时的obj2和obj1是指向同一个地址空间,之间的复制是把引用,也就是指向这个对象的内存空间的指针复制了一份,当操作obj1的属性的时候,obj2也受到影响

传递参数

ECMAScript中所有函数的参数都是按值传递的。就是把值,从外部的变量,复制一份给函数中参数变量。传递基本类型的值给函数中的参数的时候,被传递的值被复制给函数参数aguments对象的一个元素,局部变量;给参数传递引用类型的时候,就是把这个值在内存中的地址复制给arguments中的一个局部变量,所以这个局部变量变化会反映在函数的外部。

  function setName(obj){
         obj.name='icessun';
         obj=new Object();
         obj.name='icessun1';  //将新的对象赋值给obj对象并设置name属性 
    } 
    var person=new Object();
    setName(person);
    alert(person.name);   // 弹出icessun  这说明参数的传递是按照值来的

上面的代码说明,参数是按照值传递的,因为在函数setName中,重新赋值一个对象给obj,并且改变了其name属性,要是按照引用传递的话,那么后面弹出来的是icessun1;结果却不是这样,这说明:

函数内部改变了参数的值,但是原始的引用保持不变;因为在函数内部重写参数时,这个变量引用就是一个局部变量,会在函数执行完毕立即销毁。

类型检测

  • typeof
    • 字符串 ------> string
      var n; console.log(typeof n); // undefined
    • 数值 -------> number
    • 布尔值 --------> boolean
    • undefined -------> undefined

unll == undefined; true

typeof是检测上面这几种类型的最佳工具,但是对于null对象都返回object,因为null表示一个空对象指针,所以typeof nullObject;检测函数的时候,会返回function;这是区分函数和其他对象的方法,函数是一个对象,不是一种数据类型。

对于未声明的变量和为初始化的变量,执行typeof操作都返回undefined

var message; //  未初始化
// var age;   未声明
console.log(typeof message);  // undefined
console.log(typeof age);     // undefined
  • instanceof :检测什么类型的对象(引用类型)

variable instanceof constructor 返回true/false

  • Object
  • Array
  • RegExp
    如果变量是给定引用类型的实例,那么instanceof之后返回的结果都是true;基本类型不是对象,都返回false。所有的引用类型的值都是Object的实例。

执行环境和作用域

执行环境定义了变量和函数有权访问的其他数据。决定了各自的行为。某个执行环境中的所有代码执行完毕,该环境就被销毁,保存在里面的所有的变量和函数定义也随之销毁。每个函数都有自己的执行环境,当执行这个函数的时候,会把这个函数推入到一个环境栈里面,直到函数执行完成,再从环境栈里面弹出,交到之前的执行环境。

  • 作用域链
    • 保证对执行环境有权访问的所有变量和函数的有序访问;其前端,始终是当前执行代码的所在环境的变量对象环境是函数,则这个活动对象就是arguments对象。下一个变量对象来自包含环境(包含当前变量对象的外部环境),就这样一直延续到全局执行环境,故全局的执行环境是作用域链的最后一个对象。
var color='blue';
function changeColor(){
    if(color==='blue'){
         color='red';
     }else{
         color='blue';
      }
 }
 changeColor();
 console.log('Color is now'+color);

上面的代码中,函数的作用域链包含两个对象:自己的变量对象arguments对象和全局环境的变量对象。可以在函数内部访问到全局的变量,因为在其的作用域链上面可以找到。

作用域链: 
    - window
       - color
       - changeColor()
          - arguments

每一个环境都可以向上搜索作用域链,查询变量和函数名,但是不能向下搜索作用域链;函数参数也是函数执行环境中内部的变量,局部变量。

  • 延长作用域链

    • try-catch语句中的catch块
    • with语句
  • 没有块级作用域

在其他的类C语言,由花括号封闭的代码块都有自己的作用域,因而支持根据条件来定义变量。但是JavaScript没有块级作用域

- 声明变量

使用var声明的变量会自动添加到最接近的环境中:在函数内部,最接近的就是函数的局部环境;在with语句中,最接近的是函数环境;如果初始化变量时没有使用var,则会自动把该变量添加到全局环境中。

   - **注意**:
   在`javascript`中,由`for`语句创建的变量`i`(由`var`声明的),即使循环结束,也依旧存在循环外部的执行环境中。

-  作用域向上搜索
 
 在执行环境中查找一个变量的时候,在局部环境里面找到,就直接使用;否者,继续向上的作用域链查找,没有找到,说明该变量没有声明。

垃圾回收

javascript中有自动垃圾回收机制;原理就是:找到那些不再需要继续使用的变量,然后释放其占用的内存。垃圾回收机制会按照固定的时间间隔,周期性的去执行这一操作。

  • 标记清除
    给存储在内存中的变量都加上标记,然后去掉环境中的变量标记以及被环境中的变量引用的变量的标记;之后再加上的标记的变量是当做准备删除的变量,因为环境中的变量已经无法访问到这些变量了;最后,垃圾回收器完成垃圾的回收。
  • 计数清除
    记录每一个值被引用的次数,当声明了一个变量并将一个引用类型赋值给该变量的时候,引用次数为1,如果同一个值又被赋给其他的变量,该值引用次数就加1,包含对这个值引用的变量又取得另外一个值,则这个值的引用次数减1,当次数为0的时候就说明不能访问到,应该回收;坏结果:循环引用。

IE9BOMDOM对象都转换成真正的JavaScript对象。就避免了垃圾回收的问题,也消除了常见的内存泄漏现象。

一般来说:一旦数据不再使用,最好手动将其设置为null,来释放其引用,适合大多数的全局变量和全局对象的属性。局部变量会在离开执行环境的时候自动解除引用。解除引用,是让值脱离执行环境,等待垃圾回收运行将其回收。

你可能感兴趣的:(javascript高级程序设计读书笔记(四))