JS----JavaScript中的作用域和作用域链

作用域(Scope)

1.什么是作用域

作用域是在运行时代码中的某些特定部分中变量,函数和对象的可访问性。

作用域(scope):一个变量的可用范围

作用域的类型

Javascript中有三种作用域:

  • 全局作用域;
  • 函数作用域;
  • 块级作用域;

2. 全局作用域

任何不在函数中或是大括号中声明的变量,都是在全局作用域下,全局作用域下声明的变量可以在程序的任意位置访问。
例如:

 // 全局变量
var greeting = 'Hello World!';
function greet() {
  console.log(greeting);
}
// 打印 'Hello World!'
greet();

3. 函数作用域

函数作用域也叫局部作用域,如果一个变量是在函数内部声明的它就在一个函数作用域下面。这些变量只能在函数内部访问,不能在函数以外去访问。
例如:

function greet() {
  var greeting = 'Hello World!';
  console.log(greeting);
}
// 打印 'Hello World!'
greet();
// 报错: Uncaught ReferenceError: greeting is not defined
console.log(greeting);

4. 块级作用域

ES6引入了letconst关键字,和var关键字不同,在大括号中使用letconst声明的变量存在于块级作用域中。在大括号之外不能访问这些变量。
例如:

{
  // 块级作用域中的变量
  let greeting = 'Hello World!';
  var lang = 'English';
  console.log(greeting); // Prints 'Hello World!'
}
// 变量 'English'
console.log(lang);
// 报错:Uncaught ReferenceError: greeting is not defined
console.log(greeting);

上面代码中可以看出,在大括号内使用var声明的变量lang是可以在大括号之外访问的。使用var声明的变量不存在块级作用域中。

5.作用域嵌套

Javascript中函数可以在一个函数内部声明另一个函数一样,作用域也可以嵌套在另一个作用域中。
例如:

var name = 'Peter';
function greet() {
  var greeting = 'Hello';
  {
    let lang = 'English';
    console.log(`${lang}: ${greeting} ${name}`);
  }
}
greet();

这里我们有三层作用域嵌套,首先第一层是一个块级作用域(let声明的),被嵌套在一个函数作用域(greet函数)中,最外层作用域是全局作用域。

6.词法作用域

词法作用域(也叫静态作用域)从字面意义上看是说作用域在词法化阶段(通常是编译阶段)确定而非执行阶段确定的。
例如:

let number = 42;
function printNumber() {
  console.log(number);
}
function log() {
  let number = 54;
  printNumber();
}
// Prints 42
log();

上面代码可以看出无论printNumber()在哪里调用console.log(number)都会打印42。动态作用域不同,console.log(number)这行代码打印什么取决于函数printNumber()在哪里调用。
如果是动态作用域,上面console.log(number)这行代码就会打印54
使用词法作用域,我们可以仅仅看源代码就可以确定一个变量的作用范围,但如果是动态作用域,代码执行之前我们没法确定变量的作用范围。
C,C++,Java,Javascript等大多数编程语言都支持静态作用域。Perl 既支持动态作用域也支持静态作用域。

在js中词法作用域规则:

  • 函数允许访问函数外的数据
  • 整个代码结构中只有函数可以可以限定作用域
  • 作用域规则首先使用提升规则分析
  • 如果当前作用域中有名字了,就不考虑外面的名字
var num = 123;
function foo(){
	console.log( num );
}
foo();

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

7. 作用域链

当在Javascript中使用一个变量的时候,首先Javascript引擎会尝试在当前作用域下去寻找该变量,如果没找到,再到它的上层作用域寻找,以此类推直到找到该变量或是已经到了全局作用域。
如果在全局作用域里仍然找不到该变量,它就会在全局范围内隐式声明该变量(非严格模式下)或是直接报错。

例如:

// 案例 1:
function f1(){
	function f2(){
	}
}

var num = 456;
function f3(){
	function f4(){
	}
}

在这里插入图片描述

// 案例2
function f1() {
    var num = 123;
    function f2() {
        console.log( num );
    }
    f2();
}
var num = 456;
f1();

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值