JS作用域

什么是作用域

作用域: 用来描述变量或函数有限的访问范围。

通俗一点就是某个变量哪里可访问哪里不可访问。

作用域分类:

  • 全局作用域: 非函数内的区域就是全局作用域(一般都是最外围)。
  • 局部(函数)作用域: 在函数内部就是局部作用域

全局作用域(Global Scope)

  • 在全局作用域定义的变量或函数我们称之为是全局变量或全局函数,在任何地方都可以被访问。

局部作用域(Local Scope)

  • 在函数内部就是局部(函数)作用域
  • 每调用一次函数就会创建一个新的函数作用域,它们之间是相互独立的。
  • 函数内部声明的变量我们称之为局部变量,它只能在所定义的函数内部可访问,在全局中是无法访问的。

代码示例:

<script>
    // 全局作用域
    var age = 18; // 全局变量
    var email = '123@qq.com' // 全局变量
    console.log(age); // 18
​
    function getAge(){
      // 局部作用域
      var age = 20; // 局部变量 
      console.log('我今年 '+ age + '岁',', 邮箱是:',email)
    }
    getAge();
</script>

作用域链(scope chain)

作用域链:就是变量的查找规则(就近原则)。

要注意作用域和作用域链的区别

  • 作用域描述的是变量作用的范围。
  • 而作用域链决定了变量的查找规则(就近原则,由内往外层找)。

示例代码:

var age = '100';
function foo(){
    console.log(age);   // ?
    function bar(){
        var age = '18';     
        console.log(age);   // ?
        function par(){
            console.log(age);   // ?
        }
        par();
    }
    bar();
}
foo();

说明:

  • 只有函数才可以形成作用域结构。如果没有函数那就只存在一个域,就是window全局作用域。
  • 作用域链中查找变量的原则:就近原则
    就近原则:访问变量,会优先在自身的作用域查找,若没有找到,会继续往上一级作用域中去找,直到找到全局作用域,若找到就使用,找不到就报错(引用错误,这个变量没有定义 xxxx not a defined)

函数形参就是局部变量

var a = 1
var b = 2
function sum(a,b) {
    // 形参就是函数内部局部变量
    // 如果要改形参的值,不需要在重复var声明
    b = b + 1
    console.log(a + b) // 8
}
​
sum(3, 4)

未使用var声明的变量

注意:在函数内若定义一个未使用var声明的变量,此变量执行时会覆盖全局内同名的变量,这种代码是不规范的,一定要避免,否则对我们的代码造成意想不到的效果,也不利于代码调试。

示例:

var myname = "大锤";
function foo() {
    myname = "小锤" // 要避免
}
foo();
console.log(myname) // 小·锤
注意:全局中默认有个特殊的变量name,值为空 '',平时的测试代码不要被name的默认值给影响到。

JS预解析

JavaScript代码的执行是由浏览器中的JavaScript引擎来执行的。执行时,分为两个阶段:预解析执行

  • 预解析阶段的工作:

主要做提升

  1. 把var变量的声明提升到当前作用域的最顶端。
  2. 把函数的声明提升到当前作用域的最顶端。
  • 执行阶段的工作:
  1. 代码执行,如进行变量的赋值操作,和一些运算操作。

变量的提升

示例1:

console.log(a); // undefined  
var a = 10;

由于var变量的提升,等价于:

var a; // 提升全局作用域顶端
console.log(a); // undefined  
a = 10;

示例2:

var age = 18;
function foo(){
    console.log(age);  // undefined
    var age = 19;
    console.log(age);   // 19
}
foo();

由于var变量会提升,等价于:

var age = 18
function foo(){
    var age; // 提升到函数作用域顶端
    console.log(age);  // undefined
    age = 19;
    console.log(age);   // 19
}
foo();

函数声明的提升

示例:

foo(); // 1
function foo(){
	console.log(1); 	
}

由于函数声明会提升,等价于:

function foo(){ // 提升到顶端
	console.log(1); 	
}
foo(); // 1

注意:同名情况下,函数声明提升优先级要高于同名的变量声明。

开发中是不会遇见的,但面试会!你懂的!
var foo;
function foo(){
    console.log(2)
}
foo() // 2

由于提升:等价于

// 先提升
function foo(){
    console.log(2)
}
// 后提升
var foo;

foo() // 2 优先会访问函数声明,函数是一等公民,

相关面试题

  • 题1:
var a = 100;
function test(){
    console.log(a);   // ?
    var a = 200;
}
test();
  • 题2:
var a = 100;
function test(){
    console.log(a);  // ?
    if(false){
        var a = 200;
    }
   
}
test();

一句话总结:任何代码块内,只要使用了var声明的变量都会被提升到当前作用域最顶端。

建议后面不管是变量还是函数,养成先定义后使用的好习惯。

匿名函数

匿名函数:即没有名字的函数

匿名函数如何使用:将匿名函数赋值给一个变量,这样就可以通过变量进行调用

function func(){} // 函数声明

// func就是匿名函数的名字 func本质就是指向函数所在堆中的内存地址
var func = function(){} // 函数表达式

func(); // 调用函数

自执行函数(IIFE)

IIFE,其全称为  immediately invoked function expression,即立即调用的函数表达式

IIFE作用:保存变量,形成一个私有空间(局部),不会污染全局变量。

应用场景:一般多用在封装插件中。 如Vue,React等框架都是IIFE形式。

自调用函数常用有两种定义方式:

;(function ([形参列表]) {
  console.log('哈哈');
})([实参列表])
// 等价

;(function ([形参列表]) {
  console.log('哈哈');
}([实参列表]))


 var result = (function (num1, num2) {
            return num1 + num2
        })(30, 50)

        console.log(result); // 80
注意:括号前面要求加一个分号;防止代码出错。

练习题:

;(function(){
  console.log(foo); // undefined
  var foo = 2;
  console.log(foo); // 2
})();

var x = 5;
;(function () { 
    console.log(x); // undefined
    var x = 10; 
    console.log(x); // 10
})();

var a = b = 10; // var a = 10; b = 10
; (function () {
    // 连续赋值
    var a = b = 20 // var a = 20; b = 20 相当于覆盖全局变量b,改为20
    })();
console.log(a) // 10
console.log(b) // 20
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiao_ming0425

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值