首页 >

JavaScript中标识符提升问题【javascript】

web前端|js教程

JavaScript中标识符提升问题【javascript】

JavaScript,标识符提升
web前端-js教程
JS 存在变量提升,这个的设计其实是低劣的,或者是语言实现时的一个副作用。它允许变量不声明就可以访问,或声明在后使用在前。新手对于此则很迷惑,甚至许多使用JS多年老手也比较迷惑。但在 ES6 加入 let/const 后,变量Hoisting 就不存在了。
排版源码,ubuntu怎么访问磁盘,tomcat运行慢怎么解决,taptap爬虫 评论,PHP调用paddleocr,百度排名seo优化违法吗lzw
A、 变量未声明,直接使用
本地部署微办公源码破解版,vscode设置错误,ubuntu groovy,tomcat安装手册,SQLITE系统生成时间,wordpressqq客服插件,前端学习可以直接学框架吗,爬虫显示文件未存在,shuffle php,上海开眼seo招聘,在线刷业务网站源码,网页模板图片,微信后台 模板lzw
function test() {  alert(notDefined);}test(); // ?
报错是自然的
微信版彩票源码,vscode lua语言,arm ubuntu 性能,tomcat禁用put,sqlite怎么退出,使用游戏服务器违法吗,免费抽奖插件,前端自动学习框架教程,小丸爬虫,php开发培训学费,关键词seo怎么做,好看的网站网站引导页我,管理员网页模板,数据展示网页模板,订单详情页面,博客管理系统php源代码,b2b程序系统推荐lzw
二. 变量声明在末尾

function test() {  alert(declaredButNotAssigned); // undefined  var declaredButNotAssigned;}test();
输出 undefined, 结果比上例有所改善,没有报错,代码可以运行,但变量值可能不是程序员所期望的。

C、 变量声明在末尾,同时给变量赋值

function test() {  alert(declaredAndAssigned); // undefined  var declaredAndAssigned = 1;}test();
结果和 二 相同, 很明显,并不会因为赋值了就输出 1。

B、三 都发生了变量提升(Hoisting),简单定义

变量提升: 在指定作用域里,从代码顺序上看是变量先使用后声明,但运行时变量的 “可访问性” 提升到当前作用域的顶部,其值为 undefined ,没有 “可用性”。

这里强调 “代码顺序” 和 “运行顺序”,是因为多数时候我们写的代码都是顺序执行的,即 “代码顺序” 和 “运行顺序” 是一致的。这也符合人的大脑的思维过程。比如有过 C语言 经验的程序员

#include int main() {  int x = 1;  printf("%d, ", x); // 1}
两句代码,先声明整数型 x, 再输出。代码顺序和运行顺序是一致的,即正常运行。

如果顺序反过来

#include int main() {  printf("%d, ", x); // error  int x = 1;}
此时,编译都不能通过了。但JS里可以反过来写,见B、三。

因此,有类 C语言 经验的程序员,都很清楚变量需要 先声明后使用,不然会报错。而到了JS里,有 变量提升 现象,可以 先使用后声明,C 的经验用到 JS 里迷惑便出现了。

D、 函数表达式也存在变量提升

function test() {  alert(func); // undefined  var func = function() {};}test();
但如果想使用这个 func,则无可能

function test() {  alert(func); // undefined  func(); // 报异常  var func = function() {};}test();
结果func 是 undefined,调用 func 则会报异常。 在上面的定义中提到了 可访问性 和 可用性 对应如下语句。

可访问性:alert(func),输出 undefined,可以运行,可以访问 func。

可用性: func(), 报异常,不能正常调用 func,表示无可用性。

B、C、四 都是使用 var 声明的变量,JS 里函数声明也会存在提升,只是这个 “变量” 比较特殊,它是一个 function 类型(可以作为函数、方法或构造器)。它的名字(标识符)也会提升到当前作用域的顶部。

E、函数声明的名也会提升到当前作用域顶部

function test() {  alert(f1); // function  f1(); // "called"  function f1() {    alert('called');  }}test();
我们看到,声明 f1 在代码最末,f1 使用在前,alert(f1) 和 f1() 都正常执行,表示 可访问性 和 可用性 都有了。

前面说了,变量提升(Hoisting)没什么用,属于语言的低劣设计,好的习惯还是 “先声明后使用”。这个特性也会出现在不少大公司面试题里

题1:

// 写出以下代码的运行结果var a = 1;function fn() {  if (!a) {    var a = 2;  }  alert(a); // ?}fn();
题2:

// 写出以下代码的运行结果var a = 1;function fn() {  a = 2;  return;  function a() {}}fn();alert(a); // ?
但这一切随着 ES6 的 let/const 到来结束了,ES里除全局变量外,其它都使用 let/const,var 替换成 let 后变量提升就不复存在了。

function test() {  alert(declaredButNotAssigned1); // 报异常  alert(declaredButNotAssigned2); // 报异常  alert(func); // 报异常   let declaredButNotAssigned1;  let declaredButNotAssigned2 = true;  let func = function() {};}test();
这强制程序员养成好的习惯,变量需要“先声明再使用”,否则报错。

以下摘自MDN的关于let不在发生变量提升的描述


In ECMAScript 6, let does not hoist the variable to the top of the block. If you reference a variable in a block before the let declaration for that variable is encountered, this results in a ReferenceError, because the variable is in a "temporal dead zone" from the start of the block until the declaration is processed.

用 let 声明变量后,typeof 也不再安全

if (condition) {  alert(typeof num); // Error!  let num = 100;} 
以前可以用 typeof == ‘undefined’,来判断是否引入了某lib,比如jQuery

// 判断jQuery是否引入了if (typeof $ !== 'undefined') {  // do something}...
jQuery没有引入,$ 没有声明,这句也不会报错而影响到下面的代码执行,但如果是 let 声明的就会报错了。

以上所述就是本文的全部内容了,希望大家能够喜欢。


  • 暂无相关文章