web面试之JS预解析与变量提升区别

目录
  • 什么是预解析?
  • 变量和函数预解析的区别
  • 重复声明var变量
  • 变量提升和函数提升优先级
  • 函数优先级大于变量优先级的深入探究
  • 预解析流程
    • 搜寻预解析关键字
    • 执行预解析
  • 几个需要注意的细节

什么是预解析?

概念:

JS代码在在代码从上往下执行前,浏览器会先把所有变量声明解析一遍, 这个阶段叫预解析。

详讲

寻找作用域中的var 和function声明(匿名函数没有function声明,所以不会提升),然后对其进行事先声明, 并把赋值操作留在原地,再从上到下执行代码。这就是一个预解析的过程。

变量和函数预解析的区别

​ 在预解析时,会把所有用 var 声明的变量, 和 function 声明的函数,提升到所在的作用域最顶端

var声明的变量, 在预解析的时, 只是提前了声明, 赋值语句依然留在原地;

function 声明的函数, 在预解析的时, 会提前声明并同时定义, 函数执行的时候,函数内部才会进行预解析。

注意: 匿名函数没有function声明,所以不会提升

重复声明var变量

var重复声明时:若已经存在,编译器会忽略 var 继续向下编译;

若不存在,则顺着作用域链向上查找,

若没有找到,会在本作用域声明该变量

变量提升和函数提升优先级

总结:

函数提升优先级高于变量提升,且不会被同名变量声明时覆盖,但是会被变量赋值后覆盖

下面内容转载自:

https://blog.csdn.net/caoyafeicyf/article/details/53172532

函数优先级大于变量优先级的深入探究

浏览器的预解析过程

先由一道小题进入本文

var foo;
function foo(){}
console.log(foo);

结果是函数体function foo(){}
接着下面一道题:

function foo(){}var foo;console.log(foo);

结果也是函数体

function foo(){}

所有就有很多人说,函数声明的优先级大于变量声明的优先级。

那么,为什么呢?这就要从浏览器的预解析说起了。

预解析流程

搜寻预解析关键字

寻找var关键字

寻找function关键字

执行预解析

先应用var关键字声明的标识符,使这些标识符有定义
标识符有定以后,使用这项标识符就不会报错了但因为没有赋值,因此其值为undefined

至此标识符中保存了函数的引用

几个需要注意的细节

  • var 关键字对同一个标识符重复使用时,除第一次有效外,其他均做忽略处理。
  • 预解析时先处理变量声明,再处理函数声明不
  • 要纠结谁的优先级高,这些只是表面现象
  • 懂得了预解析流程,一切都是浮云

看了预解析原理以后,下面咱们回到本文开头的两题,分析下预解析的过程,详细的了解为什么函数的优先级高于变量的优先级。follow me

先看第一个

var foo;
function foo(){}
console.log(foo);

预解析过程为:

var foo;<----变量声明的var
var foo;<----函数声明抽出的var
foo=function (){}<----函数声明抽出的赋值
console.log(foo);

再来看第二个

function foo(){}
var foo;
console.log(foo);

预解析过程为:

var foo;<----变量声明的var
var foo;<----函数声明抽出的var
foo=function (){}<----函数声明抽出的赋值
console.log(foo)

比较这两个,你发现了什么?原来他们的预解析过程一样啊,这也就是为什么函数优先级高于变量的原因了。

如果你理解了上面的内容,那么下面再出一个题:

var a=1;
function a(){}
console.log(a);

这个浏览器是如何解析的呢?下面来跟着我的思路一起走:

1. 解析器首先搜寻var 关键字,结果第一行就发现了,把它提取到开头。
2. 解析器搜寻function关键字,第二行发现了,首先分离var+函数名,此时发现和第一步的一样,不做处理,然后开始分离函数的赋值,也就是a=function (){},此时a为函数体。
3. 解析器接着处理变量的赋值,a=1,上一步的函数体被覆盖掉,此时a=1。
4. 最后处理console.log(a),自然而然的结果为1。

下面是解析器处理的代码过程:

var a;<----变量声明的var
var a;<----函数声明抽出的var
a=function (){}<----函数声明抽出的赋值
a=1;
console.log(a);

以上就是web面试之JS预解析与变量提升区别的详细内容,更多关于JS预解析与变量提升的资料请关注我们其它相关文章!

(0)

相关推荐

  • 详解JS预解析原理

    目录 预解析的的不同机制 var的预解析机制 function 关键字的预解析步骤 预解析机制 面试题 预解析的的不同机制 预解析也叫预声明,是提前解析声明的意思:预解析是针对变量和函数来说的:但是变量和function的的预解析是两套不同的机制: 当浏览器加载我们的HTML页面的时候,首先会提供一个供JS代码执行的环境->全局作用域global(浏览器中的全局作用域,也叫顶级作用域是window) JS中的内存空间分为两种:栈内存.堆内存 栈内存:提供JS代码执行的环境,存储基本数据类型的值:

  • 详解javascript 变量提升(Hoisting)

    简介 "变量提升"意味着变量和函数的声明会在物理层面移动到代码的最前面,但这么说并不准确. 实际上变量和函数声明在代码里的位置是不会动的,而是在编译阶段被放入内存中. 声明变量的方法 var.let.const 不用以上关键字直接赋值的变量会挂载与windows环境下; let a=9 const a=1 var a=6 c=5 声明函数的方法 javascript中声明函数的方法有两种:函数声明式和函数表达式. //函数声明 function say(){ console.log('

  • JS变量提升及函数提升实例解析

    1在js中只有两种作用域 a:全局作用域 b:函数作用域 在ES6之前,js是没有块级作用域. 首先来解释一下什么是没有块级作用域? 所以此时 是可以打印输出变量a的值. 2:什么是变量提升? 在我们的js中,代码的执行时分两步走的,1.预解析 2.一步一步执行 在预解析阶段:首先会在全局作用域内,js解析器会找所有的 var .function .参数,并提前到当前作用域的最顶上去(变量的赋值操作不会提前,还在原来的地方),此时并没有执行代码. 然后再开始一行一行执行代码.遇到了函数调用,于是

  • 深入理解JavaScript中的预解析

    前言 JavaScript是解释型语言是毋庸置疑的,但它是不是仅在运行时自上往下一句一句地解析的呢? 事实上或某种现象证明并不是这样的,通过<JavaScript权威指南>及网上相关资料了解到,JavaScript有"预解析"行为.理解这一特性是很重要的,不然在实际开发中你可能会遇到很多无从解析的问题,甚至导致程序bug的存在.为了解析这一现象,也作为自己的一次学习总结,本文逐步引导你来认识JavaScript"预解析",如果我的见解有误,还望指正. 在

  • 跟我学习javascript的var预解析与函数声明提升

    1.var 变量预编译 JavaScript 的语法和 C .Java.C# 类似,统称为 C 类语法.有过 C 或 Java 编程经验的同学应该对"先声明.后使用"的规则很熟悉,如果使用未经声明的变量或函数,在编译阶段就会报错.然而,JavaScript 却能够在变量和函数被声明之前使用它们.下面我们就深入了解一下其中的玄机. 先来看一段代码: (function() { console.log(noSuchVariable);//ReferenceError: noSuchVari

  • web面试之JS预解析与变量提升区别

    目录 什么是预解析? 变量和函数预解析的区别 重复声明var变量 变量提升和函数提升优先级 函数优先级大于变量优先级的深入探究 预解析流程 搜寻预解析关键字 执行预解析 几个需要注意的细节 什么是预解析? 概念: JS代码在在代码从上往下执行前,浏览器会先把所有变量声明解析一遍, 这个阶段叫预解析. 详讲 寻找作用域中的var 和function声明(匿名函数没有function声明,所以不会提升),然后对其进行事先声明, 并把赋值操作留在原地,再从上到下执行代码.这就是一个预解析的过程. 变量

  • JavaScript预解析之变量预解析和函数预解析

    首先了解预解析之前先看两个问题 1.大家思考下  这个结果会是多少呢? console.log(num); var num=10; 结果是 undefined 2.这个输出结果又会是多少呢? fun(); var fun=function(){ console.log(22); } 显然这个结果报错了. 那究竟为什么会这样执行呢? 1.我们js引擎运行js分为两步: 预解析   代码执行 预解析 js引擎会把js里面所有的var还有function提升到当前作用域的最前面 代码执行 按照代码书写

  • JS中作用域和变量提升(hoisting)的深入理解

    作用域(Scoping) 对于Javascript初学者来说,一个最迷惑的地方就是作用域:事实上,不光是初学者.我就见过一些有经验的javascript程序员,但他们对scope理解不深.javascript作用域之所以迷惑,是因为它程序语法本身长的像C家族的语言.我对作用域的理解是只会对某个范围产生作用,而不会对外产生影响的封闭空间.在这样的一些空间里,外部不能访问内部变量,但内部可以访问外部变量. c语言的变量分为全局变量和局部变量,全局变量的作用范围是任何文件和函数访问(当然,对于非变量定

  • 通过示例演示理解javascript预解析

    目录 提出问题 坑一 坑二 问题解答 案例练习 案例一 案例二 案例三 案例四(经典的面试题) 结语 面试官最爱考的javascript预解析,你搞明白了吗?javascript的es5语法和其他语言还是有些区别的,预解析正是面试爱考的重点,不妨来看看这篇博文… 提出问题 先看下面的两个最基本问题,结果你想到了吗? 坑一 <script> // 坑一 console.log(num); var num = 10; </script> 结果为什么会是undefined呢?先保留这个疑

  • web面试常问http缓存解析相关

    目录 为什么要有http缓存? http缓存之 强制缓存 http缓存之 协商缓存(对比缓存) 协商缓存中的资源标识 为什么要有http缓存? 1.当输入网址到加载出页面, 电脑会经过"CPU计算.网络请求.页面渲染"等一系列步骤; 2."网络请求"是其中最不确定.最耗时的一个环节, 针对这个环节, 我们可以通过"减少网络请求的体积和数量", 来更快加载出页面, 这是"缓存"存在的原因; 3.通过"缓存"可

  • JavaScript预解析,对象详解

    目录 一.预解析 1.变量预解析和函数预解析 1.变量预解析 2.函数预解析 2.预解析案例 二.对象 1.创建对象的三种方式 1.利用字面量创建对象 2.利用new Object创建对象 3.利用构造函数创建对象 4.构造函数和对象 2.new关键字 3.遍历对象属性 总结 一.预解析 1.变量预解析和函数预解析 JavaScript 代码是由浏览器中的 JavaScript 解析器来执行的.JavaScript 解析器在运行 JavaScript 代码的时候分为两步:预解析和代码执行. 预解

  • JavaScript中的变量提升和函数提升

    目录 前言 为什么有变量提升 javascript变量提升和函数提升 总结 前言 在js中对变量进行操作后打印值经常会出现undefined的现象.其实原因是因为js中有一个叫做变量提升的功 举例: var data="lyyyyy"; getData(); function getData(){ //第一次打印 console.log("data值为: ", data); var data="yyyyyyy"; //第二次打印 console.

  • 浅谈js script标签中的预解析

    首先介绍预解析,虽然预解析字面意思很好理解,但是却是出坑出的最多的地方,也是bug经常会有的地方,利用好预解析的特性可以解决很多问题,并且提高代码的质量及数量,浏览器在解析代码前会把变量的声明和函数(整个函数体)提前到当前作用域的最顶端. 细节问题:在多对的script标签中如果有相同的函数,那它们相互之间是不会受影响的,在第二对script标签中声明变量或者是创建函数,在第一对script标签中是无法访问到的,这就说明了,javaScript的预解析只会在各自的script标签中发生,同时,第

随机推荐