符号(symbol)常作唯一标识,属于es6(ECMAScript2015)新增内容
除
对象类型 object
之外其他的都是基本类型
注意:上述’七种类型’使用类型检测运算符
typeof
得到的结果却不一定是他们本身~
观察以下代码:
typeof undefined === 'undefined' // true
typeof 123 === 'number' // true
typeof '123' === 'string' // true
...
typeof null === 'null' // false
typeof null === 'object' // true
正常来讲 typeof 可以正确获取类型。但是 null 无法获取到 null
,而是 'object'
。这是 JavaScript 的一个 bug,可能以后也不会修复了…
你们会发现,JavaScript 中的变量是没有类型的,不能使用 String str = ‘123’ 来定义一个变量。在 js 中,只有值存在类型,对于一个变量,可以拥有任何类型。所以上述的 typeof 测试的并不是变量是什么类型,而是测试变量所拥有的值。
1.3.1 undefined 和 undeclared
变量在无值时为 undefined,变量不存在时(在作用域未声明)为 undeclared
观察以下代码:
var hhh = 'a'
var xixixi
typeof hhh === 'string' // true
hhh // 'a'
typeof xixixi = 'undefined' // true
xixixi // undefined
typeof hahaha === 'undefined' // true
hahaha // ReferenceError: hahaha is not defined
注意:undeclared 在浏览器里输出为 ReferenceError: xx is not defined,容易误解为 undefined,实际上应该输出为 xx is not found 或者 xx is not declared,同时 typeof 处理 undeclared 是输出 ‘undefined’ 的,这是不合理的,期待输出’undeclared’。
和其他强类型语言不同,在 JavaScript 中,数组可以容纳任何类型的值,可以是字符串、数字、对象(object),甚至是其他数组(多维数组就是通过这种方式来实现的)
var a = [ 1, "2", [3] ];
a.length; // 3
a[0] === 1; // true
a[2][0] === 3; // true
给数组设定值的时候无需预先设置大小,可以使用字面量的形式申明一个数组
var arr = []
arr[0] = 0
arr[2] = 2
arr[1] // undefined
arr.length = 3 // 虽然 arr[1] 为定义,但是数组长度 = 最大索引 - 1
a[1] 的值为 undefined,但这与将其显式赋值为 undefined(a[1] = undefined)还是有所区别
使用 delete 运算符可以将元素从数组中删除,但是删除后,数组的 length 属性并不会发生变化。
如果字符串键值能够被强制类型转换为十进制数字的话,它就会被当作数字索引来处理。
在数组中加入 字符串键值 / 属性
并不是非常推荐。
var a = [ ];
a["13"] = 42;
a.length; // 14
类数组
类数组对象:是指在 JavaScript 中有一些对象可能并不是真正的数组,但它们可以表现得跟数组一样。比如说 arguments 对象或者 jQuery 选择元素集合等。它们可以通过 index 来访问元素,并且有 length 属性,但是缺少数组所拥有的其他方法,例如 push, pop,slice 等。
常见的类数组对象有:
类数组到数组的转换方法有:
Array.prototype.slice.call()
使用Array.prototype.slice.call()方法能将具有length属性的对象转成数组。
var arrayLike = {0: 'name', 1: 'age', 2: 'sex', length: 3 }
var arr = Array.prototype.slice.call(arrayLike); // ['name', 'age', 'sex']
let arrayLike = {0: 'name', 1: 'age', 2: 'sex', length: 3 };
let arr = Array.from(arrayLike); // ["name", "age", "sex"]
let arrayLike = {0: 'name', 1: 'age', 2: 'sex', length: 3 }
let arr = [...arrayLike]; // ["name", "age", "sex"]
如果类数组没有 length 属性或者成员不是按照顺序排序的,上述方法可能不能很好的进行转换。在这种情况下,可能需要借助其他方法,例如添加元素到空数组中。
var array = Array.prototype.concat.apply([], arguments);
字符串和数组其实是有的类似的。
var a = "foo";
var b = ["f","o","o"];
它们都是类数组,都有 length 属性以及 indexOf(…)(从 ES5开始数组支持此方法)和 concat(…) 方法
JavaScript 中字符串是不可变的,而数组是可变的。并且 a[1] 在 JavaScript 中并非总是合法语法,在老版本的 IE 中就不被允许(现在可以了)。正确的方法应该是 a.charAt(1)。
字符串不可变是指字符串的成员函数不会改变其原始值,而是创建并返回一个新的字符串。而数组的成员函数都是在其原始值上进行操作。
示例:
字符串无法使用 Array.prototype.reverse()(因为它是不可变更的)
解决方案:
var str = '123'
var newStr = str
// 将a的值转换为字符数组
.split( "" )
// 将数组中的字符进行倒转
.reverse()
// 将数组中的字符拼接回字符串
.join( "" );
newStr; // '321'
JavaScript 只有一种数值类型:number(数字),包括“整数”和带小数的十进制数。此处“整数”之所以加引号是因为和其他语言不同,JavaScript 没有真正意义上的整数,这也是js的‘特性’。
2.3.1 语法
toExponential()
函数的输出结果相同。var a = 5E10;
a; // 50000000000
a.toExponential(); // "5e+10"
var b = a * a;
b; // 2.5e+21
var c = 1 / a;
c; // 2e-11
tofixed(..)
方法可指定小数部分的显示位数var a = 42.59;
a.toFixed( 0 ); // "43"
a.toFixed( 1 ); // "42.6"
a.toFixed( 2 ); // "42.59"
a.toFixed( 3 ); // "42.590"
a.toFixed( 4 ); // "42.5900"
toPrecision(..)
方法用来指定有效数位的显示位数var a = 42.59;
a.toPrecision( 1 ); // "4e+1"
a.toPrecision( 2 ); // "43"
a.toPrecision( 3 ); // "42.6"
a.toPrecision( 4 ); // "42.59"
a.toPrecision( 5 ); // "42.590"
a.toPrecision( 6 ); // "42.5900"
.
运算法是有效的数字字符,会被优先识别为数字常量的一部分,然后才是对象的属性访问运算符42.toFixed( 3 ); // SyntaxError
(42).toFixed( 3 ); // "42.000"
0.42.toFixed( 3 ); // "0.420"
42..toFixed( 3 ); // "42.000"
42 .toFixed(3); // "42.000" 不建议使用
0xf3; // 243的十六进制
0Xf3; // 同上
0363; // 243的八进制
// es6 支持以下的格式
0o363; // 243的八进制
0O363; // 同上
0b11110011; // 243的二进制
0B11110011; // 同
2.3.2 数值边缘与机器精度(machine epsilon)
看以下代码:
它们相加的结果并非刚好等于0.3,而是一个比较接近的数字 0.30000000000000004,所以条件判断结果为 false
0.1 + 0.2 === 0.3; // false
以上结果是 JavaScript 无法完全精确呈现数字导致的~
那么怎么判断 0.1 + 0.2 和 0.3 是否相等呢?
最常见的方法是设置一个误差范围值,通常称为“机器精度”(machine epsilon),对JavaScript 的数字来说,这个值通常是 2^-52 (2.220446049250313e-16)
。
从 ES6 开始,该值定义在 Number.EPSILON
中,我们可以直接拿来用,也可以为 ES6 之前的版本写 polyfill:
if (!Number.EPSILON) {
Number.EPSILON = Math.pow(2,-52);
}
可以使用 Number.EPSILON 来比较两个数字是否相等(在指定的误差范围内):
function numbersCloseEnoughToEqual(n1,n2) {
return Math.abs( n1 - n2 ) < Number.EPSILON; // Math.abs 取绝对值
}
var a = 0.1 + 0.2;
var b = 0.3;
numbersCloseEnoughToEqual( a, b ); // true
numbersCloseEnoughToEqual( 0.0000001, 0.0000002 ); // false
2.3.3 检测整数
if (!Number.isInteger) {
Number.isInteger = function(num) {
return typeof num == "number" && num % 1 == 0;
};
}