今天又看了js基础教学视频,感觉这么好多num是真有意思啊(~才怪 ~)
js作用域
变量根据作用域的不同分为两种:全局作用域和局部作用域
- 函数内部可以使用全局变量
- 函数外部不可以使用局部变量
- 当函数执行完毕,本作用域内的局部变量会销毁
1.全局作用域
- 直接编写在script标签中的JS代码,都在全局作用域
- 全局作用域在页面打开时创建,在页面关闭时销毁
- 在全局作用域中有一个全局对象window,我们可以直接使用,它代表的是浏览器的窗口,它由浏览器创建,我们可以直接使用
因此
在全局作用域中:
创建的变量都会作为window对象的属性保存
创建的函授都会作为window对象的方法保存
var a = 1;
b = 3 //隐式全局变量
console.log(window.a);
console.log(window.b);
function fun(){
console.log("我是fun函数");
}
window.fun();
2 局部作用域(函数作用域)
即函数体内部的作用域
词法作用域
var num = 123;
function foo() {
console.log( num );
}
foo(); //123
if ( false ) {
var num1 = 123;
}
console.log( num1 ); // undefiend
function f1(){
var num2 = 123
}
console.log(num2) //报错
变量的作用域是在定义时决定而不是执行时决定,也就是说词法作用域取决于源码,通过静态分析就能确定,因此词法作用域也叫做静态作用域。
词法作用域规则:
- 函数允许访问函数外的数据.
- 整个代码结构中只有函数可以限定作用域.
- 作用域规则首先使用提升规则分析
- 如果当前作用规则中有名字了, 就不考虑外面的名字
作用域链
有函数就可以制造作用域结构,在全局作用域内有函数,那么函数就构成了另一个作用域,函数中还有函数,那么就会在这个作用域中再诞生一个作用域。
将所有的作用域列出来,就可以有一个结构:函数内指向函数外的链式结构,称为作用域链
var num = 10
function f1(){
var num = 20
function f2(){
var num = 30
function f3(){
var num = 50
console.log(num)
}
f3()
}
f2()
}
f1()
预解析(变量的声明提前和函数的声明提前)
变量的声明提前
使用var关键字,会在所有的代码执行之前被声明(但不会被赋值)
函数的声明提前
使用函数声明形式创建的函数function 函数(){}
它会在所有代码执行之前就被创建,所以我们可以在函数声明前调用
console.log("a = "+a); //a = undefined
var a = 123;
fun();
function fun(){
console.log("我是一个函数");
console.log(num) //undefined
var num = 10
}
注 预解析是先提升functionvar,再提升var,即函数优先级比变量优先级高
f1()
console.log(b) //9
console.log(c) //9
console.log(a) //报错,未声明
function f1(){
var a = b = c = 9 //b、c是隐式全局变量
console.log(a) //9
console.log(b) //9
console.log(c) //9
}