博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
js变量提升的一个小坑
阅读量:4971 次
发布时间:2019-06-12

本文共 1801 字,大约阅读时间需要 6 分钟。

好久没写博客了,原本想实训结束能对整个实训项目认真总结一下,没想到回到学校一点都不轻松,最近在制作网页版简历,遇到了一个小问题,现在不总结以后肯定忙得顾不上,所以长话短说,抓紧时间写下来.

对js语法比较熟的同学可能都知道:js是没有块级作用域的,有一个新手很容易出错的地方

for(var i = 0 ; i < 10 ; i ++){    setTimeout(function(){        console.log(i)    },1000*i)}

这段代码会输出10个10,而不是期望的1,2,...,10,原因正是因为每次循环的作用域是相同的,于是他们共享同一个i,这个问题很简单,这里就不细说了,这次要说的在后面

注意下面这段代码

 
console.log(a)  // undefined
if(!a){    var a = 1;}console.log(a)  //1

倘若a不存在,就声明一个变量a并复制为1,这段代码运行起来,控制台会不出意外地打印出 1 , 看起来好像没什么问题, 但实际发生了什么呢?

1. 将该作用域中使用的所有变量提升到当前作用域的首部进行声明,对于这段代码,因为js没有块级作用域,相当于将代码改为

var a;/*其他变量*/

2. 声明完毕后执行代码

if(!a){  //执行到这里时a其实已经声明了,只是没有赋值    a = 1;}console.log(a);  //1 /*其他语句*/

看起来好像不是什么太大的问题,但是在某些情况下对这件事情不理解就麻烦啦,举个例子,在遍历树的时候我们要用到递归,就拿递归来说事吧

function test(){    console.log("test");    if(!a){        var a = 1;    }    if(a < 3){
     a++; test(); }}

在外部调用test会发生什么呢? 至少我在写这篇博客以前以为会输出3个test了事,事实是,函数不断地调用自身,无休止地打印test

在开发中写这样一段函数时,我的想法是:在递归的入口函数保存一个数组,函数执行的过程中会根据条件进入不同的分支,从而在这个数组中增或删一些元素,最终将该数组返回,实际运行时发现返回的结果并不符合预期,每一次调用好像都重新声明了一个数组, if(!a) 的判断根本没有向调用者(父作用域)中查找变量,抓耳挠腮了很久,才突然想起以前看过变量提升相关的总结.只是因为当时觉得这个事情在其他语言里也会发生,很简单,就没当回事,果然今天就受到了制裁,耽误了不少时间才想到这里

其实理解这个问题很简单,写下面一段代码测试

if(!a){  //a尚未声明    a = 1;}console.log(a) //报错Uncaught ReferenceError: a is not defined

因为没有使用var关键字,js引擎没有对a进行变量提升,所以在运行到第一行的时候a是未声明的变量,会直接报错

那么怎么test()到底怎么写呢?

var path;function find(orignNode, desNode){    if(!path){
console.log("初始化路径") path = [orignNode]; }    temp = /*其他代码*/; find(orignNode, temp); }

目前我是这么解决的,很明显的缺点:占用了父作用域中的变量path,并且每次调用find前都要对path置空,这样的代码看起来很不爽,但是迫于水平有限,一时也没有想出更好的办法(还有一个方法是绑定到当前函数所处的闭包中(this.path),函数return之前

var path = this.path;delete this.path;return path;

感觉也没好到哪里去,若您有好的解决方案,欢迎在下面留言

另外,打个小广告,也是我发现这个问题的源头,就是我的个人主页啦(http://iny7.com),页面还在开发当中,希望能得到各位的指点 ^_^

 

转载于:https://www.cnblogs.com/iny7/p/5398101.html

你可能感兴趣的文章
jekyll bootstrap更改主题theme
查看>>
POJ1300(欧拉回路)
查看>>
HDU 1598 find the most comfortable road (最小生成树) &gt;&gt;
查看>>
数码管 键盘 十进制计数
查看>>
算法7-10:拓扑排序
查看>>
快速智能数据导入工具1.0
查看>>
态度决定品质
查看>>
NPOI Excel 单元格背景颜色对照表
查看>>
微信小程序去除button默认样式
查看>>
11/26
查看>>
Where does Visual Studio look for C++ Header files?
查看>>
JSP生成Excel报表
查看>>
Java打包可执行jar包 包含外部文件
查看>>
python第一周语言基础
查看>>
kettle的基本使用
查看>>
伪装虽易测试不易之微信浏览器
查看>>
Xcode 5.1.1 与 Xcode 6.0.1 共存
查看>>
窥探 kernel --- 进程调度的目标,nice值,静态优先级,动态优先级,实时优先级...
查看>>
使用bootstrap table时不能显示筛选列和分页每页显示的行数
查看>>
利用php cookie实现浏览历史功能
查看>>