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>

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 吃斋念佛的句子下一句 左手吃斋影视手机版 康复新液饭前吃还是饭后吃 康复新液饭前还是饭后吃 黛力新一般要吃多久 黛力新为什么中午12点不能吃 黛力新能长期吃吗 工藤新一吃宫野志保乳 新生化颗粒要吃多久才停血 骨头坏死吃什么长新骨 2018新版本吃鸡怎么换日韩服 新家开火第一餐该吃什么 宫内残留吃益母草还是新生化 新场古镇必吃小吃 新藏线厕所被狼吃 吃什么有助于新陈代谢 吃什么加快新陈代谢 哪些人不适合吃胃乐新 医生为什么不建议吃代力新 比智高增高一般建议吃多久 西比灵为什么晚上吃 为什么西比灵要吃5天停两天 西比灵为什么要吃五天停两天 吃鳗鱼比长短打一生肖 吃比智高有什么危害性 gtx1660比1060吃鸡哪个好 颈椎病可吃西比林吗 西比灵一天吃几次 特比萘芬片灰指甲吃多久 比弟子吃 教授懵比日常 喵崽要吃草 盐酸特比萘芬片怎么吃 下焦湿热吃什么药 柿子和香焦能一起吃吗 下焦湿热吃什么中成药 香焦不能和什么一起吃 焦山楂什么人不能吃 香焦不能和什么食物一起吃 吃焦糖瓜子会胖吗 孕妇可以吃焦糖瓜子吗 下焦湿热吃什么食物