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有什么特点的时候,你可能立马就想到了单线程.事件驱动.面向对象等一堆词语,但是如果真的让你解释一下这些概念,可能真解释不清 ...
随机推荐
- 2021-01-26HDOJ_Lowest_Bit
挺水的,但也学到了简单方法 题目如下: Lowest Bit Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (J ...
- Vue快速上门(3)-组件与复用
VUE家族系列: Vue快速上门(1)-基础知识 Vue快速上门(2)-模板语法 Vue快速上门(3)-组件与复用 01.component组件 1.1.component基础知识 组件是可以复用的V ...
- 解决.net Core中WebApi自动Model验证导致数据格式不能统一
简言: 最近做项目用WebAPI Core时,想把返回数据的格式,统一弄成:{"errorMsg":"xxx","Data":"x ...
- C#从实习到搬砖
日常唠唠 没事就聊聊我在c#上踩过的那些坑,和一些笔记 少点比较,多些谦虚 会者不难 原博:轩先生大冒险 2022.4.19 datagridview 修改表头 dataGridView1.Colum ...
- SQLMap自带绕过脚本tamper的讲解
sqlmap在默认情况下除了使用CHAR()函数防止出现单引号,没有对注入的数据进行修改,还可以使用--tamper参数对数据做修改来绕过WAF等设备,其中大部分脚本主要用正则模块替代攻击载荷字符 ...
- 3、数组、集合、Lambda、Stream与Optional类
一.数组: 数组保存在JVM堆内存中 1.数组的创建: (1).一维数组创建方式一: //一维数组方式一 Integer[] array01 = {1,2,3}; System.out.println ...
- [python] 基于matplotlib实现雷达图的绘制
雷达图(也称为蜘蛛图或星形图)是一种可视化视图,用于使用一致的比例尺显示三个或更多维度上的多元数据.并非每个人都是雷达图的忠实拥护者,但我认为雷达图能够以视觉上吸引人的方式比较不同类别各个特征的值.本 ...
- ArcObjects SDK开发 一些可直接调用的对话框
在ArcMap中,一些对话框是很复杂的,例如设置点线面样式的对话框,选择空间参考的对话框等,但这些对话框有些在ArcObjects SDK中是可以直接调用的. 1.空间参考选择设置对话框 弹出空间参考 ...
- Git Rebase和Merge的用法
title: Git Rebase和Merge的用法 categories: 后端 tags: - Git Rebase和Merge是什么? merge和rebase的作用都是合并两个分支,其区别在于 ...
- P5690 [CSP-S2019 江西] 日期
简要题意 给你一个格式为 \(\texttt{MM-DD}\) 的日期.你每一次可以更改一个整数,花费 \(1\) 的代价.求将该日期改为一个合法的日期的最小代价.(注:\(2\) 月视为 \(28\ ...