JavaScript的值与类型
来源:互联网 发布:微屏软件 排行 编辑:程序博客网 时间:2024/05/19 12:27
本文主要来自GitHub中作者开放的文档
在此书之前第一章中已经提到过,JavaScript中的值有类型之分,而变量是不存在类型的,目前JavaScript拥有如下几种类型,区分null和undefined的话总共7种类型。
- string
- number
- boolean
- null and undefined
- object
- symbol (new to ES6)
如果你不知到某个值的类型,JavaScript里提供了一个名字为typeof的函数,用这个函数可以检测你的值的类型。
var a;typeof a;// "undefined"a = "hello world";typeof a;// "string"a = 42;typeof a;// "number"a = true;typeof a;// "boolean"a = null;typeof a;// "object" -- weird, buga = undefined;typeof a;// "undefined"a = { b: "c" };typeof a;// "object"
注意上面的6种类型返回的都是string类型的字符串(如果算上es6的"symbol"类型,就是7种),如typeof "abc"返回的是"string",而不是string。
同时可以看到上面只定义了一个变量,仅是在不同时刻赋予的值是不同的,我们这里使用的typeof a其实际意义上并不是指type of a,而是type of the value current in a,是指值的类型而非变量,JavaScript中只有值拥有类型,而变量只是这些具体值的一个容器。
这其中有一个值的类型比较有趣,那就是typeof null,因为如果你测试一下的话,就会发现她返回的竟然是一个"object",而你希望她应该正确的返回一个"null",注意,这是一个由来已久的JavaScript bug,由于现在很多web项目中使用了这个bug,所以不可能再去修复,否则会引发更多的问题.
假如你定义 a = undefined,再定义 var a,当你使用typeof输出a时,会发现其实都是"undefined",这说明这两种操作可以等同看待,类似这种返回"undefined"的操作还有一些,如将一个没有返回值的函数(即void类型)赋值给a,其返回的也会是一个"undefined"。
function fun(){ }var a = fun();typeof a; // "undefined"
下面我们就来仔细看一下
1. "object"
首先她是一个复合值,简单说就是她可以包含各种类型的值,也是我们最常用的一个类型。
var obj = {a: "hello world",b: 42,c: true};obj.a;// "hello world"obj.b;// 42obj.c;// trueobj["a"];// "hello world"obj["b"];// 42obj["c"];// true
注意上面两种获取值的方式,一般优先选择第一种使用点号获取的方式(主要是由于其简短易读的特点)。但是某些情况下,例如以property/key形式定义的值,一般会使用后者获取,如
var obj = {a: "hello world",b: 42};var b = "a";obj[b];// "hello world"obj["b"];// 42
类似地,还有一些常用的类型,如数组array和函数function,这些类型不是内置类型(build-in type),但可以想象成object的子类型。其中数组不是以property/key形式定义的,而是以数字作为下标按一定顺序排列的,以下标0作为起点,如
var arr = ["hello world",42,true];arr[0];// "hello world"arr[1];// 42arr[2];// truearr.length;// 3typeof arr;// "object"建议在使用数字定位的值(numerically positioned values)时定义成数组的形式,而在使用具体名字获取值(property/key形式,named properties)时定义成object类型。
function也是object的一个子类型,如下
function foo() {return 42;}foo.bar = "hello world";typeof foo;// "function"typeof foo();// "number"typeof foo.bar;// "string"注意,通常只是在真正需要时才会调用函数function里的值(如上面定义的foo.bar这种取值方式)。
2. 内置类型的方法
在JavaScript中,如果你定义的数据类型是内置类型,那么你可以使用其自带的方法去做一些操作。如字符串的大小写转换,长度大小的获取等。
var a = "hello world";var b = 3.14159;a.length;// 11a.toUpperCase();// "HELLO WORLD"b.toFixed(4);// "3.1416"一个字符串值可以被一个String对象包装,一个数字可以被一个Number对象包装,并且一个布尔值可以被一个Boolean对象包装。大多数情况下,你不必担心或直接使用这些值的对象包装形式,基本上我们都是在使用原始数据类型,而不必理会其自身的拆箱和装箱操作。
3. 值的比较
(1)强制转换:分为显式和隐式两种,显式转换可以简单地从代码中判断,而隐式的类型转换相对比较隐蔽,可能存在一些不够明显的副作用(或不好的行为)。我们通常会认为强制做类型转换是很邪恶的一种行为,这是因为强制类型转换可能会存在一些出人意料的结果,但事实上,当我们使用强制转换时,很多时候场景是相对合理的,容易被人理解的,甚至可以提高代码的可读性。
显式转换:
var a = "42";var b = Number( a );a;// "42"b;隐式转换:
var a = "42";var b = a * 1;// "42" implicitly coerced to 42 herea;// "42"b;// 42 -- the number!
(2)布尔值判断(Truthy & Falsy):当非布尔值被强制转为布尔值时,它是真还是假?下面列一下默认的一些情况。在实际使用中,如果你的ajax返回的数据类型比较复杂,那就要小心了。
默认为falsy的情况:
- "" (empty string)
- 0, -0, NaN (invalid number)
- null, undefined
- false
默认为truthy的情况:
- "hello"
- 42
- true
- [ ], [ 1, "2", 3 ] (arrays)
- { }, { a: 42 } (objects)
- function foo() { .. } (functions)
举个例子说明一下
var t = "";if (t){ console.info("1");}else{ console.info("2"); //输出2}可以看到默认空字符串做布尔转换时,其实就是false。
(3)相等判断:这个是一个比较常见的问题,一般使用==判断是不做类型区别的,而===会首先判断你的数据类型是否一致,如
var a = "42";var b = 42;a == b;// truea === b;// false所以:
- 如果比较中的任何一个值(aka side)可以是真或假值,则避免==并使用===。
- 如果比较中的任一值可能是这些特定值(0,“”或[] - 空数组),请避免==并使用===。
- 在所有其他情况下,可以安全地使用==。这不仅是安全的,而且在很多情况下它可以简化代码,提高可读性。
想要具体了解的话可以阅读es5官方文档的11.9.3章节。
另外,在做数组判断时,可能会遇到下面这种情况。至于原因是什么,可以参考es5的官方文档。
var a = [1,2,3];var b = [1,2,3];var c = "1,2,3";a == c;// trueb == c;// truea == b;// false
(4)不等式判断:通常我们认为做不等判别的知识number类型,然而在JavaScript中,string类型值同样可以,string类型的判断使用的是字母排列规则,如b<f,a<b
console.info("bar" < "foo"); //输出true
console.info("24" < "21"); //输出false当然,你也可以将number和string做比较,如
var a = 41;var b = "42";var c = "43";a < b;// trueb < c;// true然而,有时我们会遇到比较奇葩的判断,致使两边的数据类型“严格不想等”(strict inequality),如
var a = 42;var b = "foo";a < b;// falsea > b;// falsea == b;// false此时,上面的b会判定为"invalid number value" ,即NaN,在es5文档上讲:NaN既不大于也不小于任何其他值。所以都是false。
阅读全文