作用域、JS预解析机制

作用域:
域:空间 
    script、全局变量 全局函数 自上而下
    函数:由里往外

作用:读、写
浏览器对JS解析机制:
1:预解析:碰到var function 参数会将这些预存到仓库
2:逐行读代码:表达式 =+-*/% 参数
例子1:
alert(a);   //function a(){alert(4);}   
var a = 1;
alert(a);//1
function a(){alert(2);}//函数的声明直接往下读
alert(a);//1
var a = 3;
alert(a);//3
function a(){alert(4);}//函数的声明直接往下读
alert(a);//3
alert(typeof a)//number
a();//函数调用 仓库已经不存在任何函数了-->相当于3();//会报错 a is not a function
1:预解析:找一些东西 var function 参数(放入仓库)
    01:a = 未定义
        a = function a(){alert(2);}
         注:一旦出现重名的,会只留一个(和上下文没有关系,变量和函数重名,就只留下函数)
    02:a = function a(){alert(2);}
        a = 未定义;
        踢出未定义
    03:a = function a(){alert(2);}
        a = function a(){alert(4);}
        函数遇到函数根据上下文的关系保留a = function a(){alert(4);}
例子2:
alert(a);//undefined
var a = 1;
alert(a)//1
function fn1(){alert(2)}
1:预解析:找一些东西 var function 参数(放入仓库)
    a = 未定义所有的变量在正式运行代码前都提前赋了一个值:未定义    
    fn1()=function fn1(){alert(2)}

2:逐行读代码(从仓库读取)
    //var a function fn1(){alert(2)}函数声明
    //a=1表达式 +-*/%++--! Number()参数; 做一些改变的动作
例子3:
var a = 1;
function fn1(){
    alert(a);//undefined
    var a = 2; 
}
fn1();
alert(a);//1
1:预解析:
    a = 未定义
    fn1 = function fn1(){alert(a);var a = 2;}

2:逐行读代码:
    a = 1;
        遇到函数声明直接跳
        遇到函数调用再次触发预解析:
            01:预解析:
                碰到var 定义变量 a = 未定义
            02:读代码:
                优先的从局部范围内查找有没有定义一个a的值
例子4:
var a = 1;
function fn1(){
    alert(a);//1
    a = 2;//修改全局的a
}
fn1();
alert(a);//2
1:预解析:
    a = 未定义
    fn1 = function fn1(){alert(a); a = 2;}
2:逐行读代码:
    a = 1;
    函数声明直接跳
    遇到函数调用再次触发预解析:
    01:预解析:没有var function 参数直接读代码               
    02:读代码:
        优先的从局部范围内查找有没有定义一个a的值 如果没有会顺着子级作用域往父级作用域找(作用域链)
例子5:
var a = 1;
function fn1(a){
//function fn1(var a;){
    alert(a);//undefined
    a = 2;
    alert(a);//2
}
fn1();
alert(a);//1
1:预解析:
    a = 未定义
    fn1 = function fn1(){alert(a); a = 2;alert(a);}
2:逐行读代码:
    a = 1;
    函数声明直接跳
    遇到函数调用再次触发预解析:
        01:预解析:
            参数本质上就是局部变量var a
            a= undefined
        02:读代码:
            根据就近原则里面有个a = undefined
例子6:
var a = 1;
function fn1(a){
//function fn1(var a = 1){
    alert(a);//1
    a = 2;
}
fn1(a);//里面的参数来自全局
alert(a);//1
1:预解析:
    a = 未定义
    fn1 = function fn1(a){alert(a); a = 2;}
2:逐行读代码:
    a = 1;
    函数声明直接跳
    遇到函数调用再次触发预解析:
        01:预解析:
            参数本质上就是局部变量var a
            a= undefined
        02:读代码:
            从参数开始读
            全局上的a = 1赋值给局部变量a;
调用局部函数
01:通过全局变量
var num = 0;
function fn1(){
    num++;
}
function fn2(){
    num--;
}
fn2();
fn1();
fn2();
alert(num)//-1
//想要获取fn1内部a的值,定义一个全局变量str
var str = "";
function fn1(){
    var a = "快获取我";
    str = a;
}
fn1();
alert(str);
02:通过局部的函数调用来获取
function fn1(){
    var a = "快获取我";
    fn2(a);
    /*
        代码读到这块的时候,代码先读取的是fn2;然后在这个fn1里面查找,如果没找到就会返到父级进行查找,这时候父级已经把fn2给预解析里面了,所以就是说函数fn1里面可以调用fn2
    */
}
function fn2(a){
    alert(a);
}
fn1();
for嵌套函数中的i取值
<!-- html代码片段 -->
<input type="button" value="按钮1" />
<input type="button" value="按钮2" />
<input type="button" value="按钮3" />
window.onload = function(){
    var aBtn = document.getElementsByTagName("input");//局部
    /*var i=0;
    function(){
        alert(i);//3
        //aBtn[i].style.background = "yellow";
    }*/
    for(var i=0;i<aBtn.length;i++){
        aBtn[i].onclick = function(){
            alert(i);//undefined
            //aBtn[3].style.background = "yellow";会报错
            for(var i=0;i<aBtn.length;i++){
                //i :0 1 2
                aBtn[i].style.background = "yellow";
            }
        }
    }
}
第一种情况:这种情况下由于for的执行速度大于btn的点击事件,所以当btn触发点击的时候for已经走完,此时i的值就是btn.length btn点击触发函数的作用域,开始预解析和逐行解读代码内部没有var 不存在i这个变量会往父级查找,父级i=3,所以会弹出3,并且还会报错
    for(var i=0;i<aBtn.length;i++){
        aBtn[i].onclick = function(){
            alert(i);//3
            aBtn[i].style.background = "yellow";//会报错
            //aBtn[3].style.background = "yellow";
        }
    }
第二种情况:btn点击函数体内再嵌套一层for,此时外层的for已走完,外层i=3,点击的时候触发作用域,触发预解析和逐行读代码;找到内层for循环里的var i 预解析成i=undefined,所以此时弹出的i为undefined
    for(var i=0;i<aBtn.length;i++){
        aBtn[i].onclick = function(){
            alert(i);//undefined
            for(var i=0;i<aBtn.length;i++){
                //i :0 1 2
                aBtn[i].style.background = "yellow";
            }
        }
    }
第三种情况:btn点击函数体内再嵌套一层for,此时外层的for已走完,外层i=3,点击的时候触发作用域,触发预解析和逐行读代码;预解析时没有找到var,表示里面不存在i这个变量,会返回到父级查找,此时的父级外面的i是3,所以此时弹出的i就是3
    for(var i=0;i<aBtn.length;i++){
        aBtn[i].onclick = function(){
            alert(i);//3
            for(i=0;i<aBtn.length;i++){
                //i :0 1 2
                aBtn[i].style.background = "yellow";
            }
        }
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值