什么是预解析?
- js引擎执行js代码分为两步,首先预解析,然后执行js代码
- 预解析就是将代码所有的 var声明和 function声明 提升到当前作用域的最前面
- 预解析分为函数预解析(提升)和变量预解析(提升)
什么是变量提升?
- 将所有的 var声明提升到当前作用域的最前面,但是不提升赋值操作
看如下代码:
console.log(value) // undefined
var value = 100
结果是undefined,这是因为变量提升的原因,等同于如下代码,将声明value变量提前,但是并不提升赋值操作,value并没有赋值。所以是undefined
var value
console.log(value)
value = 100
什么是函数提升?
- 将所有的function声明提前到当前作用域的最前面,不调用函数
看如下代码
fun() // i am function
function fun() {
console.log('i am function')
}
结果输出 i am function,这是因为函数提升的原因,将函数声明提前,所以 fun() 可以成功执行,等同如下代码
function fun() {
console.log('i am function')
}
fun() // i am function
接下来看看变量提升和函数提升都存在的情况(重名)
- 函数名与变量名冲突(全局作用域)
首先理解一点,函数提升优先级高于变量提升,也就是说如果发生重名时函数会覆盖掉变量,也可以这样理解,先将 变量提升置顶,然后将函数提升,此时若重名,则后提升的函数就会覆盖掉先提升的变量;看如下代码
console.log(foo) // [Function: foo]
function foo(params) {
console.log(params)
}
var foo = 'i am variable'
console.log(foo) // i am variable
等同如下代码
var foo
function foo(params) {
console.log(params)
}
console.log(foo)
foo = 'i am variable'
console.log(foo)
第一个foo输出的是foo函数,因为函数提升优先级高于变量提升,所以函数覆盖掉了变量;第二个foo输出i am variable,是因为 字符串i am variable赋值给了foo,此时新值(字符串 i am variable)覆盖掉旧值(function)
var fnc = 13
function fnc() {
console.log('ok')
}
fnc() // Uncaught TypeError: fnc is not a function
等同如下代码
var fnc
function fnc() {
console.log('ok')
}
fnc = 13
fnc()
- 函数名与变量名冲突(函数作用域)
在函数内部,就避免不了出现形参,形参其实可以看做是一个局部变量,即在函数内部用 var 声明了形参;但这时候就出现了问题,当函数内部有function,形参,var声明的变量,这个时候代码又是如何执行的?
顺序是这样的,在函数内部,先对变量,形参提升,然后形参赋值,然后函数提升,看如下代码
function func(params) {
console.log('params', params) // params 10
console.log('v', v) // v [Function: v]
console.log('value', value) // value undefined
var value = 100
function v() {}
}
func(10)
等同于如下代码
function func(params) {
var params
var value
params = 10
function v() {}
console.log('params', params) // params 10
console.log('v', v) // v [Function: v]
console.log('value', value) // value undefined
value = 100
}
func(10)
- 总结,首先,函数提升优先级高于变量提升,在函数名与变量名冲突时,全局作用域下,先变量提升,然后函数提升,同名时函数覆盖掉变量,在函数内部,先形参,变量提升,然后形参赋值,然后函数提升,同名时函数覆盖掉变量(函数内部,形参可以看作是一个局部变量,所以当函数名和形参名冲突时,函数会覆盖掉形参)
关于预解析方面的知识,可以多做一些题巩固理解,可以看看以下例题
var a = 1
function b() {
a()
console.log(a) // function a() {}
a = 10
console.log(a) // 10
return
function a() {
console.log(a) // function a() {}
}
}
b()
console.log(a) // 1
var txt = 'hx'
function hello() {
var txt
fn() // world
var fn = function () {
console.log('hello')
}
function fn() {
console.log('world')
}
console.log(txt) // undefined
fn() // hello
}
hello()
function b() {
function a() {
console.log(a)
}
a() // function a
a = 10
a() // 报错 a is not function
return
}
var a
a = 1
b()
console.log(a) // 1