IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> JavaScript变量提升详解 -> 正文阅读

[JavaScript知识库]JavaScript变量提升详解

变量提升

在js中我们用var声明的变量是存在变量提升的。换句话说,我们js的解释器在解释js代码的时候,会优先把所有的变量声明提到前面。

示例代码

var的变量提升

下面我演示的就是一个简单的变量提升的问题。

js源代码

console.log(a)
var a=1
console.log(a)

js解释器编译的顺序:

//js编译时会把所有的变量声明提前
var a;
console.log(a)//显示undefiend,因为此时a没有赋值不知道数据类型
a=1//赋值操作不提前,只是var a的声明提前了
console.log(a)//输出a

这里理解的要点是,js只是把变量的声明提前了。但是赋值并没有提前。var a=1其实是两行代码的简写,var a;a=1

function变量赋值提升

接下来这个问题可是经典的面试题

function foo(a){
    console.log(a)
    var a=2
    function a(){
        
    }
    console.log(a)
}
foo(10)

请问两次的console.log分别打印出什么呢?

想要搞清楚这个问题,我们需要理解变量提升的优先级。
其实在JS中,被变量提升的不仅仅有var还有我们的function,而且function提升变量的优先级要比var要高一些,而且这个函数变量提升还是变量和赋值同时提升!!!

所以上面这段代码在js解释器下是按照这样的顺序解释的

function foo(a){
    //function a变量提升,并赋值function
    var a=function (){
        
    }
    console.log(a)
    a=2
    console.log(a)
}
foo(10)

虽然我们调用foo函数时候传递了一个10进去,但是根据js的作用域链规则,js会优先在最小的作用域依次,向上、向外去寻找声明的变量。显然这个时候我在外面传的10就没有作用了,因为js在向上找的同时在{}里面找到了变量a的声明,也就是var a=function(),就没有必要向外找传递进来的10了

所以第一个打印语句打印的是函数本体,第二个打印的是2

理解上面代码的要点是理解function声明函数其实是变量和赋值同时提升,这里和我们的var是不一样的,var仅仅是声明提升,它的赋值不会提升,所以才有可能打印出undefined(undefined就是声明了但是却没有赋值的意思)

局部变量的偷偷赋值

我们看下下面案例的输出

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

foo(10)

输出结果是10

奇怪了这是为什么呢?a我们没有赋值呀,根据作用域链规则,应该是undefined呀。为什么传递进去的10,却打印出来了。

其实这里的底层是这样的

//在括号外部a接收了传递的10
function foo(var a=10) {
	//你自己重复声明变量
    var a
    console.log(a)
}

foo(10)

我们在console.log(a)时候,js沿着作用域链在括号内寻找,找到了a,发现是undefined,但是js不甘心,继续沿着作用域链向上检索,终于搜寻到外面的形参声明赋值,然后输出10
也就是说作用域链向上查找不是查到声明就完的,如果js发现它是undefined的话还会继续向上找

我们再来一道题练习一下作用域链

var a=10
var a=2
{
    var a
    console.log(a)
}

输出2,不是undifined,js找到undifined是不会甘心的,会继续向上找不是undifined的数值,找到了一个不是undifined就不继续找了

再来看一个有趣的事情

function foo(a){
    console.log(a)
    var a=2
    console.log(a)
}
foo(10)

这个我们来看js编译之后的执行顺序

//形参接收a=10 这里写var其实是有语法错误的,我这样写是为了让大家理解
function foo(var a=10){
    console.log(a)
    a=2
    console.log(a)
}
foo(10)

显然输出10和2

箭头函数和function不一样

function foo(a) {
    console.log(a)
    a = () => {

    }
    var a = 2
    console.log(a)
}

foo(10)

输出什么呢?

我们来分析一下js编译之后的执行顺序

//局部变量声明并接收参数赋值
function foo(var a=10) {
    var a
    console.log(a)
    a = () => {

    }
    // var已经声明提升了
    a = 2
    console.log(a)
}

foo(10)

输出10和2

这里注意的是我们的箭头函数和function是不一样的,上面说我们的function是变量声明提升,赋值也会提升,但是我们的箭头函数仅仅只会变量提升而已,因为()=>function关键字是不一样的,function是声明函数的关键字,()=>只是一个赋值的右值而已

回过头来再看这个例子

function foo(a) {
    console.log(a)
    function a (){

    }
    var a = 2
    console.log(a)
}

foo(10)

它输出的是function()和2

js编译后的执行顺序如下

//接收形参的传值
function foo(var a=10) {
    var a = function (){
    
    }
    console.log(a)
    var a = 2
    console.log(a)
}

foo(10)

好了,相信通过我的讲解,大家应该对变量提升有了新的认识了。我们下次再见,see you!

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-17 15:18:45  更:2021-08-17 15:21:08 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 9:26:01-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码