JS引擎在读取js代码的过程中,有以下步骤
解析读取代码
执行。
注意:在JS代码执行之前,浏览器的解析器在遇到 var 变量名 和function 整个函数 提升到当前作用域的最前面。
优先级:函数提升>变量提升
同步任务大于异步任务
let有自己的块级作用域
匿名函数不会提升,会有自己的模拟块级作用域
如果在函数内部用var声明了和外部相同的变量,则优先看函数作用域当中的变量
在不同的函数里面,变量和函数提升互不影响,也不影响全局作用域(父级影响子级,子级不影响父级,3>1,3>1,3>1)
在不同的script块里面,变量和函数提升互不影响,但影响全局作用域(这里无所谓父子级之分,1+1+1=3)
// 变量提升
console.log(op);
var op = 1;
// 输出undefined
// 相当于
// var op
// console.log(op)
// op = 1
for(var i =0;i<=3;i++){
setTimeout(function(){
console.log(i);
},0)
}
// 输出:4 4 4 4
for(let j =0;j<=3;j++){
setTimeout(function(){
console.log(j);
},0)
}
// 输出:1 2 3 4
// 这是一个很棒的对比!
// 1. 前提
// js里有同步和异步的概念,且先同步后异步
// 这里面,对于i的累加,是同步事件,放到执行栈里面,而setTimeout是异步事件,放到宏任务队列
// 2. 为何有所区别
// es6提出的let,具有块级作用域的概念,即每一个let都有自己的作用域
// var 则是没有
// 简单来说就是,let i=0,i=1,i=2,i=3,这些都在自己的块级作用域里面,互不影响,故能输出0,1,2,3
// var i=0,i=1,i=2,i=3,i=4,这些是共享一个作用域的,那么后者会覆盖前者,故到输出的时候,则全为4~
// 同步和异步题型
for(var i=0;i<=3;i++){
console.log(i); // 0 1 2 3
setTimeout(function(){
console.log(i); // 4 4 4 4
})
}
// 有了上面的2做基础,不难知道
// 输出的0123是因为其在同步任务中,i每加1则执行一次,那么自然而然,0123都能输出
// 而4444则是,异步任务了,此时已累加至4,自然输出就是4444
function fun(){
var a;
a=99;
fun1();
console.log(a);
function fun1(){
console.log(a);
var a=10;
console.log(a);
}
}
fun()
// 输出:undefined 10 99
// 这个直接分析即可,记“子级作用域可以找到父级作用域,反之不可以,因为函数的销毁机制”
// 相当于
// var a
// a=99
// fun1(){
// var a
// console.log(a); undefined
// a=10
// console.log(a); 10
// }
// console.log(a); 99
// 可能有小伙伴疑惑为什么这里的a值不是fun1里面是10而是外面的99
// 这是因为那是函数作用域里面值不影响外面的作用域(简单来说就是 父级影响子级,子级不影响父级)
// 那是只要函数执行完毕,就可以立即销毁其作用域链了;同时也避免了过多占用内存的相关情况
// 故到最后一行的时候,是找不到fun1的,再往上找,也就是值99啦
function fun(){
var a;
a=99;
fun1();
console.log(a);
function fun1(){
console.log(a);
var a=10;
console.log(a);
}
}
fun()
// 输出:undefined 10 99
// 这个直接分析即可,记“子级作用域可以找到父级作用域,反之不可以,因为函数的销毁机制”
// 相当于
// var a
// a=99
// fun1(){
// var a
// console.log(a); undefined
// a=10
// console.log(a); 10
// }
// console.log(a); 99
// 可能有小伙伴疑惑为什么这里的a值不是fun1里面是10而是外面的99
// 这是因为那是函数作用域里面值不影响外面的作用域(简单来说就是 父级影响子级,子级不影响父级)
// 那是只要函数执行完毕,就可以立即销毁其作用域链了;同时也避免了过多占用内存的相关情况
// 故到最后一行的时候,是找不到fun1的,再往上找,也就是值99啦
// 作用域链
var i=1;
function fun1(){
console.log(i);
}
fun1();
var j=1;
function fun2(){
var j=2;
console.log(j);
}
fun2();
// 这个记住,如果在函数内部用var声明了和外部相同的变量,则优先看函数作用域当中的变量
// 那么看,第一个函数内部没有自己的i值,往外找,1
// 第二个函数内部有自己的j值,直接为2