javascript学习系列(一)变量、作用域

1、变量是保存数据的容器;

2、变量的命名规则:

    (1)包含$、_、字母、数字,其中竖子不能用作开头;

    (2)区分大小写,不能是保留字和关键字。

3、变量的声明:

一般用var/let(ES6),如果没有var则默认为全局变量,且预解析时不能被解析,且容易造成变量污染。

4、数据类型:

分为基本类型和引用类型

javascript学习系列(一)变量、作用域

 

(1)基本类型变量直接放在栈中,调用时访问栈内内容就行;而引用类型变量实际是存放在堆中,然后在栈中存放对应的地址,访问时通过调用栈中的引用名,其内容对应的就是堆中的地址。

javascript学习系列(一)变量、作用域

(2)数据类型判断

typeof(a);   //返回a的数据类型

eg:typeof(1)->number;

typeof('a')->string;

typeof(true)->boolean;

typeof(undefined)->undefined;

typeof(null)、typeof({})、typeof([])->Object;

typeof(function(){})->function;

但是对于null、[ ]、{}等类型怎只能判断为object,所以需要用instanceof来判断。

instanceof: object instanceof VarType;

eg:[] instanceof Array -> true;

5、作用域

(1)分为全局作用域和局部作用域(主要指函数作用域,因为js中无块级作用域),对应的变量为全局作用域和局部作用域。

(2)作用域链时用来查询变量的(从里层到外层查询,最外层为window)。

6、js解析机制

过程:

(1)预解析:找到var声明的变量并赋值为undefined;然后再找function后面的函数名(函数参数作为局部变量处理),直接提前声明函数;

(2)逐行解读代码:读取每一行代码并赋值(有关函数声明的部分都跳过,因为预解析时已经声明了。)

命名冲突:

(1)变量名和函数名冲突时预解析只保留函数名,剔除变量名(函数权重大);

(2)函数名与函数名冲突,后面的覆盖前面的;

预解析问题

(1)问题1  (注:不通过var声明的变量都是全局变量)

A. console.log(a); var a = 1; ->undefined

B. console.log(a); a=1;  ->a is not defined

(2)问题2

console.log(a);

var a=1;

console.log(a);

function a(){ console.log(2);}

console.log(a);

var a=3;

console.log(a);

function a(){console.log(4);}

console.log(a);

a();

预解析为:function a(){console.log(4);}

输出结果为:

a();   //a函数

1

1

3

3

a is not a function     //a已经被变为一个变量

(3)问题3

   A.

var a=1;

function fn(){ console.log(a); var a=2;}

fn();

console.log(a);

预解析为:

        a:undefined;

        fn{ a:undefined;}

输出结果为:

       undefined;     //先读取fn里面的局部变量a,但是a还未被赋值,所以输出结果为fn里面的预解析a

  B.

var a=2;

function fn(){

     console.log(a);

      a=2;     //全局变量

}

fn();

console.log(a);

预解析为:

        a:undefined;

        fn{ }   //fn里面没变量a

输出结果为:

       1;     //先在fn里面找变量a,没找到就往外继续找a,所以输出的结果为1

       2;  //逐行解析后a被赋值为2

  C.

var a=2;

function fn(a){

     console.log(a);

      a=2;     //全局变量

}

fn();

console.log(a);

预解析为:

        a:undefined;

        fn{ a:undefined; }   //fn里面参数a,预解析时等同于局部变量

输出结果为:

       undefined;     //先在fn里面找变量a,没找到就往外继续找a,所以输出的结果为1

     1;  //逐行解析后a被赋值为2

7、内存问题

(1)离开作用域的值将被标记为可收回,将在垃圾收集期间删除;

(2)标记清除是目前主流的垃圾收集算法(另一种引用计数法存在循环引用等缺陷被摒弃);

(3)标记清除就是给不用的值加标记,然后回收其内存;

(4)引用计数法可能因为循环引用的问题而得不到释放(解决办法就是在使用完后赋值为null);

(5)当变量不用的时候,可以手动解除它的引用(赋值为null)。