1、介绍
预解析,笔试常考的一个东西,前几天,群友发了个题目,确实有意思
JavaScript 代码是由浏览器中的 JavaScript 解析器来执行的。JavaScript 解析器在运行 JavaScript 代码的时候分为两步:预解析和代码执行。
- 预解析:在当前作用域下, JS 代码执行之前,浏览器会默认把带有 var 和 function 声明(匿名函数没有function声明,所以不会提升)的变量在内存中进行提前声明或者定义。
- 代码执行: 从上到下执行JS语句。
预解析也叫做变量、函数提升。
变量提升(变量预解析): 变量的声明会被提升到当前作用域的最上面,变量的赋值不会提升。
函数提升: 函数的声明会被提升到当前作用域的最上面,但是不会调用函数
2、小试牛刀
function f1() {
var a = b = c = 9;
console.log(a);
console.log(b);
console.log(c);
}
f1();
console.log(c);
console.log(b);
console.log(a);
console.log(window);
// 结果为 9 9 9 9 9 报错
// var a=b=c=9 其实 是 var a , a=b=c=9 ,
// 又因为 没有定义 b、c ,而是 直接赋值,默认会在 window 里面显示
// 第2个 测试
console.log(a)//undefined:带var变量预解析时存在提升
var a = 0;
console.log(a);//0
// 其实它的代码执行顺序是 下面这样
/*
var a
console.log(a)
a = 0
console.log(a)
*/
console.log('第三个测试————————————————————————————');
(function () {
// 函数名 和 变量名 重名的时候,函数的优先级更高,定义变量并不会执行
console.log(number); // 这里输出的其实是 这个函数
var number = '我是变量number' // 这里 给number 重新赋值了
function number() {
console.log('我是函数');
}
console.log(number); // 所以这里输出的是 字符串变量
})()
/*
function number(){console.log('我是函数');}
console.log(number);
number = '我是变量number'
console.log(number);
*/
console.log('第4个测试————————————————————————————');
(function () {
fn(11, 22); //报错:fn is not a function,
var fn = function (a, b) {
return a + b;
}
//这个函数定义的方式是:函数表达式定义,在预解析时这个函数不会整体提升,
//只是提升了 var fn = undefined,此时当函数调用,肯定就会报错
})()
console.log('第5个测试————————————————————————————');
alert(a); //1. undefined
var a = 0;
alert(a); //2. 0
function fn() {
alert(a);
a = 1;
alert(a);
} //函数在预解析提升时,如果函数重名,下边的会覆盖掉上边的,所以这函数失效
fn()
function fn() {
alert(a); //3. undefined
var a = 2;
alert(a++); //4. 2:++在前,先赋值后运算,++在后,先运算再赋值,所以这里还是输出0,但a再后面已经变成1
}
alert(a); //5. 0:函数里的a带var,不影响全局的a
总结
- 函数的优先级高于变量的 预解析优先级
- 函数名 和 变量名 重名的时候,函数的优先级更高,定义变量并不会执行
- 函数在预解析提升时,如果函数重名,下边的会覆盖掉上边的