[持续更新]JavaScript学习笔记(二)

来源:互联网 发布:淘宝好评评语 编辑:程序博客网 时间:2024/05/22 05:22

1.变量作用域

这个是个重点,也是前端考察的要点。

一个变量的作用域(scope):是程序员代码中定义这个变量的区域。

这是JavaScript权威指南第六版中对作用域的定义。简单的来说:一个变量定义在全局,就是全局变量,具有全局作用域(在代码中的任何地方都有定义);一个变量定义在函数内部,就是局部变量,只在函数内部有定义;参数也是局部变量,只再函数体内有定义。

a.全局变量与局部变量

JavaScript使用了函数作用域:变量在声明他们的函数体以及函数体嵌套的任意函数体内均有定义。

举个例子:

 

function f1(obj){if(typeof obj == "object"){var a = 0;for(var i = 0; i < 10; i++){console.log(i);//输出0-9}console.log(i);//10}console.log(a);//0 或者undefined}

简单解释下:函数根据参数obj先判断类型,if函数内先定义a,并未赋值,若函数执行到if的大括号内,会给a赋值0,反之,a未赋值,为undefined。这块没听懂的接下来会细讲;for循环中定义了i,循环体中不断输出i0-9),当i=9时,最后一次执行循环体,然后i++ i=10),来到判断条件,不符合,则跳出循环,向下执行,打印输出i=10

这个例子看出来,在函数内部,定义了局部变量,这些变量在函数内部,均可以被使用。

至于a,按照我之前的认识,a打印出undefined没问题,但是a存在,未被赋值,我就不认同,若没有执行if大括号内的语句,应该不会创建aa应该不存在。这就引出了我们的第二个问题。

我们应该知道,当在函数内部定义变量时,

var a = 0;

b = 1

这样写,a定义为函数的局部变量,b没有使用var,定义为全局变量。

但是在函数外部,也就是全局代码中,这样写也是可以的,ab均为全局变量。但是意义就不一样了,以为JavaScript有个声明提前机制。

看个例子:

        var scope = "global";function f1 (){console.log(scope);//undefinedvar scope = "local";//函数名重复console.log(scope);//local}


有些人就比较迷惑了,因为他们认为第一个打印应该为global,我之前也是这么认为的,但是这几天每天的读书都在颠覆我的人生观,使我对JavaScript有了新的更加全面的认识。

声明提前(hoisting):函数内部声明所有变量(不包括赋值),都被提前至函数体的顶部。

通俗地讲,函数内声明变量使用var的时候,var a = 0;就会转变成var a; a=0; 第一句var被提前,于是上面的代码就变成了

 

        var scope = "global";function f1 (){var scope;//声明提前,赋值的地方不变console.log(scope);//undefinedscope = "local";//变量赋值console.log(scope);//local}

这样,就能理解为什么第一次打印为undefined。还要提一句,在函数体内,局部变量的优先级要高于全局变量,所以同名变量,内部覆盖外部。

所以,一些程序员会将变量定义在函数的顶部,而不是在快要用到变量的时候在定义,这样更真实地反映了变量的作用域。

b.作为属相的变量

看小标题是不是没看明白,这就对了,这样你才能仔细阅读这部分。

上一节说道定义全局变量时,使用或者不使用var定义变量,意义不一样的。

看个例子:

 

var a = 1;b = 2;this.c = 3;

这时候你快使用firebug哼哼哈兮看看

 

全局对象存在abc,这时候添加代码:

 

var a = 1;b = 2;this.c = 3;delete a;delete b;delete c;

删除3个全局变量,嗯嗯,应该都删掉了,快去看看firebug

 

a没被删除掉,WTF

声明一个全局变量时,这个变量其实就是全局对象的一个属性。使用var声明一个属性时,这个属性是不可配置的。也就是无法通过delete来删除它;当不使用var定义变量的时候,这个属性时刻配置的,可以删除它们。所以需要大量变量的时候,声明变量要注意,一面声明太对,无法删除。

你有没有想过,一直在说全局变量是全局对象的属性,那全局对象是谁啊?

firebug的左上角,写了一个英文单词window,他就是bossa应该写成window.a,只是window我们习惯不写,想想alert,为什么他直接写就能运行。

c.作用域链

每段js代码都有一个与之相关的作用域链,这个作用域链可以是一个对象列表或者一个链表,这组对象定义了这段代码可以使用的变量,以及每个变量在哪定义的。

当我需要一个变量x时,js按照作用域链来进行查找,首先查找作用域最大的全局变量,如没有,则往下查找,找与他自身相关的局部变量,直到找到该变量为止,如没找到,则抛出引用错误异常。

举个例子:

 

f2需要变量时,首先查找(1)的位置,如没有,则查找(2)的位置,在没有则查找(3)位置,以此类推。

需要说明一句的是,函数的参数,算上一级的作用域里,也就是说,f1的参数是(1)中的变量,f2的参数,是(2)的变量。

0 0
原创粉丝点击