js代码在解析也就是执行之前首先都会进行预处理操作。对var 声明的变量进行预处理,只声明不定义。对声明式函数进行预处理,既声明又定义。同名声明式函数,后者覆盖前者。
对于所有var的变量首先会在其作用域内的开头声明该变量或者该方法,但是不定义也就是不赋值。记住这个点,我们看下面的代码
1、
fn();
function fn() {
console.log('hello')
}
var fn = function() {
console.log('hello world')
}
// 打印hello
分析:function fn()是声明式函数,在预处理的时候就已经声明和定义了,但是var fn这个变量在预处理的时候仅仅声明,没有定义(js代码执行到fn = function()的时候才定义),我们在第一行调用fn(),就直接执行function fn()方法了(因为function fn()预处理的时候就已经声明并且定义了)。
2、
fn();
function fn() {
console.log('hello')
}
function fn() {
console.log('hello world')
}
// 输出hello world
这个比较简单,两个同名的fn函数,它们都是声明式函数,它们在预处理的时候就已经声明并且定义过了。在开始执行js代码后,同名声明式函数,后者覆盖前者。
3、
var a = 2;
function fn() {
console.log(a);
a = 3;
}
fn(); // 2
a=3没有用var定义,所以预处理的时候不理它。从上往下执行可不输出2嘛
4、
var a = 2;
function fn() {
console.log(a);
var a = 3;
}
fn(); // undefined
oh,no这里为啥输出undefined呢?我模拟一下预处理之后的js代码,你就恍然大悟了。
var a;
a=2;
function fn() {
var a;
console.log(a);
a=3
}
fn() // undefined
你现在再从上往下执行瞅瞅,由于fn里的a仅仅是声明了,但是没有定义,所以输出undefined
5、
function foo() {
console.log("函数声明");
}
var foo;
console.log(typeof foo); // function
console.log(foo) // foo函数
console.log('-----------------------------------------------------------')
function fn() {
console.log('函数声明')
}
var fn = 5;
console.log(typeof fn); // number
console.log(fn) // 5
同名的函数和变量,如果变量声明了没有定义,那么函数不会被覆盖。如果变量声明了并且也定义了,那么同名函数会被变量覆盖
6、
var c = 1;
function c(c) {
console.log(c);
var c = 3;
}
console.log(c); // 1
c(2); // 这里直接报错 :c is not a function
这里变量c和函数c同名,变量c不仅声明了,还定义了,所以函数c被变量c覆盖了,你执行c(2)肯定报错