预览加载中,请您耐心等待几秒...
1/7
2/7
3/7
4/7
5/7
6/7
7/7

在线预览结束,喜欢就下载吧,查找使用更方便

如果您无法下载资料,请参考说明:

1、部分资料下载需要金币,请确保您的账户上有足够的金币

2、已购买过的文档,再次下载不重复扣费

3、资料包下载后请先用软件解压,在使用对应软件打开

关于js的作用域链,早有耳闻,也曾看过几篇介绍性的博文,但一直都理解的模棱两可。近日又精心翻看了一下《悟透Javascript》这本书,觉得写得太深刻,在“代码的时空”一节里有一段介绍作用域链的地方寥寥数语,回味无穷(其实还是理解的模棱两可^_^)。现在整理下自己的读书笔记,顺便借鉴网上资源,写下来。一、从一个简单的问题说起下面的js代码在页面中运行显示什么结果:JavaScript代码1.vararg=1;2.functionfucTest(arg){3.alert(arg);4.vararg=2;5.//alert(arg);6.}7.fucTest(10);您的答案是什么?没错,就是弹出10。我的理解是这样的,funTest函数有一个形参arg,funTest函数传入实参10,alert方法把10弹出就是了,囧。好,问题又来了:JavaScript代码1.vararg=1;2.functionfuncTest(){3.alert(arg);4.vararg=2;5.}6.arg=10;7.funcTest();答案是什么?如果是5年前的我,肯定不会再往下想了,还是10!这么简单的问题还用想什么呀?我的理解是这样的:funTest函数是一个无参数的函数,函数内部通过alert方法,调用外部(全局)的变量arg,在函数执行前,arg赋值为10,弹出arg值后改变arg值为2,所以弹出值为10。真的是10吗?是还是不是?测试的结果:弹出“undefined”,瀑布汗.二、理解作用域链,从javascript运行机制说起1、js的运行顺序如果一个文档流中包含多个script代码段(用script标签分隔的js代码或引入的js文件),它们的运行顺序是:步骤1.读入第一个代码段(js执行引擎并非一行一行地执行程序,而是一段一段地分析执行的)步骤2.做语法分析,有错则报语法错误(比如括号不匹配等),并跳转到步骤5步骤3.对var变量和function定义做“预解析”(永远不会报错的,因为只解析正确的声明)步骤4.执行代码段,有错则报错(比如变量未定义)步骤5.如果还有下一个代码段,则读入下一个代码段,重复步骤2步骤6.结束上面的分析已经足够清楚,步骤二、三和步骤四里的红色字体可能是我们新手理解上的一个盲点,尤其是步骤三的“预解析”,如果不清楚什么叫预解析,总觉得不踏实。而步骤四的“有错则报错”也是经常碰到的。举例来说:JavaScript代码1.functionfuncTest(){2.alert(arg);3.vararg=2;4.}5.funcTest();上面这段代码执行时,弹出“undefined”,也就是说arg没有定义,js的变量不是不用定义也可以吗?2、语法分析和“预解析”(1)、从解释型语言的编译过程说起众所周知,javascript是解释型语言,它不同于c#和java等编译型语言。对于传统编译型语言来说,编译步骤分为:词法分析、语法分析、语义检查、代码优化和字节生成;但对于解释型语言来说,通过词法分析和语法分析得到语法树后,就可以开始解释执行了。a、词法分析简单地说,词法分析是将字符流(charstream)转换为记号流(tokenstream)。但是这个转换过程并不是可以用一句话就可以概括的那么简单,我们可以试着用伪代码理解一段简单的程序:代码varresult=x-y;的转换大致可以表示如下:NAME"result"EQUALSNAME"x"MINUSNAME"y"SEMICOLONb、语法分析简单地说,语法分析就是为了构造合法的语法分析树,而语法分析树可以直观地表示出推导的过程。那么什么是语法分析树?简单地说,就是程序推导过程的描述。但是到底什么是语法树,请参考专业文章,本篇略过。c、其他通过语法分析,构造出语法分析树后,接下来还可能需要进一步的语义检查。对于传统强类型语言来说,语义检查的主要部分是类型检查,比如函数的实参和形参类型是否匹配等等。结论:通过上面的分析可以看出,对于javascript引擎来说,肯定有词法分析和语法分析,之后可能还有语义检查、代码优化等步骤,等这些编译步骤完成之后(任何语言都有编译过程,只是解释型语言没有编译成二进制代码),才会开始执行代码。(2)、执行过程a、javascript的作用域机制通过编译,javascript代码已经翻译成了语法树,然后会立刻按照语法树执行。进一步的执行过程,需要理解javascript的作用域机制:词法作用域(lexcicalscope)。通俗地讲,就是javascript变量的作用域是在定义时决定而不是执行时决定,也就是说词法作用域取决于源码,编译器通过静态分析就能确定,因此词法作用域也叫做静态作用域(staticscope)。但需要注意,with