JavaScript_个人笔记7_javascript作用域链
来源:互联网 发布:自然排名优化的方法 编辑:程序博客网 时间:2024/06/05 10:51
JS里面,一切对象。说到对象,就有属性。JS里面的属性分为两种:一种是可以通过代码可以访问的,一种是js内部访问的,其中,内部访问的,有一个[[scope]]值得注意,特别是是javascript的函数。
函数的作用域链():包含函数创建的作用域中的对象集合,这个集合被称作是作用域链。
执行上下文(EC):本身也是一个对象,用于定义对象的执行环境。
活动对象:活动对象包含了EC+对象的执行上下文。
全局对象总是放在作用域链的末端,这样一来,在一个函数里面,强烈建议使用局部变量,特别是针对多次使用的全局变量,在函数里面也最好使用局部变量进行索引。
下面结合一个具体的例子来说明:
<!DOCTYPE html><html> <head> <meta charset="UTF-8"><title>Javascript测试</title><script type="text/javascript"> var globalNum = 10; function modifyData(){ globalNum = 200; return; function globalNum(){ //Do Nothing } } modifyData(); alert(globalNum);</script></head> <body> </body></html>
这个页面打开弹出的数字是多少呢? 10? 200?
---------------------------------------------------------------------------------------------------------------------------
这个问题考查几个点:
1)函数声明函数的创建机制问题
函数声明的函数,其在进入上下文时已经创建,这也是为什么我们可以把一个函数声明写在调用后面,函数还能正常工作的原因;另外,我们可以通过函数声明的函数名称调用函数也是因为,函数名称其实就是对于函数对象的引用,即指向函数,如果将alert里面的内容换成 modifyData,那么弹出的对话框上面的内容就会是函数声明的内容,所以,从代码的角度来看,函数声明的作用就是定义了一个对象变量,其对象的名称是 函数名称。同时,这个跟是否执行被执行无关,可以认为在执行前就会有的一个初始化工作,同时,也可以引申一点,JS不会针对函数申明的函数在代码中是否会被执行而决定是否创建。
2) 对象的作用域链问题
前面说到任何对象都有一个作用域链,且全局对象对象集合总是在作用域链的末端,这种设计是有用意的,这样的设计对于处理同名对象就很方便。在运行时,任何一变量都需要解析,这个解析就是通过活动对象,根据活动对象中的作用域链,依次从前向后找,找到就返回,这样一来,涉及到同名的对象,总是局部变量优先。
3 变量的类型是由其值决定的
一个变量被赋值一个数字,那么它就是一个number类型,被赋值一个函数,那么它就是一个function
依据这两点,上面的答案就很明显了:
1) 首先看modifyData函数,我们看到有一个函数声明,这样一来,它内部本身就有一个globalNum的函数对象,那么在执行 globalNum=200这条语句时,就会执行查找,正好,我们找到了一个globalNum,那么就会将其改写成200,但是,记住,当前modifyData中,globlNum变成了一个number类型变量,同时这个globalNum只是针对modifyData而言的
2) 输出函数alert里面,活动对象已经变了,那么全局对象global就是之前申明的,这样一来,最终输出的还是原来的对象。
为了验证modifyData里面的变量变化,可以将代码稍稍修改如下:先调用函数,再改写,再调用函数
<!DOCTYPE html><html> <head> <meta charset="UTF-8"><title>Javascript测试</title><script type="text/javascript"> //var globalNum = 10; function modifyData(){ globalNum(); globalNum = 200; globalNum(); return; function globalNum(){ alert("I am function");
realGlobal = 11; } } modifyData(); alert(globalNum); //这里会报错,那个globalNum并不是所谓的 没有var修改的局部变量,而是在执行前已经创建好的变量,
alert(realGlobal); //这个能够打印出来,在函数里面没有var修饰的变量是全局的!!!!
</script></head> <body> </body></html>
稍稍总结一下: 1 在页面初始化时,创建一个在modifyData作用域内的全局变量 globalNum, 由于其位于函数内部,所以,我们称之为局部变量,同时这个函数是基于modifyData这个函数的,是一个局部函数,只能在函数内部执行
2 在modifyData中,所有的globalNum都是那个局部变量,那个变量先是一个function类型,可以使用一对小括号进行调用,而被赋值后,它变成了一个number类型,但是这个过程并没有创建一个新的变量,所以,其访问作用域还是在函数内部。
3 一个函数里面的变量可以在外部调用,需要满足三个条件:1) 没有同名的函数声明 2)没有var修饰 3)函数执行过
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>Javascript测试</title> <script type="text/javascript"> function modifyData(){ globalNum(); globalNum = 200; alert(typeof globalNum); function globalNum(){ relativeGlobal = 20; alert("globalNum is called!"); } } modifyData(); alert(relativeGlobal); //globalNum(); modifyData(); </script> </head> <body> </body></html>
- JavaScript_个人笔记7_javascript作用域链
- JavaScript_个人笔记2_JavaScript的变量
- JavaScript_个人笔记3_JavaScript扩展
- JavaScript_个人笔记3_JavaScript的函数
- JavaScript_个人笔记1_JavaScript的面向对象是模仿的
- 12_JavaScript 作用域
- JavaScript_个人笔记6_再说函数
- JavaScript_事件、函数、变量作用域
- JavaScript_个人笔记5_JavaScript_event相关的重要参数
- JavaScript_个人笔记8_js的闭包closure
- JavaScript_个人笔记9_悟透js闭包
- 黑马程序员_javaScript笔记
- JavaScript_异常_笔记
- JavaScript_个人笔记10_由一个JS语法错误想到的
- JavaWeb学习笔记02_javascript
- [知了堂学习笔记]_JavaScript
- JavaScript_查找指定节点之后的下一个元素节点_getNextElement(node)_JavaScript扩展
- JavaScript作用域个人理解
- C/C++头文件与实现文件中的内容安排
- 最短路+树分治(hdu4871多校联合)
- 在Cocos2d-X3.0中使用瓦片地图中的对象层
- 第5周项目【项目2 - 对象作为数据成员】
- 等差数列
- JavaScript_个人笔记7_javascript作用域链
- GOF23设计模式之中介者模式的理解
- UI界面写学习积累
- java 类型
- 利用顺序表实现优先队列的插入和删除操作
- GOF23设计模式之中介者模式的实现
- java IO流 之 处理流
- #if, #if defined, #ifdef, #ifndef, #elif, #else, #endif 使用
- 海龟交易系统R代码