js预解析函数名变量名冲突

什么是预解析?

  • 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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值