js作用域超全介绍--全局作用域、局部作用、块级作用域

一、作用域定义

作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。在JavaScript中,变量的作用域有全局作用域和局部作用域两种。ES6中新增块级作用域。

相应作用域的变量分别称为全局变量、局部变量和块级变量。


二、全局作用域

一般来说以下几种情形拥有全局作用域:

(1)最外层函数和在最外层函数外面定义的变量拥有全局作用域,直接写在script标签中的JS代码或单独一个JS文件中的;

<script>
  var a = 1;
</script>

(2)所有末定义直接赋值的变量自动声明为拥有全局作用域(情况较少);

(3)所有window对象的属性拥有全局作用域。一般情况下,window对象的内置属性都拥有全局作用域,例window.name、window.location、window.top等等。

var a = 1;
function b(){
  console.log(a); // 1 a为全局变量可以在函数内访问到
}
console.log(a); // 1 可以全局访问
console.log(window.a); // 1 可以全局访问

三、局部作用域

1、 也称为函数作用域,其含义是指,属于这个函数的全部变量都可以在整个函数的范围内使用及复用(包括嵌套的作用域中也可以使用)在固定的代码片段才能被访问;

function b(){
  var a = 1; // 变量a定义在函数内部
}
console.log(a) // error,引用错误,a没有定义

2、调用函数时创建函数作用域,函数执行完成后,函数作用域就销毁,每调用一次函数就会创建一个新的函数作用域,他们之间是互相独立的;

function b(){
  if(true){
    var a = 1; // a的作用域不是if的范围,而是在函数中
  }
  console.log(a); // 1 在函数内部能访问到
}
console.log(a); // error引用错误

**3、和全局作用域的关系:**在函数作用域中可以访问到全局作用域的变量,但是在全局作用域中是访问不到函数作用域的变量;当函数作用域操作一个变量时,它会先在自身中寻找,如果有就直接使用,如果没有就向上一级作用域中寻找,直到找到全局作用域。

var a = 1;
function b(){
  var a = 10;
  console.log(a); // 10 局部变量和全局变量同名,在函数作用域中,局部变量覆盖全局变量
}
console.log(a); // 1 输出全局变量的值

四、块级作用域

ES6 中引入了 let 与 const,与 var 不同的是在大括号(包括纯粹的大括号、if、while、for)间用var 定义的变量处在全局作用域。如果我们用 let 与 const 在大括号中定义,变量将处于块作用域。

{
  var a = 1; // var声明a=1 全局变量
  let b = 2; // let声明b=2 局部变量
  const c = 3; // const声明c=3 局部变量
  console.log(a) // 1
  console.log(b) // 2
  console.log(c) // 3
}
console.log(a) // 1
console.log(b) // error引用错误,b未定义
console.log(c) // error引用错误,c未定义

对块级变量来说,其作用域是块级变量声明语句开始到块结束之间的区域。

let 与 const 的不同点在于,const 定义的是一个常量,无法修改定义后的值。

{
  const a; // 语法错误,const声明必须初始化赋值
  const b = 1; // const声明c为常量,赋值后不会改变,在块级作用域内
}
console.log(b); // error引用错误b未定义

五、作用域中的特殊情况

1、函数参数------属于函数(局部)作用域

function printAge(age) {
  console.log('我今年' + age + '岁了');
}
printAge(20); // 我今年20岁了
console.log(age); // 报错

2、for循环

使用var---全局作用域,外面也可以访问

for(var i = 0; i < 10; i++) {
  console.log(i); // 0 1 2 3 4 5 6 7 8 9 
}
console.log(i); // 10

使用let---块级作用域,只能在{}范围内被访问,外面访问不到

for(let i = 0; i < 10; i++) {
  console.log(i); // 0 1 2 3 4 5 6 7 8 9 
}
console.log(i); // error

3、try...catch中的err---不属于任何作用域,只能被catch访问

try {
  throw new Error();
} catch (err) {
  var test = 'hello';
  const test2 = 'Hi';
  console.log(err); // 正常打印
}
console.log(test); // hello
console.log(test2); // 报错
console.log(err); // 报错

六、作用域实例

function Person() {
  getAge = function () {
    console.log(1);
  }
  return this;
}

Person.getAge = function () {
  console.log(2);
}

Person.prototype.getAge = function () {
  console.log(3);
}

var getAge = function () {
  console.log(4);
}

function getAge() {
  console.log(5);
}

Person.getAge();
getAge();
Person().getAge();
getAge();
new Person.getAge();
new Person().getAge();

输出结果:2 4 1 1 2 3

相关推荐
一个处女座的程序猿O(∩_∩)O1 小时前
小型 Vue 项目,该不该用 Pinia 、Vuex呢?
前端·javascript·vue.js
hackeroink4 小时前
【2024版】最新推荐好用的XSS漏洞扫描利用工具_xss扫描工具
前端·xss
迷雾漫步者6 小时前
Flutter组件————FloatingActionButton
前端·flutter·dart
向前看-6 小时前
验证码机制
前端·后端
燃先生._.7 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
高山我梦口香糖8 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
m0_748235248 小时前
前端实现获取后端返回的文件流并下载
前端·状态模式
m0_748240259 小时前
前端如何检测用户登录状态是否过期
前端
black^sugar9 小时前
纯前端实现更新检测
开发语言·前端·javascript