JS作用域与JS代码的运行

第7章 作用域与JS代码的运行

作用域:变量可以起作用的范围和区域

7.1 全局变量和局部变量

7.1.1 局部变量与全局作用域

在任何地方都可以访问到的变量就是全局变量,全局变量所在的区域就是全局作用域

7.1.2 局部变量

只在固定的代码片段内可访问到的变量,最常见的例如函数内部的变量,就是局部变量。局部变量所在的区域就是局部作用域(函数作用域)

不使用var声明的变量是全局变量,不推荐使用。
变量退出作用域之后会销毁,全局变量关闭网页或浏览器才会销毁


: 除了全局作用域和局部作用域外 , 还有块级作用域, 如 for循环 和 if语句 中定义的变量

7.1.3 块级作用域 :

一对大括号就可以看成是一块 , 在这对大括号里使用的变量 , 只能在这个区域中使用 . 但是在js中 , 在这个块级作用域中定义的变量 , 外面也能使用 就是没有块级作用域 , 只有函数除外

for(var i=0; i<5; i++){
    var a = 9;  //块级作用域
    console.log(a+i);
}
7.1.4 隐式全局变量 :

声明的变量没有var , 就叫做全局变量

a = 2;  //隐式全局变量
function f1(){
    b = 3;   //隐式全局变量
}

7.2 JS代码的运行

console.log(s); //undefined
var s = 2;

JavaScript代码的执行是由浏览器中的JavaScript解析器来执行的。

JavaScript解析器执行JavaScript代码的时候,分为两个过程:预解析(编译)过程和代码执行过程

预解析过程:

  1. 语法检查,如果有错误,直接停止后续步骤不再运行。

  2. 把变量和函数的声明提升到当前作用域的最前面,只会提升声明,不会提升赋值和调用。

  3. 先提升变量后提升函数,如果函数和变量同名,则被替换;

代码执行过程

变量的赋值,函数的调用,循环判断等,根据代码由上往下顺序执行;

var a = 25;
function abc (){
  alert(a);//undefined
  var a = 10;
}
abc();
​
// 如果变量和函数同名的话,函数优先做提升
console.log(a);
function a() {
  console.log('aaaaa');
}
var a = 1;
console.log(a);
// 1、----------------
var num = 10;
fun();
function fun() {
    console.log(num); //undefined
    var num = 20;
}
​
// 2、----------------
var a = 18;
f1();
function f1() {
    var b = 9;
    console.log(a); //undefined
    console.log(b); // 9
    var a = '123'; 
}
​

7.3 词法作用域

变量的作用域是在定义时决定而不是执行时决定的,也就是说词法作用域取决于编译阶段,通过静态分析就能确定,因此词法作用域也叫做静态作用域。

在 js 中词法作用域规则:

  • 函数允许访问函数外的数据.

  • 整个代码结构中只有函数可以限定作用域.

  • 作用域规则首先使用提升规则分析

  • 如果当前作用规则中有名字了, 就不考虑外面的名字

var num = 123;
function foo() {
  console.log( num );
}
foo();
​
if ( false ) {
    var num = 123;
}
console.log( num ); // undefiend

也就是说:

函数内部可以访问函数外部的变量,但是函数外部不可以访问函数内部的变量;

函数内部如果有变量,则优先使用内部的变量,如果函数内部没有,才会使用函数外部的变量;

7.4 变量的提升

console.log(a); // undefined
var a = 2;
console.log(a); //   a is not defined
  • 变量提升

    定义变量的时候,变量的声明会被提升到作用域的最上面,变量的赋值不会提升。

  • 函数提升

    JavaScript解析器首先会把当前作用域的函数声明提前到整个作用域的最前面

f();
function f(){
    console.log(12); //12
}
var f = 1;
function f(){
    console.log(12); //12
}
// 由于函数提升在前,所以被变量声明替换了;
// 执行阶段,变量赋值为1,不再是一个函数,
f(); // f is not a function

注:不管是普通变量还是函数,尽量不要出现重名;

7.5 作用域链

只有函数可以制造作用域结构, 那么只要是代码,就至少有一个作用域, 即全局作用域。凡是代码中有函数,那么这个函数就构成另一个作用域。如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域。
将这样的所有的作用域列出来,可以有一个结构: 函数内指向函数外的链式结构。就称作作用域链。


var a = 1;
function fn1(){
    function fn2(){
        function fn3(){
            console.log(a);
        }
        fn3();
    }
    fn2();
}
fn1();
var a = 1;
function fn1(){
    var a = 2;
    function fn2(){
        var a = 3;
        function fn3(){
            console.log(a);
        }
        fn3();
    }
    fn2();
}
fn1();

7.6 预解析

JavaScript代码是由浏览器中的JavaScript解析器来执行的, JavaScript解析器执行JavaScript代码的时候,分为两个过程 , 预解析过程和代码执行过程.

  • 把变量的声明提升到当前作用域的最前面 , 只会提升声明 , 不会提升赋值

  • 函数的声明提升到当前作用域的最前面 , 只会提升声明 , 不会提升调用

  • 先提升var , 再执行function

//1--------------------
var num;
console.log(num);   //undefined//2---------------------
function f1(){
    console.log(111);
}
f1();  //2222
function f1(){
    console.log(2222);
}
f1();  //2222//3----------------------
function f1(){
   console.log(num);   //undefined
   var num = 10;
}
f1();
console.log(num);   //报错

预解析中 , 变量的提升 , 只会在当前的作用域中提升 , 提前到当前的作用域的最上面

函数中的变量只会提前到函数的作用域的最前面 , 不会出去

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值