[持续更新]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,循环体中不断输出i(0-9),当i=9时,最后一次执行循环体,然后i++ (i=10),来到判断条件,不符合,则跳出循环,向下执行,打印输出i=10。
这个例子看出来,在函数内部,定义了局部变量,这些变量在函数内部,均可以被使用。
至于a,按照我之前的认识,a打印出undefined没问题,但是a存在,未被赋值,我就不认同,若没有执行if大括号内的语句,应该不会创建a,a应该不存在。这就引出了我们的第二个问题。
我们应该知道,当在函数内部定义变量时,
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,他就是boss,a应该写成window.a,只是window我们习惯不写,想想alert,为什么他直接写就能运行。
c.作用域链
每段js代码都有一个与之相关的作用域链,这个作用域链可以是一个对象列表或者一个链表,这组对象定义了这段代码可以使用的变量,以及每个变量在哪定义的。
当我需要一个变量x时,js按照作用域链来进行查找,首先查找作用域最大的全局变量,如没有,则往下查找,找与他自身相关的局部变量,直到找到该变量为止,如没找到,则抛出引用错误异常。
举个例子:
当f2需要变量时,首先查找(1)的位置,如没有,则查找(2)的位置,在没有则查找(3)位置,以此类推。
需要说明一句的是,函数的参数,算上一级的作用域里,也就是说,f1的参数是(1)中的变量,f2的参数,是(2)的变量。
- [持续更新]JavaScript学习笔记(二)
- JavaScript学习笔记(持续更新)
- [持续更新]JavaScript学习笔记(一)
- [持续更新]JavaScript学习笔记(三)
- [持续更新]JavaScript学习笔记(四)
- [持续更新]JavaScript学习笔记(五)
- [持续更新]JavaScript学习笔记(六)
- [持续更新]JavaScript学习笔记(七)
- [持续更新]JavaScript学习笔记(八)
- [持续更新]HTML5学习笔记(二)
- iOS学习笔记总结二(持续更新)
- JavaScript学习【持续更新】
- 指针学习笔记(持续更新)
- spring学习笔记(持续更新)
- C语言学习笔记(持续更新)
- cocos2d-x学习笔记(持续更新)
- Java学习笔记(持续更新)
- oracle学习笔记(持续更新)
- C++ 数据的保护(const)
- 多线程
- SQL SERVER 2008:内部查询处理器错误: 查询处理器在执行过程中遇到意外错误
- Java:日期字符串格式大小比较
- 黑马程序员----排序算法分析与总结
- [持续更新]JavaScript学习笔记(二)
- MacRitchie Reservoir hiking
- 《笨方法学python》-2
- Java 正则表达式
- HDOJ 5372 Segment Game 树状数组+离散化
- CSS 参考
- 查找满足大于左边小于右边的数
- 【Hadoop系列第十章】(二)数据分析系统Pig
- [Vijos]P1282 佳佳的魔法照片