JavaScript数组索引访问返回undefined及控制台提示问题解析
问题:数组push元素后,console.log(array)能看到元素但array[0]返回undefined,以及控制台蓝色提示的含义
我创建了一个数组array,通过array.push()方法向其中插入元素。执行console.log(array)时能看到对应输出,但执行console.log(array[0])却返回undefined。请问这是什么原因?另外截图中的蓝色提示“this value was evaluated on first expanding it may have changed since then in array javascript”是什么意思?
完整代码
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>zip reader</title> </head> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css" /> <script type="text/javascript" charset="utf8" src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.3/jstree.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js"></script> <body> <h3>Choose the local(s) zip file(s)</h3> <input type="file" id="file" name="file" multiple /><br /> <div id="result_block" class="hidden"> <h3>Content :</h3> <div id="result"></div> </div> </body> <script src="jszip.min.js"></script> <script src="jszip-utils.min.js"></script> <script src="app1.js"></script> <script src="FileSaver.min.js"></script> </html>
app1.js
var array = [] var contents = [] var $result = $("#result"); $("#file").on("change", function(evt) { // 清空内容 $result.html(""); // 显示结果区块 $("#result_block").removeClass("hidden").addClass("show"); // 处理单个文件的闭包函数 function handleFile(f) { var $title = $("<h4>", { text : f.name }); var $fileContent = $("<ul>"); $result.append($title); $result.append($fileContent); var dateBefore = new Date(); JSZip.loadAsync(f) // 异步读取Blob文件 .then(function(zip) { var dateAfter = new Date(); $title.append($("<span>", { "class": "small", text:" (loaded in " + (dateAfter - dateBefore) + "ms)" })); zip.forEach(function (relativePath, zipEntry) { var y = zipEntry.name array.push(y); $fileContent.append($("<li>", { text : zipEntry.name })); }); }, function (e) { $result.append($("<div>", { "class" : "alert alert-danger", text : "Error reading " + f.name + ": " + e.message })); }); } var files = evt.target.files; for (var i = 0; i < files.length; i++) { handleFile(files[i]); } console.log(array[0]) });
问题解答
1. 为什么console.log(array[0])返回undefined
核心是异步代码的执行顺序问题:
JSZip.loadAsync(f)是异步方法,它会在后台加载解析Zip文件,不会阻塞后续代码运行。- 当循环结束后执行
console.log(array[0])时,JSZip.loadAsync的then回调还未触发,array.push(y)根本没执行过,此时array是空数组,array[0]自然为undefined。 - 而当你在控制台手动展开
console.log(array)的输出时,浏览器已经完成了Zip文件解析,then回调已执行并向数组插入了元素,所以能看到内容。
2. 控制台蓝色提示的含义
提示翻译为:此值是在首次展开时计算的,此后该值可能已发生变化
- 浏览器控制台对于数组、对象这类引用类型,不会在调用
console.log时立即打印所有内容,而是保存一个指向该对象的引用。 - 当你手动展开数组时,浏览器才会读取它当前的实际内容。如果在
console.log执行之后,数组被异步代码修改,就会出现这个提示,说明你看到的内容和console.log执行时的原始内容不一致。
内容的提问来源于stack exchange,提问作者gaurav joshi
相关产品推荐
相关产品推荐

