-
什么是预解释(变量提声)
当浏览器开始解析JS代码的时候,首先看当前的运行环境(作用域)有没有带var和function,带var的变量会提前声明但是不会赋值,但是会带有一个默认值undefined,当代码执行过后才会复制;带function的会提前声明并且会立即赋值。
预解释需要注意的几个点
- 预解释只看等号左面的变量,并不会看你的值是什么
- 预解释只发生在当前作用域
- 预解释的时候无论你的条件是否成立,都要把里面的var提前声明
- return下面的代码仍然会被预解释,但是return后面的值即使你是一个函数也不会被预解释
- 自执行函数不被预解释
先看下面的例子
console.log(obj);//undefined
console.log(num);//undefined
var num = 12; //赋值
console.log(num); //12
var obj = {'name': 'tianxi', age: 30}; //对象类型
console.log(obj);
预解释只看等号左面的变量,并不会看你的值是什么
function sum(num1, num2) { //当代码执行到这的时候,声明和赋值都已经结束,直接跳过
function haha() {
}; //我们的预解释只发生在当前作用域
var total = 0;
total = num1 + num2;
}
-
堆和栈
-栈内存:提供一个让JS代码执行的环境,全局作用域和私有作用域都存储在这里。 -堆内存:是一个存储空间,放着所有的应用类型,需要存储的内容都在堆内存中,比如对象存储键值对,函数存储代码字符串;保存的都是一个地址
画图更容易理解
先把会预解释的全部提上来,是var的先不赋值,是function的立即赋值,当遇到function或者对象这种引用类型时,会开辟一个堆内存。
-
预解释的时候各种情况
- 1、无论条件是否成立,都会预解释
console.log(total); //undefined if('total' in window){ var total = 6; } console.log(total); //6,- 2、预解释的时候带var关键字只看等号左面,并不会看你的值是什么
console.log(a)//undefined var a = function () {};- 3、自执行函数不被预解释
!function (){ var b = 0; }(- 4、return下面的代码仍然会被预解释,但是return后面的值即使你是一个函数也不会被预解释
function fn(){ console.log(num); //undefined return function (){ console.log(num); } var num = 9;//return 下面的代码不执行,但是还会声明提前 } fn(); -
面试题
fn();//->2
function fn(){
console.log(1); //虽然重复,但是提前,并且已经做过一遍
}
fn();//->2
var fn = 12//代码执行到这的时候,我们原来的函数引用地址已经被破坏,并且把n赋值为12,
fn();//=》10 前面已经有一个fn,不是函数所以报fn is not function
function fn(){
console.log(2);
}
fn();//运行结果:2 2 error