什么是作用域
当前的执行上下文。值和表达式在其中 "可见" 或可被访问到的上下文。如果一个变量或者其他表达式不 "在当前的作用域中",那么它就是不可用的。 作用域也可以根据代码层次分层,以便子作用域可以访问父作用域,通常是指沿着链式的作用域链查找,而不能从父作用域引用子作用域中的变量和引用。
当然,一个 Function 将生成一个闭包(通常是返回一个函数引用),这个函数引用从外部作用域(在当前环境下)可以访问闭包内部的作用域
- ECMAScript5 只有全局作用域和函数作用域,ECMAScript6 之后才有块级作用域(let 、const)
全局作用域
定义的变量或函数在整个JavaScript程序中,都是可见的
var name = 'zyc'; // 全局变量
// 全局函数
function foo() {
console.log(name); //使用全局变量
}
foo(); // 运行打印: zyc
//全局函数
function bar(){
//嵌套函数
function getAge(){
console.log(name); //使用全局变量
}
getAge(); //运行打印:zyc
foo(); //运行打印:zyc
}
bar();
console.log(name) //打印:zyc
函数作用域
定义在函数中的参数和变量或嵌套函数在函数外部是不可见的
console.log(age); //报错 Uncaught ReferenceError: age is not defined
getAge(); //报错 Uncaught ReferenceError: getAge is not defined
//全局函数
function bar(){
var age= 10;
//嵌套函数
function getAge(){
console.log(age);
}
getAge(); //运行打印:10
}
bar();
getAge(); //报错 Uncaught ReferenceError: getAge is not defined
console.log(age); //报错 Uncaught ReferenceError: age is not defined
块级作用域
任何一对花括号 {} 中的语句集都属于一个块,在这之中定义的所有变量在代码块外都是不可见的,我们称之为块级作用域。
function bar() {
var name = "zxy";
{
let age = 10;
var kk = 'kk'
}
console.log(name); //打印输出 zxy
console.log(kk); //打印输出 kk
console.log(age); //报错 Uncaught ReferenceError: age is not defined
}
bar();
变量与声明提升
- var 关键字定义的变量可以在使用后声明,也就是变量可以先使用再声明(声明提升)
- 使用 var 关键字声明的变量在任何地方都可以修改
- let 、const关键字定义的变量则不可以在使用后声明,也就是变量需要先声明再使用。
- let 、const 声明的变量只在 let 、const 命令所在的代码块 {} 内有效,在 {} 之外不能访问。(块级作用域)
- let 、const都不能和它所在作用域内的其他变量或函数拥有相同的名称
- const 用于声明一个或多个常量,声明时必须进行初始化,且初始化后值不可再修改
- 在相同的作用域或块级作用域中,不能使用 const 关键字来重置 var 和 let关键字声明的变量
- 在相同的作用域或块级作用域中,不能使用 const 关键字来重置 const 关键字声明的变量
- 在相同的作用域或块级作用域中,不能使用 var 关键字来重置 let 关键字声明的变量
- 在相同的作用域或块级作用域中,不能使用 let 关键字来重置 let 关键字声明的变量
- 在相同的作用域或块级作用域中,不能使用 let 关键字来重置 var 关键字声明的变量
- const 、let关键字在不同作用域,或不同块级作用域中是可以重新声明赋值的
var name = 'zyc'; // 全局变量
// 全局函数
function foo() {
console.log(name); //使用全局变量
}
console.log(foo) //运行打印 函数体
foo(); // 运行打印: zyc
//全局函数
function bar() {
var name = 2; //函数局部变量(属于当前函数体)
foo(); // 这里调用全局函数,运行打印 zyc(调用的是栈内存中保存的方法属于全局作用域下不属于bar 函数的嵌套函数所以无法读取到bar函数定义的name)
}
console.log(bar) //运行打印 函数体
bar();//全局函数调用
可以看成
{
var name = 'zyc'; // 全局变量
var foo;
foo = function () {
console.log(name); //使用全局变量
}
var bar;
bar = function(){
var name = 2; //函数局部变量(属于当前函数体)
foo(); // 这里调用全局函数,运行打印 zyc(调用的是栈内存中保存的方法属于全局作用域下不属于bar函数的嵌套函数所以无法读取到bar函数定义的name)
}
console.log(foo) //运行打印 函数体
foo(); // 运行打印: zyc
console.log(bar) //运行打印 函数体
bar();//全局函数调用
}
在如
console.log(fn);
fn();
{
fn();
function fn() {
console.log(10)
};
fn();
}
fn();
看做
var fn;
console.log(fn);
fn();
{
fn = function(){
console.log(10)
};
fn();
fn();
}
fn();
- 函数声明(函数名称) 类似于 var,即会提升到全局作用域或函数作用域的头部
- 函数声明(函数整体) 还会提升到所在的花括号 {} 中的语句的头部
可以把整个script当做花括号{}
相关资料
JavaScript 变量
JavaScript let 和 const
JavaScript 声明提升
JavaScript 作用域
Scope
函数作用域, 块级作用域和词法作用域
函数提升与函数的块级作用域