console.log(text)打印不出来的值,用console.log(text.length)却打印出来长度为1?

本文深入探讨了一个常见的JavaScript编程陷阱,即使用console.log显示的字符串长度与实际length属性值不符的问题。通过逐步排查,揭示了innerText属性在处理空内容时自动添加制表符的特性,并提供了相应的解决方案。

一、背景

      好久没写博客了,最近时间实在是紧的不行,忙中偷闲记录一个小问题先。大概描述就是像题目中说的那样,用console.log打印结果和实际的length不同,以为是遇到鬼了,实际呢,我还是太年轻。
如图:
在这里插入图片描述

二、找问题过程

1、 使用typeof看看 发现类型都是string的

2、console.log(JSON.stringify(text)); 发现加了个\t制表符,我们知道,console.log(JSON.stringify(text))有个参数space ,指定缩进用的空白字符串,用于美化输出(pretty-print);如果参数是个数字,它代表有多少的空格;上限为10。该值若小于1,则意味着没有空格;如果该参数为字符串(字符串的前十个字母),该字符串将被作为空格;如果该参数没有提供(或者为null)将没有空格。 (https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify)
在这里插入图片描述

3、 打印 console.log(text === "" ); 发现都是false,也就是说并不是空字符串

4、 打印 console.log(text === "\t" ); 发现打印的结果是true,也就是说此时的text是一个空格

5、 发现空格之后,打印console.log(trim(sourceText).length); 去掉空格,打印出的结果正常了,长度为0的空字符串

问题所在:
代码中有一句, var text = b.innerText; (b是td元素节点,这部分是获取td里面的内容)

      由于其中一个td里面是一个img标签,所以用innertext()获取到的是不含html的内容。用<span></span>测试一下,
发现获取到的还是一个空格,那么可以大致总结下,用innertext()获取td标签的值的话,无论是否获取到结果,后面
都会自动加个空格(\t),就是不清楚这个空格到底是innertext()获取不到值自己解析的,还是td自带的有一个空格?

6、 如果要对innertext()赋值之后的变量进行测试的话,那尽量去掉它的空格,或者把(\t)考虑进去。
JS去除空格参考: https://www.cnblogs.com/bafeiyu/archive/2012/12/13/2816546.html

总结:
      这次问题的出现,整体来说还是对于使用变量不够严谨引起的。在使用变量的时候,如果是int类型,建议类似于php的intval()一样,格式化一下。如果是string类型的话,最起码也要去除下空格。把这些当做习惯,那在开发中肯定会省下很多不必要的小bug。

end

你遇到的是一个 **典型的 Vue 响应式系统 + 异步加载 + 控制台延迟求** 导致的“看似矛盾”的现象。 --- ## ✅ 问题描述 ```js console.log(dictList.value) // 打开后看到有数据,包含 aigc_file_type: Array(4) console.log(dictList.value.aigc_file_type) // 却打印出 [] (空数组) ``` 看起来矛盾:**同一个对象,展开看有数据,直接访问却没有?** 这其实是 JavaScript 控制台的“**惰性求(lazy evaluation)”机制**在作祟。 --- ## 🔍 根本原因分析 ### 🕒 场景还原: 1. `useDict(&#39;aigc_file_type&#39;)` 是异步请求字典数据。 2. 你在 `setup` 或 `onMounted` 中写了两个 `console.log`: ```ts console.log(dictList.value) console.log(dictList.value.aigc_file_type) ``` 3. 这两行代码执行时,**字典数据尚未返回** → 此刻 `dictList.value.aigc_file_type` 确实是 `[]` 4. 但几毫秒后,API 返回了,Vue 更新了 `dictList` 5. 当你打开浏览器控制台查看第一个 `console.log(dictList.value)` 时,它显示的是 **当前最新**(已更新),而打印那一刻的快照! > 💥 关键点:`console.log(obj)` 输出的是一个 **实时引用(live reference)** > > 而 `console.log(obj.prop)` 打印的是那一刻的 **静态快照** --- ## ✅ 示例说明 ```ts let obj = { list: [] } console.log(obj) // 🟡 显示 { list: [...] } console.log(obj.list) // 🔴 显示 [] // 模拟异步更新 setTimeout(() => { obj.list.push(1, 2, 3) }, 100) ``` - 你在 0ms 打印 `obj` 和 `obj.list` - 在 200ms 你打开控制台 - 结果: - `obj` 展开后看到 `list: [1,2,3]` → 因为它是 live object - `obj.list` 显示 `[]` → 因为它是那一刻的(快照) 👉 它们一致是正常的! --- ## ✅ 验证方法:强制深拷贝输出真实快照 ### 方法 1:使用 `JSON.parse(JSON.stringify(...))` ```ts console.log(&#39;dictList.value 快照:&#39;, JSON.parse(JSON.stringify(dictList.value))) console.log(&#39;aigc_file_type 快照:&#39;, JSON.parse(JSON.stringify(dictList.value.aigc_file_type))) ``` 结果会一致:都显示 `[]`(如果调用时还未加载完成) --- ### 方法 2:加 `setTimeout` 等待加载完成 ```ts setTimeout(() => { console.log(&#39;延迟查看 dictList.value:&#39;, dictList.value) console.log(&#39;延迟查看 aigc_file_type:&#39;, dictList.value.aigc_file_type) }, 1000) ``` 你会发现两者都有数据了。 --- ## ✅ 如何正确监听数据是否加载完成? ### 使用 `watch` 监听变化 ```ts import { watch } from &#39;vue&#39; const { dictList } = useDict(&#39;aigc_file_type&#39;) watch( () => dictList.value.aigc_file_type, (newVal, oldVal) => { console.log(&#39;aigc_file_type 已更新:&#39;, newVal) // 此处可以触发其他逻辑 }, { immediate: true } ) ``` 或者监听长度: ```ts watch( () => dictList.value.aigc_file_type?.length, (len) => { if (len > 0) { console.log(&#39;✅ 字典数据已加载完成,共&#39;, len, &#39;项&#39;) } } ) ``` --- ## ✅ 解决你的 `<el-option>` 显示问题 你现在写的是: ```ts const aigcFilesType = dictList.value[&#39;aigc_file_type&#39;] ``` ⚠️ 错!这是在 setup 阶段执行的一次性赋,当时还是空数组 → 后面会更新! ### ✅ 正确做法:用 `computed` ```ts import { computed } from &#39;vue&#39; const aigcFilesType = computed(() => { return dictList.value[&#39;aigc_file_type&#39;] || [] }) ``` 这样模板中使用 `v-for="dict in aigcFilesType"` 才能动态响应更新。 --- ## ✅ 最终推荐代码 ```vue <script setup lang="ts"> import { computed } from &#39;vue&#39; import { useDict } from &#39;@/utils/dictUtils&#39; // 加载字典(异步) const { dictList } = useDict(&#39;aigc_file_type&#39;) // ✅ 响应式计算属性 const aigcFilesType = computed(() => dictList.value[&#39;aigc_file_type&#39;] || []) // 调试:验证是否正确响应 watch( () => aigcFilesType.value, (val) => console.log(&#39;【实时】aigcFilesType:&#39;, val) ) </script> <template> <el-form-item label="文件类型"> <el-select v-model="query.params.fileType" placeholder="Select ..." clearable style="width: 200px" :disabled="!aigcFilesType.length" > <el-option v-for="dict in aigcFilesType" :key="dict.value" :label="dict.label" :value="dict.value" /> </el-select> </el-form-item> </template> ``` --- ## ✅ 总结对比 | 写法 | 是否响应式 | 是否推荐 | |------|------------|----------| | `const x = dictList.value.key` | ❌ 响应 | ⛔ 要这样做 | | `computed(() => dictList.value.key)` | ✅ 响应式 | ✅ 推荐 | | 模板中直接写 `dictList.value.key` | ✅ 自动追踪 | ✅ 可接受 | | `console.log(obj)` vs `console.log(obj.prop)` | 行为同正常 | 注意调试方式 | --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

铁柱同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值