热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

javascript声明提升的介绍(附示例)

​本篇文章给大家带来的内容是关于javascript声明提升的介绍(附示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

本篇文章给大家带来的内容是关于Javascript声明提升的介绍(附示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

Javascript声明提升

在分析声明提升之前,我认为有必要知道的两点:

一、引擎查询变量的两种方式

引擎查询变量的方式可以分为LHS和RHS两种方式,通过“L”和“R”是可以大致了解意思,分别是赋值操作的左侧和右侧。 (不能光是理解为“=”的左右侧可不行,因为赋值操作的形式有多种。)

简单说下我对这两种查询方式的理解:
LHS:赋值操作的目标是谁。 (查询变量)
RHS:谁是赋值操作的源头。 (查询变量的值)

这样说可能有些难以理解,举个栗子:

function foo(a){
    //这里存在一个隐式变量分配,LHS查询变量a,并赋值2.
    //隐式a = 2;
    //左边LHS查询变量b,查询作用域中是否存在b这个变量。
    //右边RHS查询变量a的值,将a赋值给b。
    var b = a;
    //返回a,b是RHS查询变量a的值和变量b的值并使用。
    return a + b;
}
//左边LHS查询变量c,查询作用域中是否存在c这个变量。
//右边RHS引用函数foo,将2作为参数传进去。
var c = foo(2);

二、异常

关于异常要强调一点,必须在严格模式下。因为在非严格模式下,LHS查询若是在最顶层的全局作用域上找不到查询的变量,则会创建一个该名称变量返还给引擎。

ReferenceError:同作用域判别失败相关。(比如:作用域中遍寻不到所需的变量)
TypeError:作用域判别成功了,但是对结果的操作是非法或不合理的。(比如:试图对一个非函数类型的值进行函数调用,或者引用null或undefined类型的值中的属性)

举个栗子:

"strict"
function foo() {
    console.log(a) //undefined
    console.log(b) //ReferenceError
}
var a = 2;

声明提升

一、初步了解

编写Javascript代码时,很多时候都会觉得代码会自上而下的执行。但是碰到声明提升,这种想法就会被打破。

举个栗子:

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

运行结果为: 2

如果按照常理的自上而下执行,那么a执行的预期结果应当是undefined,然而为什么会是2?
这就是声明提升的结果。

二、进一步了解

当初步了解声明提升的时候,碰上下面的代码:

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

运行结果为:undefined

初步了解声明提升之后,会自然而然的认为,声明就会被提升,然而声明的时候赋值,却得不到变量的值。

其实,上面代码的运行步骤可以分解为:

var a; //声明提升
console.log(a); //打印a的值
a = 2; //对a进行赋值

原来,声明提升就是字面上的声明提升,其余的操作(如:赋值和其他逻辑)都还在原地踏步。

声明一个函数进行相应的操作,会得到函数声明提升的结果。由此可以发现:变量和函数的声明都会被提升在其他代码的前面执行。

三、逐步了解

通过几次试验可以逐步了解到,其实声明提升就是:变量和函数的声明会被提升在其他代码(当前作用域)的前面执行。

走到这里,有人就会想到,要是函数表达式,也会进行提升吗?

答案是:不会。而且,即使是具名函数表达式,在名称标识符赋值之前也是不能使用的。

举个栗子:

foo(); //TypeError
bar(); //ReferenceError
var foo = function bar(){};

代码分解为:

var foo; //变量声明提升
foo(); //foo对undefined值进行函数调用导致非法操作,故TypeError
bar(); //bar函数并没有声明,故ReferenceError
foo = function bar(){}; //对foo进行赋值

所以:函数表达式在名称标识符赋值之前是不能使用的。

注意:1、每个作用域都会进行提升操作。(所以函数内部形成的作用域也会有提升操作,提升 操作仅限当前的函数内部作用域)
2、在函数和变量提升时,函数优先提升。
3、一个普通块内部的函数声明通常会被提升到所在的作用域的顶部。

四、深入了解

在阅读《你不知道的Javascript》时,学习let的过程中,会发现有说明提到:使用let进行的声明不会在作用域中进行提升。声明的代码在被运行之前是,声明并不存在。

举个栗子:

console.log(a);
let a = 2;

运行结果是:ReferenceError: Cannot access 'a' before initialization. //初始化前无法访问"a"

然后回到之前我运行的代码,将let换为var,返回的结果是undefined。

二者结合,再加上阅读我用了两个月的时间才理解let这篇文章,发现对let是否提升有了一个更新的认识。

作者把js变量分成三部分操作:创建(create)、初始化(initialize)和赋值(assign)

上面的操作之所以会有不同的响应并不是说let没有创建,而是有一个初始化的过程并没有执行。而在初始化之前使用变量,就会形成一个暂时性死区

经过var和let和function的测试可以总结到:

var的创建和初始化被提升,赋值不会被提升。

let的创建被提升,初始化和赋值不会被提升。

function的创建、初始化和赋值均会被提升。

本篇文章到这里就已经全部结束了,更多其他精彩内容可以关注PHP中文网的Javascript教程视频栏目!

以上就是Javascript声明提升的介绍(附示例)的详细内容,更多请关注 第一PHP社区 其它相关文章!


推荐阅读
  • 本文介绍了如何使用PHP向系统日历中添加事件的方法,通过使用PHP技术可以实现自动添加事件的功能,从而实现全局通知系统和迅速记录工具的自动化。同时还提到了系统exchange自带的日历具有同步感的特点,以及使用web技术实现自动添加事件的优势。 ... [详细]
  • 2018年人工智能大数据的爆发,学Java还是Python?
    本文介绍了2018年人工智能大数据的爆发以及学习Java和Python的相关知识。在人工智能和大数据时代,Java和Python这两门编程语言都很优秀且火爆。选择学习哪门语言要根据个人兴趣爱好来决定。Python是一门拥有简洁语法的高级编程语言,容易上手。其特色之一是强制使用空白符作为语句缩进,使得新手可以快速上手。目前,Python在人工智能领域有着广泛的应用。如果对Java、Python或大数据感兴趣,欢迎加入qq群458345782。 ... [详细]
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • PHP玩家基地系统毕业设计(附源码、运行环境)的用户登录界面、游戏管理和玩家作品管理
    本文介绍了一个PHP玩家基地系统的毕业设计,包括用户登录界面、游戏管理和玩家作品管理等功能。附带源码和运行环境,并提供免费赠送本源代码和数据库的方式,请私信获取详细信息。摘要共计约XXX字。 ... [详细]
  • Monkey《大话移动——Android与iOS应用测试指南》的预购信息发布啦!
    Monkey《大话移动——Android与iOS应用测试指南》的预购信息已经发布,可以在京东和当当网进行预购。感谢几位大牛给出的书评,并呼吁大家的支持。明天京东的链接也将发布。 ... [详细]
  • 本文介绍了《中秋夜作》的翻译及原文赏析,以及诗人当代钱钟书的背景和特点。通过对诗歌的解读,揭示了其中蕴含的情感和意境。 ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
  • 本文描述了作者第一次参加比赛的经历和感受。作者是小学六年级时参加比赛的唯一选手,感到有些紧张。在比赛期间,作者与学长学姐一起用餐,在比赛题目中遇到了一些困难,但最终成功解决。作者还尝试了一款游戏,在回程的路上感到晕车。最终,作者以110分的成绩取得了省一会的资格,并坚定了继续学习的决心。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
    本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
author-avatar
球球爱生活0423
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有