JavaScript是一种非常灵活的现代编程语言,灵活到使用者极其容易被忽视的它那广阔的世界以及它带给我们的无限遐想空间。本文将对JavaScript最最基础也最容易被忽视的数据类型问题和类型转换问题进行探索。
数据类型
众所周知,JavaScript有8种内置数据类型:string,number,boolean,object,null,undefined,function,symbol(来自ES规范)。
除了object外,我们通常称其他类型为基本类型(typeof null 的运算结果是'object',有些人认为这是个由来已久的‘bug’)。基本类型可以想对象一样产生直接调用类型方法(如果有的话),如4.toFixed,'hello'.split('l')等。
typeof 运算符总是会返回一个字符串
typeof sd;//"undefined"
var a = 3;
typeof a; // "number"
a = true;
typeof a; // "boolean"
typeof typeof 42; // "string"
typeof function a(){ /* .. */ } // "function"
typeof {a:12,b:2};//"object"
typeof [121,2324];//"object"
typeof null ;//"object"
利用typeof 运算符安全的检查变量是否定义
//检查变量
// 这样会抛出错误ReferenceError
if (testObject) {
console.log( "defined" );
}
// 这样是安全的
if (typeof DEBUG !== "undefined") {
console.log( "defined" );
}
类型转换
类型转换(type casting)指的是将值从一种类型转换为另一种类型。显示的调用转换过程称为显式强制类型转换,隐
式的情况称为隐式强制类型转换(coercion)。但是坦白说,你知道,就是显示,你不知道,便是隐式。
显示类型转换
显式强制类型转换旨在让代码更加清晰易读
//这里为什么多了个'.'?不加点(12.toString())js会认为12.是一个数字整体,故而报语法错误(SyntaxError)
12..toString();//"12"
var num = 120;//"120"
Number('012');//12
parseInt('012.3asd88')//12;注意,parseInt返回Str[0]开始的有效数字字符组成的数字
parseFloat('012.3asd88')//12.3;
Boolean(10);//true
Boolean(new Boolean);//true;注意哦,这里会返回true
隐式类型转换
这是一种简化的语法,编译器为了我们方便(可能吧),在这方面帮我们做了很多事。
隐式强制类型转换是隐蔽的强制类型转换,而你自己觉得不够明显的强制类型转换都可以算作隐式强制类型转换。隐式强制类型转换让代码变得晦涩难懂而又‘便捷而奇妙’。
+new Date();//1564536588540;== new Date().valueOf();
'12' + 1;//"121"
false - 1;//-1
false - '1';//-1
false + '1';//"false1"
[1,2,3] + '';//"1,2,3"
if(0 /*false*/){}
if([] /*true*/){}
让人困惑的求等:==和===(宽松相等和严格相等)详解
JavaScript 中,判断两个值是否“相等”可以用宽松相等(loose equals) == 和严格相等(strict equals) === 。但是在判断条件上它们有一个很重要的区别。 不少人认为“ == 检查值是否相等, === 检查值和类型是否相等”。然而还不够准确。很多 JavaScript 的书籍和博客也是这样来解释 的,但是很遗憾他们都错了。 事实上,== 允许在比较中进行强制类型转换,而 === 不允许。 这几个情况需要注意:
• null == 0;//false;null 除了null 和undefined,与null或undefined执行==都会得false
• [] == ![];//true;意外吧!
• false == []; // true
• "" == 0; // true
• "" == []; // true
• 0 == []; // true
• NaN === NaN;//false;NaN不等于NaN,不论严不严格
• +0 === -0; //true;
• "0" == false; // true
• 42 == "43"; // false
• "foo" == 42; // false
• "true" == true; // false
• 42 == "42"; // true
• "foo" == [ "foo" ]; // true
根据ECMA规范,模糊相等计算‘==’一般是以下四种情况或者其组合:
var a = *;
var b = *;
a === b;
a == b;
- 字符串和数字之间的相等比较
ES5 规范 11.9.3.4-5 这样定义:
(1) 如果 Type(x) 是数字, Type(y) 是字符串,则返回 x == ToNumber(y)
的结果。
(2) 如果 Type(x) 是字符串, Type(y) 是数字,则返回 ToNumber(x) == y
的结果。 - 其他类型和布尔类型之间的相等比较
ES5 规范 11.9.3.6-7 :
(1) 如果 Type(x) 是布尔类型,则返回 ToNumber(x) == y 的结果;
(2) 如果 Type(y) 是布尔类型,则返回 x == ToNumber(y) 的结果。 - null 和 undefined 之间的相等比较
ES5 规范 11.9.3.2-3 :
(1) 如果 x 为 null , y 为 undefined ,则结果为 true 。
(2) 如果 x 为 undefined , y 为 null ,则结果为 true 。 - 对象和非对象之间的相等比较
ES5 规范 11.9.3.8-9 :
(1) 如果 Type(x) 是字符串或数字, Type(y) 是对象,则返回 x == ToPrimitive(y)的结果;
(2) 如果 Type(x) 是对象, Type(y) 是字符串或数字,则返回 ToPromitive(x) == y的结果。
抽象操作 ToPrimitive (参见 ES5 规范 9.1 节)是为了求对象的‘值’,它首先(通过内部操作 DefaultValue ,参见 ES5 规范 8.12.8 节)检查该值是否有 valueOf() 方法。
如果有并且返回基本类型值,就使用该值进行强制类型转换。如果没有就使用 toString()的返回值(如果存在)来进行强制类型转换。
如果 valueOf() 和 toString() 均不返回基本类型值,会产生 TypeError 错误。
注意,对 == 两边的值认真推敲,为了避开不必要的错误,我们可以遵循两个原则。
• 如果两边的值中有 true 或者 false ,千万不要使用 == 。
• 如果两边的值中有 [] 、 "" 或者 0 ,尽量不要使用 == 。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。