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的全局变量。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值