0%

js作用域和预解析

今天又看了js基础教学视频,感觉这么好多num是真有意思啊(~才怪 ~)

js作用域

变量根据作用域的不同分为两种:全局作用域和局部作用域

  1. 函数内部可以使用全局变量
  2. 函数外部不可以使用局部变量
  3. 当函数执行完毕,本作用域内的局部变量会销毁

1.全局作用域

  • 直接编写在script标签中的JS代码,都在全局作用域
  • 全局作用域在页面打开时创建,在页面关闭时销毁
  • 在全局作用域中有一个全局对象window,我们可以直接使用,它代表的是浏览器的窗口,它由浏览器创建,我们可以直接使用

因此

  • 在全局作用域中:

    创建的变量都会作为window对象的属性保存

    创建的函授都会作为window对象的方法保存

1
2
3
4
5
6
7
8
var a = 1;
b = 3 //隐式全局变量
console.log(window.a);
console.log(window.b);
function fun(){
console.log("我是fun函数");
}
window.fun();

2 局部作用域(函数作用域)

即函数体内部的作用域

词法作用域

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var num = 123;
function foo() {
console.log( num );
}
foo(); //123

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

function f1(){
var num2 = 123
}
console.log(num2) //报错

变量的作用域是在定义时决定而不是执行时决定,也就是说词法作用域取决于源码,通过静态分析就能确定,因此词法作用域也叫做静态作用域。

词法作用域规则:

  • 函数允许访问函数外的数据.
  • 整个代码结构中只有函数可以限定作用域.
  • 作用域规则首先使用提升规则分析
  • 如果当前作用规则中有名字了, 就不考虑外面的名字

作用域链

有函数就可以制造作用域结构,在全局作用域内有函数,那么函数就构成了另一个作用域,函数中还有函数,那么就会在这个作用域中再诞生一个作用域。

将所有的作用域列出来,就可以有一个结构:函数内指向函数外的链式结构,称为作用域链

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 函数(){}

它会在所有代码执行之前就被创建,所以我们可以在函数声明前调用

1
2
3
4
5
6
7
8
9
10
11
console.log("a = "+a);	//a = undefined

var a = 123;

fun();
function fun(){
console.log("我是一个函数");

console.log(num) //undefined
var num = 10
}

预解析是先提升functionvar,再提升var,即函数优先级比变量优先级高

1
2
3
4
5
6
7
8
9
10
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
}