作用域链
-
默认情况下全局作用域, 我们称之为0级作用域
-
只要定义一个函数就会再开启一个作用域
-
如果该函数是在全局作用域中定义的, 那么函数的作用域我们称之为1级作用域
-
如果该函数是在其他函数中定义的, 那么作用域级数为所在函数+1级作用域
-
作用域链的作用:
- 当前变量如果在自己的作用域内找不到,就会到上级作用域内寻找
// num属于0级作用域
var num = 123;
// test函数也属于0级作用域
function test() {
// test的{}中是新开启的一个作用域
// test的{}中定义的变量和函数都属于1级作用域
// value属于1级作用域
var value = 666; // 1级作用域
// demo函数也属于级作用域
function demo() {
// demo的{}中是新开启的一个作用域
// demo的{}中定义的变量和函数都属于2级作用域
// temp属于2级作用域
var temp = 678;
console.log(temp);
}
}
全局变量
- 默认情况下在一对script标签或者在一个单独的JS文件中定义的变量都是全局变量
- 默认情况下在函数中定义的变量都是局部变量
- 注意点:
- 但是如果在函数中定义变量时, 没有书写var关键字, 那么这个局部变量就会变为全局变量
- 虽然这样可以将一个局部变量变为全局变量, 但是在企业开发中千万不要这样写
预解析
- 将变量和函数的声明提升到当前作用域的最前面, 这个我们就称之为预解析
- 注意点:函数的声明不只是function 函数名() 而是整个函数
- 预解析之后的代码
- 声明提前的代码
- 自己编写的代码
- 有多级作用域的代码解析方法
- 从0级作用域开始依次预解析
源代码
var num = 123;
fun();//undefined
function fun() {
console.log(num);
var num = 666;
}
预解析之后的代码
var num;
function fun(){
var num;
console.log(num)
num = 666;
}
num = 123;
fun();
源代码
var a = 666;
test();
function test() {
var b = 777;
console.log(a);
console.log(b);
var a = 888;
}
预解析的代码
var a;
function test() {
var b;
var a;
b = 777;
console.log(a); // undefined
console.log(b); // 777
a = 888;
}
a = 666;
test();
- 预解析注意点:
- 变量和函数同名时, 函数的优先级高
- 注意点:
- 在企业开发中变量的名称千万不要和函数的名称一样, 否则会出现混乱问题
- 规则:
- 如果在同名的变量和函数声明之前访问这个名称, 拿到的是函数
- 如果在同名的变量和函数声明之后访问这个名称, 拿到的是变量
console.log(value); // function value() {}
var value = 123;
function value() {
console.log("fn value");
}
console.log(value); // 123
不同函数定义方式的区别
- 在高级别的浏览器中, 预解析不会提升{}中的函数
- 但是在低级别的浏览器中, 预解析会提升{}中的函数
源代码
if(true){
// 前面我们说过默认都是0级作用域, 也就是全局作用域
// 只有定义了函数才会开启一个新的作用域
// 所以test函数虽然定义在了if的{}中, 但是并没有定义在其它函数中
// 所以test函数还是属于0级作用域, 所以还是一个全局函数
function test() {
console.log("test1");
}
}else{
function test() {
console.log("test2222222");
}
}
test();
高级别不会提升
低级别浏览器提升后的代码
function test() {
console.log("test1");
}
function test() {
console.log("test2222222");
}
if(true){
}else{
}
test();
- 所以在高级别浏览器中,test()会打印test1,但在低级别了浏览器中会打印test2222222
- 为了解决如上问题,我们可以用函数表达式的方式将函数保存在变量中
if(false){
var test = function () {
console.log("test1");
}
}else{
var test = function () {
console.log("test22222");
}
}
test();
高级别或者低级别提升后的代码
var test;
if(true){
test = function () {
console.log("test1");
}
}else{
test = function () {
console.log("test22222");
}
}
test();
网友评论