作用域
作用域是行时代码中某些特定部分中变量,函数和对象的可访问性换句话说,作用域决定了代码中变量和其他资源的可见性
<script>
function Fun(){
let a ='内层变量'
console.log(a);
}
Fun();//先执行函数
//console.log(a);
function fun () {
console.log(a);
}
fun()
//console.log(a);//a is not defined
//变量a在全局作用域没有声明,所以在全局作用域下取值会报错
//作用域就是一个独立的地盘,让变量不会外泄、暴露出去
//作用域最大的用处就是隔离变量,不同作用域下同名变量不会有冲突
//ES6之前JavaScript没有块级作用域,只有全局作用域和函数作用域
//ES6的到来,为我们提供了"块级作用域",可通过新增命令let和const来体现
</script>
函数作用域
<script>
// 局部变量/函数作用域:
// 声明在函数内部的变量,和全局作用域相反,局部作用域一般只在固定的代码片段内可)
// 最常见的例如函数内部,所以在一些地方也会看到有人把这种作用域称为函数作用域,
function outFun() {
var a ='函数内部的变量';
function innerFun(){
console.log(a); //函数内部的变量
}
innerFun();
}
// console.log(a); // a is not defined
innerFun;//innerFun is not defined
outFun()
</script>
全局作用域
<script>
// 【全局作用域】
// 在代码中任意地方都能访问到的对象拥有全局作用域。
//(即在全局作用域中定义的变量可以在任何地方使用。)
// 全局作用域在页面打开时创建,在页面关闭时销毁。
// 【情况一:所有未定义直接赋值的变量自动声明为拥有全局作用域】
function Fun1(){
a ='未定义直接赋值的变量';
var b ='内层变量';
}
Fun1();
console.log(a);//未定义直接赋值的变量
//console.log(b); //b is not defined
// 注意点:如果一个变量在声明的时候没有使用关键字
// 例如:num = 10,此时这个变量写在哪里都是全局作用域
// 但这样的写法很不规范,不能这么写否则以后的代码将会出现bug
// 【情况二:最外层函数和最外层函数外面定义的变量拥有全局作用域】
var A = '最外层变量';//最外层变量
function outFun(){ //最外层函数
var B ='最外层函数的内层变量'
function innnerFun(){ //内层函数
var c ='内层函数的内部变量'
}
}
console.log(A);//最外层变量
//console.log(B); //B is not defined
outFun()
//innerfun(() //innerfun is not defined
//console.log(c); //c is not defined
// 【情况三:所有window对象的属性拥有全局变量】
// 在全局作用域中有一个全局对象window,他代表的浏览器的窗口,由浏览器创建。
// 一般情况下,window对象的内置属性都拥有全局作用域,例如window.name、window.location
</script>
块级作用域
js的三种作用域:
- 全局作用域(全局变量):在函数外面let的变量
- 局部作用域(局部变量):在函数里let的变量
- 块级作用域(块级变量): 在分支或循环大括号中let的变量
<script>
if(1) {
let sex = '男';
console.log(sex); // 男
}
// console.log(sex); // sex is not defined
for(let i = 1; i <= 5; i++){
console.log('循环内部:'+ 1);
}
console.log('循环外部:'+ 1); // i is not defined
</script>
作用域链
作用域链:
默认情况下,代码处于全局作用域(0级链),当声明一个函数会开辟一个局部作用域(1级)而函数里面又可以声明一个函数,又会形成一个新的作用域(2级),以此类推形成的结果称为作用域链
变量访问规则:就近原则
当你在一个作用域访问变量之后,首先会看当前作用域有没有声明
如果有则访问,没有则继续往上
直到作用域最顶端0级,如果还没有找到,则程序报错
<script>
// 作用域链:会向上级一级一级的寻找
// 0级
let num = 10;
// 1级
function fn1(){
let num = 20;
console.log(num);
// 2级
function fn2() {
// let num = 30;
console.log(num);
}
fn2()
}
fn1()
console.log(num);
</script>
匿名函数
<script>
// 匿名函数:
// 没有函数名的函数
// 具名函数:
function fn(){
console.log('123'); // 123
}
fn()
// 匿名函数:
let fn1 = function(){
console.log('456'); // 456
}
fn1()
// 执行匿名函数:自动执行语法
// 自执行语法:(匿名函数)()
(function (){
let num = 10
console.log('456');
})()
</script>