0


javascript作用域

作用域表示当前执行的上下文,值与表达式在其中可见,可以被访问到的上下文,作用域决定了区块代码中的可见性。

js,作用域可分为全局作用域,局部作用域,块级作用,在javascript中一般有三中情况拥有全局作用域,

作用域存在的意义:变量隔离,不同作用域下的同名变量不会出现冲突

** 一、全局作用域**

1.window对象到的属性、方法

console.log(window.alert);

如图,所有的window对象的属性都拥有去全局作用域,之所以javascript中的任何地方都能alert(‘xxxx’),是因为它被定义在了window对象上的一个函数,拥有全局作用域

** 2.定义在最外层的变量、函数、对象**


       c=3 //外层变量

       //最外层函数
       function fun1(){
           //内层变量
           a=1;
           a=2;
               //内层函数
              function fun2(){
                  b=2;
              }
       }
  
  console.log(c);     //3
  console.log(a);     // not definded
   console.log(fun1)  //function fun1()
   console.log(fun2) //fun2 is not defined

变量a与函数fun1拥有全局作用域,在任何地方都可以访问,可,变量b与fun2没有定义在全局作用域里,在全局作用域中无法访问

3.所有未定义直接赋值的变量自动声明为拥有去全局作用域

  function  fun(){
      a=2;
      var b=2;
  }
  fun()//首先的执行一下这个函数不然不知道里面是啥
  
console.log(a)          // 2
console.log(b)          // b is  not defined

b var定义并且赋值了,而变量a只是在函数中直接赋值并没有定义 ,那么变量a,会自动挂到window对象上,拥有全局作用域。

ps: 常量和变量都属于变量,只不过常量是赋过值不能再改的变量,而普通的变量可以进行赋值操作(有人可能会疑问a,明明是常量,(^o^)/~)

**二、局部作用域 **

局部作用域相当于函数作用域,指函数内部的空间,函数内部的变量,外部无法访问

function doSomething(){
    var blogName="xx";
    function innerSay(){
        alert(blogName);
    }
    innerSay();
}
alert(blogName); //脚本错误
innerSay(); //脚本错

作用域是分层的,内层作用域可以访问外层作用域的变量,反之不行。

三、块级作用域

ES5只有全局作用域没和函数作用域,没有块级作用域,这带来很多不合理的场景。

第一种场景,内层变量可能覆盖外层变量:


var tmp = new Date();
 
function f(){
  console.log(tmp);
  if(false){
    var tmp = "hello";
  }
}
 
f(); // undefined

上面代码中,函数f执行后,输出结果为undefined,原因在于变量提升,导致内层的tmp变量覆盖了外层的tmp变量。

第二种场景,用来技术的循环变量泄露为全局变量:

var s = "hello";
for(var i=0;i<s.length;i++){
  console.log(s[i]);
}
console.log(i); // 5

上面代码中,变量i只用来控制循环,但是循环结束后,它并没有消失,泄露成了全局变量。

实际上正是es6,let的出现让javascript拥有了块级作用域

**var ** 无块级作用域


function fun(){
    var n =10
    if(1==true){
       var n=5   
    }
    console.log(n)  //5
}
fun();

let 有块级作用域

//块级作用域
function fun(){
    let n =10
    if(1==true){
       let n=5   
    }
    console.log(n)  //10
}
fun();

var 同一个作用域下可以重复声明


function fun(){
    var n =10
    if(1==true){
       var n=5   
       var n=9//var允许重复声明
    }
    console.log(n)  //9
}
fun();

let 同一个作用域下不能重复声明

//块级作用域
function fun(){
    let n =10
    if(1==true){
       let n=5   //let不允许重复声明
       let n=9
    }
    console.log(n)  // 脚本报错
}
fun();

** 作用域链**

当在某个函数内部作用域中查找某个变量时,如果没有就找到他的父级作用域中去查找,若是父级作用域也没有,就会一层一层往上找,直到找到全局作用域还没找到的话,就结束寻找,认定变量未定义.这种一层一层的作用域嵌套关系,就是作用域链。

案例:

 let a =1;
      function func1(){
          let b=2;
          function func2(){
              let c=3;
              console.log(a);   //输出全局变量a=1,根据作用域链查找
          }
          func2();
      }
       func1();

附一个面试题:

在以下代码中: typeof a 和typeof b的值 分别是什么?

看代码:

 function foo(){
            let a=b=0; 
            a++;
           // return a;
            console.log(a)
        }
        foo();
          console.log( typeof a)     undefined
      console.log( typeof b)        number
        //a????     b???  

我们仔细看看第2行:let a = b = 0。这个语句确实声明了一个局部变量a。但是,它确实声明了一个全局变量b。

在foo()作用域或全局作用域中都没有声明变量 b 直接赋值了”。因此JavaScript将表达式 b = 0 解释为 window.b = 0。

b是一个偶然创建的全局变量。

在浏览器中,上述代码片段相当于:

function foo() {
let a; window.b = 0; a = window.b; a++;
return a;
}

foo();
typeof a; // => 'undefined'
typeof window.b; // => 'number'
typeof a是 'undefined'。变量a仅在 foo()范围内声明,在外部范围内不可用。

typeof b等于'number'。b是一个值为 0的全局变量。


本文转载自: https://blog.csdn.net/qq_54250695/article/details/123023519
版权归原作者 编码~ 所有, 如有侵权,请联系我们删除。

“javascript作用域”的评论:

还没有评论