【JavaScript】超详细版作用域解析

作用域和变量

1、JavaScript作用域:就是代码名字(变量)在某个范围内起作用和效果,目的是为了提高程序的可靠性,更重要的是减少命名冲突。
2、js的作用域分类(es6):全局作用域局部作用域

  • 全局作用域:整个script标签
  • 局部作用域:函数作用域
var a = "apple";
console.log(a);  //apple
var a = "apple"; //全局
function fighting() {
	var a = 'angel';  //局部
}
console.log(a); // apple

块级作用域

var a='apple';
if(true){
    var a = 'angel';
}
console.log(a);  //'angel'

这其实是一个坑,虽然 if 语句执行完毕后会销毁,但是在js中 if 内内部定义的变量就会变成当前执行环境的变量,这里在最外围,也就是全部变量了,ES6开始定义块级作用域了,这里不过多赘述;除了 if代码块,常见的还有 for循环、while循环也是相似的结构,所以不要被括号所迷惑,在括号内定义的变量不一定就是局部作用域。

作用域链

作用域链(就近原则):函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问。

var a = 'apple';
var b = 'boy';
function fighting() {
    var a = 'angel';
    console.log(a); //angel
    console.log(b)  //boy
}
fighting();
console.log(a);  //apple

作用域表示区域,作用域链表示次序1… 2… 3… ;在JavaScript中首先会查看函数作用域内部有没有这个变量,再看外围有没有这个变量,这里我们看不见的作用域链帮我们安排好了顺序,规定好了从里到外的顺序,那么函数里面有定义这个变量 a,则第一个 a 的值就是angel;再来看 b,发现函数内部没有 b,然后就去找外围的b,也就是全局的变量 b,找到了,输出 b 是 boy;再看最后一个 a,因为是在全局范围内,只能访问全局变量 a,不能访问局部变量 a,因此返回apple。
我们可以把作用域链想象为铺地砖,铺地砖一般都是从里到外,从里到外铺地砖可以防止把地砖弄脏,从外到里每次铺地砖都要经过外面这层才能抵达。

声明提升

JavaScript代码是由浏览器中的JavaScript解析器来执行的,JS解析器在运行代码的时候分为两步:预解析代码执行

  • 预解析:js引擎会把js里面所有的 var 还有 function 提升到当前作用域的在前面
  • 代码执行:按照代码书写顺序从上外下
var a = 'apple';
function fighting() {
    console.log(a); //undefined
    var a = 'angel';  //局部变量
    console.log(a); //angel
}
fighting();
// 在代码执行之前上面的代码会自动把顺序变成下面的
var a = 'apple';
function fighting(){
    var a;  //声明提升了
    console.log(a);
    a = 'angel';
    console.log(a)
}
fighting();

函数里面的函数也会被提升上去,提升会比变量更优先

var a = 'apple';
function fighting() {
    console.log(a);  //undefined
    var a = 'angel'; 
    console.log(ss()); 
    function ss(){  // angel //函数里面的函数也会被提升上去,提升会比变量更优先
        return a;
    }
}
fighting();
// 上面的代码在执行前会按下面这个顺序
var a = 'apple';
function fighting(){
    function ss(){
        return a;
    }
    var a;
    console.log(a);
    a = 'angel';
    console.log(ss());
}
fighting();

最后,用一个综合一点的例子:

var b = 'boy';
console.log(b); //boy
function fighting(){
    console.log(a); //undefined
    console.log(c); //undefined
    if(a === 'apple'){a = 'Alice'}
    else{a = 'Ada'}
    console.log(a); //Ada
    var a = 'Andy';
    midlle();
    function midlle(){
        console.log(c++); //undefined
        var c = 100;
        console.log(++c); //101
        small();
        function small() {console.log(a);} //Andy
    }
    var c = a = 88;
    function bottom(){
        console.log(this.b); //此时this指向全局变量boy
        b = 'baby'; //如果在函数里面声明变量前没有var的话,他就是一个全局变量;一般不建议使用
        console.log(b); //baby
    }
    bottom();
}
fighting();
console.log(b); //baby

over!!!

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值