博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JavaScript基础学习--08 JS作用域
阅读量:6554 次
发布时间:2019-06-24

本文共 3717 字,大约阅读时间需要 12 分钟。

Demos:     

 

一、浏览器
     1、“JS解析器”(至少分为两步骤)
          1.1     JS预解析(代码正式运行之前的准备工作)     “找一些东西并形成一个
仓库”:var、function、参数
               1.1.1     var a = 1;                                        找到var a = undefined     (所有的变量在正式运行代码之前,都提前赋值:未定义;--》undefined)
               1.1.2     function fn(){ alert(......); }                  找到fn =  function fn(){ alert(......); }    (所有的函数在正式运行之前都是整个函数块)
               1.1.3    
预解析规则
                    1.1.3.1     遇到
重名的:
只留一个------变量和函数重名,选择留下函数;同等级的留下后面那个(两个变量重名留后者;两个函数重名留后者)
                    1.1.3.2     表达式可以修改仓库中的值     
                         1.1.3.2.1     表达式:+-*/ Number()......     注意:函数只是一个声明,不是表达式
 
          1.2     逐行解读代码
1 alert(a);   // function a(){alert(4);} 2 var a = 1;  // 表达式能改变仓库中(预解析仓库)的值---> a = 1 3 alert(a);   // 1 4   5 function a() {  //函数声明不是表达式,不能改变a的值 6     alert(2); 7 } 8 alert(a);   // 1 9 var a = 3;  //  表达式能改变仓库中(预解析仓库)的值---> a = 310 alert(a);   // 311  12 function a() {  //函数声明不是表达式,不能改变a的值13     alert(4);14 }15 alert(a);   // 316  17 a();     //a is not a function 报错,因为此时仓库中已经没有函数a了18  19  20       21 模拟浏览器解析:22 预解析:23 a = undefined24 a = function a(){alert(2);}25 a = undefined26 a = function a(){alert(4);}27 综上,最后 a = function a(){alert(4);}28 所以 ......
     
二、作用域     只要是一个域,就会发生预解析。其中script标签是一个域
     1、每个script标签代表一个域块,从上到下的顺序,执行完一个script块中 js(预解析+逐行读代码) 才执行下一个script(如果有的话)
     2、script是全局变量、全局函数
     3、函数也是一个域,所以遇到函数执行时也会发生至少两步骤:预解析+逐行读代码     读代码:
由里而外,作用域链
     4、{} 也是一个域,所以遇到 {} 执行时也会发生至少两步骤:预解析+逐行读代码
1 var a = 1;  // a = 1 2 function fn(){  //fn不变 3     alert(a);   //  // undefined 4     var a = 2;  //  // a = 2 5 } 6 fn();   // // 开始fn的预解析+逐行读代码 7 alert(a);   //完成fn代码域的js解析,这是全局下的a ---> // 1 8   9 模拟浏览器解析:10 预解析:11     a = undefined12     fn = function fn(){alert(a); var a = 2;}13 综上:读代码 //14  15 fn 中的预解析:16     a = undefined17 综上:读代码 // //
 
1 var a = 1; // a = 12 function fn() { //fn不变3     alert(a); //  // 预解析的仓库中没有,此时作用域链发生作用,由里而外,局部没有,找全局中a = 14     a = 2; //  // a = 25 }6 fn(); // // 开始fn的预解析+逐行读代码7 alert(a); //完成fn代码域的js解析,这是全局下的a,并且被局部函数中的表达式改变了值 ---> // 2
模拟浏览器解析:
预解析:
a = undefined
fn = function fn() { alert(a); var a = 2; }
综上: 读代码 //
 
fn 中的预解析:
仓库为空
综上: 读代码 // //
1 var a = 1; // a = 1 2 function fn(a) { //fn不变 3     alert(a); //  // 预解析仓库中有,就优先预解析仓库的值---> undefined 4     a = 2; //  // a = 2 修改的是仓库中的a,没有修改全局的 a 5 } 6 fn(); // // 开始fn的预解析+逐行读代码 7 alert(a); //全局中的a  1 8   9  10  11 模拟浏览器解析:12 预解析:13 a = undefined14 fn = function fn(a) { alert(a); var a = 2; }15 综上: 读代码 //16  17 fn 中的预解析:18 a = undefined //这是参数a,也是被预解析的对象19 综上: 读代码 // //
1 var a = 1; // a = 1 2 function fn(a) { //fn不变 3     alert(a); //  // 预解析仓库中有,并且传值a = 1(fn(a) == fn(var a = 实参a
<如果有传参的话>
))就优先预解析仓库的值---> 1 4 a = 2; // // a = 2 修改的是仓库中的a,没有修改全局的 a 5 } 6 fn(a); // // 开始fn的预解析+逐行读代码 7 alert(a); //全局中的a 1 8 9 模拟浏览器解析:10 预解析:11 a = undefined12 fn = function fn(a) {alert(a);var a = 2;}13 综上: 读代码 //14 15 fn 中的预解析:16 a = undefined //这是参数a,也是被预解析的对象17 综上: 读代码 // //

 

为了防止预解析浏览器兼容:尽量不要在if、for中定义函数、定义变量等等
1 alert(fn);  //预解析中if、for不是一个作用域,所以里面的变量相当于全局变量,所以弹出function fn(){alert(2);}2             //但是,在FF浏览器中有兼容性,会报错,fn未定义!!!3 if(true){4     function fn(){5         alert(2);6     }7 }
 
注意:for循环内部的函数与i
1 for (var i = 0; i < 3; i++) { 2     oBtn.onclick = function() { 3         alert(i); //undefined     原因是函数内部是一个域,内部找到var i---> i预加载是undefined 4         for (var i = 0; i < 3; i++) { 5             ...... 6         } 7     } 8 } 9  10 for (var i = 0; i < 3; i++) {11     oBtn.onclick = function() {12         alert(i); //3     原因是函数内部是一个域,预加载时没有变量,于是第二部在逐行读代码的时候找不到i,到作用域链上(外部)找到i = 3,所以313         // for (var i = 0; i < 3; i++) {
14 // ......15 // }16 }17 }18 19 for (var i = 0; i < 3; i++) {20 oBtn.onclick = function() {21 alert(i); //3 原因是函数内部是一个域,预加载时没有变量,于是第二部在逐行读代码的时候找不到i,到作用域链上(外部)找到i = 3,所以322 for (i = 0; i < 3; i++) {23 ......24 }25 }26 }

 

转载于:https://www.cnblogs.com/hihao/p/7344684.html

你可能感兴趣的文章
数据归一化和两种常用的归一化方法
查看>>
React.js初探(一)
查看>>
Neo4j CQL -(17)- NULL值
查看>>
BZOJ4554: [Tjoi2016&Heoi2016]游戏 luoguP2825 loj2057
查看>>
json_encode后的中文不编码成unicode
查看>>
iOS 导航栏title显示右偏移
查看>>
字符串处理 2015百度之星资格赛 1002 列变位法解密
查看>>
修改纵断面图标注栏
查看>>
Flex创建带有空间信息的椭圆(Polygon)
查看>>
【转】参照protobuf,将json数据转换成二进制在网络中传输。
查看>>
wpf 输入停止一段时间后。执行事件
查看>>
享元模式
查看>>
Python中的str与bytes之间的转换的三种方法
查看>>
java异常常见面试问题
查看>>
课后作业5
查看>>
Centos7.1环境下搭建BugFree
查看>>
共用y轴的双图形绘制
查看>>
(错误) Eclipse使用Maven创建Web时错误
查看>>
第31讲 | 数字货币钱包服务
查看>>
P2073 送花
查看>>