JavaScript 中的一些奇怪问题
JavaScript 中的一些奇怪问题
JavaScript 在开发过程中可能会出现很多奇怪的问题,以下是一些示例:
1、变量提升问题:
变量提升是 JavaScript 中一个常见的问题,特别是当没有充分理解变量作用域和声明提升时。以下是一个变量提升导致的问题示例:
var a = 1;
function foo() {
console.log(a);
var a = 2;
}
foo(); // 输出:undefined
预期输出是 1,但实际上输出的是 undefined。这是因为在函数内部声明了一个同名变量 a,函数作用域内的变量声明被提升到了函数开头,所以 console.log(a)
实际上输出的是 undefined。
解决该问题的方法是使用 let 或 const 关键字声明变量,这样可以避免变量提升和作用域污染:
let a = 1;
function foo() {
console.log(a);
let a = 2;
}
foo(); // 输出:报错 Uncaught ReferenceError: Cannot access 'a' before initialization
2、this 指向问题:
this 关键字在 JavaScript 中非常重要,但也很容易导致问题。this 关键字的指向是动态的,它的值取决于函数的调用方式。以下是一个 this 关键字导致的问题示例:
var name = "John";
var person = {
name: "Bob",
sayName: function () {
console.log("name", this.name);
},
};
var sayName = person.sayName;
sayName();
预期输出是 "Bob",但实际上输出的是 "John"。这是因为在全局作用域中调用 sayName 函数时,this 指向的是全局对象 window,而全局作用域中定义的 name 变量值为 "John"。
解决该问题的方法是使用 call、apply 或 bind 方法来改变 this 的指向:
sayName.call(person);
3、==
和 ===
比较问题:
console.log(false == "0"); // 输出 true
console.log(false === "0"); // 输出 false
在第一行中,"0" 被转换为 false,因此 false == false,结果为 true。在第二行中,使用了严格相等运算符 ===,它不会自动转换类型,因此 false 和 "0" 不相等,结果为 false。
4、循环中的异步问题:
异步操作是 JavaScript 中一个重要的特性,但也容易导致一些问题。以下是一个异步操作导致的问题示例:
for (var i = 0; i < 5; i++) {
setTimeout(function () {
console.log(i);
}, 1000);
}
预期输出是 0、1、2、3、4,但实际上输出的是 5、5、5、5、5。因为 setTimeout 函数是一个异步操作,它会在循环结束后再执行。当 setTimeout 函数被调用时,i 的值已经变成了 5,因此它会输出 5,而不是预期的 0、1、2、3 和 4。为了解决这个问题,可以使用闭包或 let 关键字来解决变量作用域的问题。
通过使用闭包来保存变量的值来解决该问题:
for (var i = 0; i < 5; i++) {
(function (j) {
setTimeout(function () {
console.log(j);
}, 1000);
})(i);
}
// 输出 0、1、2、3、4
5、引用类型比较问题:
在 JavaScript 中,引用类型(如数组和对象)的比较可能导致一些奇怪的问题。以下是一个引用类型比较导致的问题示例:
console.log([] == []); // 输出 false
console.log([] === []); // 输出 false
这是因为 JavaScript 中比较引用类型时,比较的是它们在内存中的地址,而不是它们的内容。因此,两个空数组虽然看起来相同,但它们在内存中的地址不同,因此比较结果为 false。
6、变量命名问题:
不恰当的变量命名可能导致一些问题。以下是一个变量命名导致的问题示例:
var NaN = "not a number";
console.log(NaN); // 输出 NaN
console.log(typeof NaN); // 输出 "number"
因为 NaN 是 JavaScript 中一个关键字,表示 Not a Number,不应该被用作变量名。因为变量名和关键字相同,所以 typeof 操作符返回了 "number",而不是预期的 "string"。
7、数据类型转换问题:
JavaScript 中有很多不同的数据类型,类型转换可能导致一些奇怪的问题。以下是一个数据类型转换导致的问题示例:
console.log(1 + "2" + "2"); // 输出 "122"
console.log(1 + +"2" + "2"); // 输出 "32"
console.log(1 + -"1" + "2"); // 输出 "02"
console.log(+"1" + "1" + "2"); // 输出 "112"
console.log("A" - "B" + "2"); // 输出 "NaN2"
console.log("A" - "B" + 2); // 输出 NaN
这些奇怪的输出都是因为类型转换造成的,例如在第一行中,数字 1 和字符串 "2" 相加,得到字符串 "12",然后再和字符串 "2" 相加,得到字符串 "122"。
8、NaN 的比较问题
NaN 是一种特殊的数值,表示 "Not a Number"。在 JavaScript 中,NaN 与任何值都不相等,包括它自己。以下是一个 NaN 比较导致的问题示例:
console.log(NaN == NaN); // 输出 false
console.log(NaN === NaN); // 输出 false
解决该问题的方法是使用全局函数 isNaN() 来判断一个值是否为 NaN:
console.log(isNaN(NaN)); // 输出 true
9、0.1 + 0.2 不等于 0.3 问题
在 JavaScript 中,使用浮点数进行计算时,可能会出现精度问题。例如,0.1 + 0.2 的结果并不是 0.3。以下是一个精度问题导致的问题示例:
console.log(0.1 + 0.2 == 0.3); // 输出 false
解决该问题的方法是将浮点数转换为整数进行计算,最后再将结果除以 10。或者使用 Number.EPSILON 来比较两个浮点数是否相等:
console.log(Math.abs(0.1 + 0.2 - 0.3) < Number.EPSILON); // 输出 true
参考:JavaScript 中 0.1+0.2 不等于 0.3 的问题
JavaScript 中的一些奇怪问题的更多相关文章
- JavaScript中的"奇奇怪怪"
filter等方法的隐式转化 var list = [1,,2,,0,5,9];console.log(list[1]); // console: undefinedconsole.log(list[ ...
- JavaScript 中的数据类型
Javascript中的数据类型有以下几种情况: 基本类型:string,number,boolean 特殊类型:undefined,null 引用类型:Object,Function,Date,Ar ...
- JavaScript中的this陷阱的最全收集
JavaScript来自一门健全的语言,所以你可能觉得JavaScript中的this和其他面向对象的语言如java的this一样,是指存储在实例属性中的值.事实并非如此,在JavaScript中,最 ...
- JavaScript中的this陷阱的最全收集 没有之一
当有人问起你JavaScript有什么特点的时候,你可能立马就想到了单线程.事件驱动.面向对象等一堆词语,但是如果真的让你解释一下这些概 念,可能真解释不清楚.有句话这么说:如果你不能向一个6岁小孩解 ...
- JavaScript中的apply和call函数详解(转)
每个JavaScript函数都会有很多附属的(attached)方法,包括toString().call()以及apply().听起来,你是否会感到奇怪,一个函数可能会有属于它自己的方法,但是记住,J ...
- 深入理解Javascript中this, prototype, constructor
在Javascript面向对象编程中经常需要使用到this,prototype和constructor这3个关键字. 1.首先介绍一下this的使用:this表示当前对象;如果在全局中使用this,则 ...
- javascript中的链表结构—从链表中删除元素
1.概念 上一个博文我们讲到链表,其中有一个方法remove()是暂时注释的,这个方法有点复杂,需要添加一个Previous()方法找到要删除的元素的前一个节点,这一个博文我们来分析一下这个remov ...
- 深入理解JavaScript中创建对象模式的演变(原型)
深入理解JavaScript中创建对象模式的演变(原型) 创建对象的模式多种多样,但是各种模式又有怎样的利弊呢?有没有一种最为完美的模式呢?下面我将就以下几个方面来分析创建对象的几种模式: Objec ...
- JavaScript中Eval()函数的作用
这一周感觉没什么写的,不过在研究dwz源码的时候有一个eval()的方法不是很了解,分享出来一起学习 -->首先来个最简单的理解 eval可以将字符串生成语句执行,和SQL的exec()类似. ...
- 转:JavaScript中的this陷阱的最全收集
在其他地方看到的,觉得解释的狠详细,特此分享 当有人问起你JavaScript有什么特点的时候,你可能立马就想到了单线程.事件驱动.面向对象等一堆词语,但是如果真的让你解释一下这些概念,可能真解释不清 ...
随机推荐
- 一步步带你设计MySQL索引数据结构
前言 MySQL的索引是一个非常重要的知识点,也基本上是面试必考的一个技术点,所以非常重要.那你了解MySQL索引的数据结构是怎么样的吗?为什么要采用这样的数据结构? 现在化身为MySQL的架构师,一 ...
- elasticsearch倒排索引(全面了解)
SimpleAI推荐语: 前年转过这篇文章,最近在看检索相关论文,发现又有点忘记倒排索引(inverted index)的具体内容,遂翻出来再看看,不得不说,这个漫画画的太好了,娓娓道来,一看就懂,再 ...
- vue 组件之间传值(父传子,子传父)
1.父传子 基本就用一个方式,props Father.vue(用v-bind(简写 : ) 将父组件传的值绑定到子组件上) <template> <div> 我是爸爸:{{ ...
- @LoadBalanced注解原理
在使用springcloud ribbon客户端负载均衡的时候,可以给RestTemplate bean 加一个@LoadBalanced注解,就能让这个RestTemplate在请求时拥有客户端负载 ...
- 基于Spark的均值漂移算法在网络舆情聚类中的应用
知网链接 原文链接 张京坤, 王怡怡 软件导刊 2020年19卷第9期 页码:190-195 DOI:10.11907/rjdk.192529 出版日期:2020-9-15 摘 要: 为了改善网 ...
- IT编程相关内容汇总 - 进阶者系列 - 学习者系列文章
笔者工作了十多年了,对于技术也有一定的经验,但是IT编程技术的更新是挺快的,特别是各种框架,各种中间件啥的都涌现出来了.这篇博文笔者打算将IT编程的前端.后端.数据库和移动端做一个博文知识汇总,让阅读 ...
- Blazor WebAssembly的初次访问慢的优化
Blazor WebAssembly初次访问需要加载很多dll,体积较大,因此第一次加载比较慢. 针对此问题Microsoft提供了优化方案:压缩 https://learn.microsoft.co ...
- OpenMP 环境变量使用总结
OpenMP 环境变量使用总结 OMP_CANCELLATION,在 OpenMP 规范 4.5 当中规定了取消机制,我们可以使用这个环境变量去设置是否启动取消机制,如果这个值等于 TRUE 那么就是 ...
- Java基础学习笔记-类的静态属性和静态方法--待继续补充
程序运行时的内存占用 代码区(code area) 存放代码 数据区(data area) 存放全局数据.静态数据 堆区(heap area) 存放动态申请的数据 栈区(stack area) 存放局 ...
- 动力节点—day06
常用类 String String表示字符串类型,属于引用数据类型,不属于基本数据类型 在Java中随便使用双引号括起来的都是String对象,例如"abc"."def& ...