千锋教育-做有情怀、有良心、有品质的职业教育机构

400-811-9990
手机站
千锋教育

千锋学习站 | 随时随地免费学

千锋教育

扫一扫进入千锋手机站

领取全套视频
千锋教育

关注千锋学习站小程序
随时随地免费学习课程

上海
  • 北京
  • 郑州
  • 武汉
  • 成都
  • 西安
  • 沈阳
  • 广州
  • 南京
  • 深圳
  • 大连
  • 青岛
  • 杭州
  • 重庆
当前位置:太原千锋IT培训  >  技术干货  >  变量的预解析

变量的预解析

来源:千锋教育
发布人:qyf
时间: 2023-01-31 17:50:08

  预解析呢,也被称为预解释;他对于我们初学者来说,还是蛮重要的,因为他涉及到了我们js代码的执行机制。“预解析”,这个“预”,我们会联想到“预备”、“预先”;而javascript 是一个解释型语言,所以可以理解为在代码开始执行之前,会对代码进行通读解释,然后在进行执行。所以,当我们写完代码,打开浏览器的时候,代码已经执行了,或者说这个解释的过程已经过去了,那么,这个过程,他解释了什么内容呢?

  什么情况预解析

  1、var关键字

  在代码执行之前,会把代码里面所有的 var 关键字声明的变量提升

  比如说

  console.log(num) // undefined

  var num = 100

  在这个代码块中,运行console.log(num)之前;会将页面整个代码通读解释一下,看是否有var关键字;我们发现是有的,所以在代码执行之前,先告诉浏览器num这个变量可以使用,只不过不赋值;也就是我们常说的声明提前;所以上面的两行代码,其实等价于

  var num

  console.log(num)

  num = 100

  2、声明式函数

  在代码执行之前,会把代码里面的 声明式函数的变量 提升,并且给这个变量赋值为一个 函数的地址

  举个例子

  fn()

  function fn() {}

  在代码fn()执行之前,浏览器已经知道了 fn 变量可用;并且 fn 变量的值是一个函数的地址;这些是浏览器已经通读解释好了的,所以这个时候,在function fn() {}上方调用函数是没有问题的,这也是声明式函数可以在上方调用的原因。

  值得注意的是赋值式函数

  赋值是式函数按照 var 关键字的解析规则解析

  比如说:

  fn()

  var fn = function () {}

  在代码执行之前,浏览器先通读解释,遇见了var关键字,知道了 fn 这个变量可用,仅此而已 在执行fn()这句代码的时候,fn 只是一个变量,还没有赋值,是 undefined

  console.log(fn)//undefined

  fn()

  var fn = function () {}

  但是()是函数执行,所以fn()这样子,是把 fn 当作函数来执行了;那么就会报错 fn is not a function!!所以赋值式函数是不能在上方调用的,因为那个时候,他还不是一个函数。

  函数预解析

  函数内部的预解析,是比较常见的,我们通过三个案例来更清楚的认识了解它。

  案例一:

  fun()

  var fn = function () {

  console.log('我是 fn 函数')

  }

  function fun() {

  console.log('我是 fun 函数')

  }

  fn()

  fn = 100

  fn()

  上述代码,是怎样运行的呢?首先,在代码执行之前,我们先预解析:

  1. 我们找到了var关键字,所以知道全局声明一个 fn 变量可用

  2. 我们看到了声明式函数,所以知道全局声明一个 fun 变量可用,并且这个变量的值是一个函数的地址

  3. 预解析完成,开始执行代码

  3-1、fun() 这个代码执行,因为我们上方已经预解析知道fun这个变量可用,并且是一个函数地址,所以直接执行这个函数,控制台打印出 “我是 fun 函数”

  3-2、然后执行fn = function () {console.log('我是 fn 函数')}这块代码,给fn赋值;把一个函数的地址给到了 fn 这个变量

  3-3、再之后,执行 fn()。可以直接调用函数,控制台打印“我是 fn 函数”

  3-4、紧接着,执行fn = 100;也就是给 fn 这个变量重新赋值为 100

  3-5、最后执行 fn()这行代码 那么就会报错 fn is not a function

  案例二:

  fn()

  function fn() {

  console.log('我是一个 fn 函数')

  }

  fn()

  var fn = 100

  fn()

  这个案例中,变量名和函数名重复了,那应该是什么样子的呢?

  我们先预解析

  1. 首先,我们看到了声明式函数,所以全局声明一个 fn 变量可用,并且赋值为一个函数的地址

  1. 紧接着,我们看到了var关键字,所以全局声明一个 fn 变量可用;请注意这个没有赋值

  但是我们在第一步的时候,已经知道有一个fn变量可用;所以第二句话就没有什么用了。

  2. 预解析完成,开始执行代码

  3-1、我们代码第一步执行fn();此时 fn() 是一个函数的地址,执行函数

  3-2、 我们代码第二步执行fn();此时fn() 还是一个函数的地址,函数执行

  3-3、 我们代码第三步,执行fn = 100;给 fn 从新赋值,赋值为 100;从此时开始,fn不是一个函数了,是一个数值

  3-4、我们代码第四步执行fn();把数值当成函数,就会报错 fn is not a function

  所以当函数名和声明的变量名同名的时候,var 的声明就没有意义了

  案例三:

  function fn(a) {

  console.log('我是 fn 函数')

  a()

  function a() {

  console.log('我是函数 a')

  }

  }

  fn(10)

  这个案例,我们聊一下函数在执行阶段,都做了哪些事情

  首先我们要明确一件事情,那就是预解析会解析函数外部的内容,不会解析函数内部的内容

  那么,我们回顾一下函数的执行过程

  1. <!--*按照函数名称的地址找到函数*-->
  2. <!--*行参赋值*-->
  3. <!--*函数内部的代码进行预解析*-->
  4. <!--*把函数体内存储的代码拿出来执行一下*-->

  然回顾了函数的执行过程之后,我们来分析上方案例三的代码,首先 ,全局预解析

  1.在全局下,我们看到了声明式函数fn,所以知道先 声明一个 fn 变量可用,并且 fn 的值是一个函数地址

  2.预解析完成,开始执行代码

  2-1、 执行这行代码fn(10);然后就是函数的执行过程

  2-2、 函数的执行过程

  2-2-1、形参赋值 , 先给 a 赋值为一个数字 10

  2-2-2、函数内部的代码进行预解析,声明一个 a 变量可用,并且赋值为一个函数的地址;所以函数体内的代码在一开始执行的时候 a 就是一个函数地址

  2-3、 函数体内的代码执行,也就是执行a()这行代码,因为我们在2-2-2的时候,a就是一个函数地址了,所以我们会在控制台打印'我是函数 a'

  预解析的无节操

  1. 不管 if 条件是否成立,代码块里面的 var 都会进行声明

  2. return 后面的代码虽然不会执行,但是会进行预解析

  举个例子

  function fn() {

  console.log(num1)

  return

  var num1 = 100

  }

  fn()

  console.log(num)

  if (false) {

  var num = 100

  }

  在上述代码中,我们会先去预解析

  1. 首先,我们看到了声明式函数,所以全局声明一个 fn 变量可用,并且赋值为一个函数的地址

  1. 紧接着,我们看到了var关键字,所以全局声明一个 num 变量可用

  2. 预解析完成,开始执行代码

  3-1、先执行fn()这行代码,然后就是函数的执行过程

  3-1-1、直接就是函数内部的预解析,正常情况,return后面的代码是不执行的,但是预解析他没有节操,还是大大咧咧的开始进行自己的骚操作;声明了一个变量num1可用

  3-1-2、函数内部代码执行 ,也就是执行console.log(num1)折行代码,那么结果就是undefined

  3. 执行下一行代码console.log(num);因为在预解析的时候,我们已经知道有一个num变量可用;所以结果是undefined。

  4. 因为选择分支结构中,条件表达式为false,所以不会再进行下面的num赋值操作了。

  这个就是预解析的无节操,概括的说,就是上述的两点,不管 if 条件是否成立,代码块里面的 var 都会进行声明,return 后面的代码虽然不会执行,但是会进行预解析

声明:本站稿件版权均属千锋教育所有,未经许可不得擅自转载。

猜你喜欢LIKE

React的遮羞布

2023-01-31

Local Storage的高阶用法

2023-01-31

javascript中如何将伪数组转换成真数组

2023-01-30

最新文章NEW

变量的预解析

2023-01-31

Vue中常见的组件间通信方案及典型应用场景

2023-01-31

VueJS中的动画菜单效果的实现

2023-01-31

相关推荐HOT

更多>>

快速通道 更多>>

最新开班信息 更多>>

网友热搜 更多>>