JS 预解析机制 (变量提升 Hoisting)
预解析:在当前作用域下,js运行之前,会把带有var
和function
关键字声明的变量先声明,然后从上至下解析js语句
console.log(a); //undefined
let a = 0;
console.log(a); //0
// 预解析
// 会将页面中的js变量都前置声明!
// 变量声明
let a;
// 只声明了变量,没赋值,打印出来就是undefined
console.log(a); //undefined
// 赋值变量
a = 0;
// ----------------------------
// 如果连声明都没有,就会报错
console.log(a); //Uncaught ReferenceError: a is not defined
// let a = 0;
function fn(){
console.log(1);
}
fn(); // 1
// 预解析
// 会将页面中的函数声明前置!
fn(); // 1
// 就算函数写到下面,它也会给前置了
function fn(){
console.log(1);
}
fn(); // Uncaught TypeError: fn is not a function
let fn = function (){
console.log(1);
}
fn(); // 1
// ----------------------------
// 函数声明 - 命名函数
// function fn(){
// }
// fn 变量 = 函数表达式
let fn = function (){
console.log(1);
}
//它会理解为你声明了一个变量,只不过变量里面存的是函数而已
// 声明变量
var fn;
fn();
// 赋值
fn = function(){
console.log(1);
}
作用域 (scope)
// 作用域 - 在特定的区域可以使用
// 函数 外面的变量 在里面随便用 - 全局变量 (可以在任何函数下调用)
let a = 12;
function fn(){
console.log(a)
}
fn(); //12
// ----------------------------
// 函数 里面的变量 在外面不能用 - 局部变量 (只能在函数内部使用)
function fn(){
let a =5;
console.log(a);
}
fn();
console.log(a); //Uncaught ReferenceError: a is not defined
var a =12;
function fn(){
a = 5;
}
console.log(a); // 12
// ----------------------------
var a =12;
function fn(){
// 没有var 就是赋值
a = 5;
}
fn();
console.log(a); // 5
// ----------------------------
var a =12;
fn(); // 预解析
console.log(a); // 5
function fn(){
a = 5;
}
// ----------------------------
var a =12;
console.log(a); // 12
fn();
function fn(){
a = 5;
}
// ----------------------------
var a =12;
fn();
console.log(a); // 12
function fn(){
var a = 5;
}
// ----------------------------
var a =12;
function fn(a){
// 形参声明过这个名称,函数内部这就是一个局部变量
// 形参 -- 局部变量声明
a = 5;
return a;
}
console.log(fn()) //5
console.log(a); //12
多个作用域嵌套(作用域链)
// 定义的函数,看到调用后再去看函数内的代码 -- 追根溯源,找到函数触发的点,再去看函数发生了什么
function fn1(){
var a = 12;
// 函数内声明的函数称为局部函数
function fn2(){
var b = 5;
return a+b;
}
return fn2();
}
console.log(fn1()); // 17
// 函数内查找变量时 - 顺序
// 先从自身作用域下查找 - 如果没有就会从父级作用域下找 - 如果父级也没有 还会往上找
// 由内向外 - 一层一层 - 直到找到window下面
// 反之 不能调用局部变量!(内层作用域能访问外层作用域,而外层不能访问内层。)
var c = 1;
function fn1(){
var a = 12;
// 局部函数
function fn2(){
var b = 5;
return a+b+c;
}
// b是fn2的局部变量,它只能在fn2的函数内去调用
// console.log(b);
return fn2();
}
console.log(fn1()); // 18