1.数组
var a = [ 1, "2" , [3]];
a.length; //3
a[0] === 1; //true
a[2][0] === 3; //true
创建稀疏矩阵,中间会留有一些空白单元,值为undefined
var a = [ ];
a["13"] = 42;
a.length; //14
从0到12的值都为undefined
类数组
function foo() {
var arr = Array.prototype.slice.call( arguments );
arr.push( "bam" );
console.log( arr );
}
foo( "bar","baz" );
arguments是arr的参数,而slice()返回参数列表的一个数组副本,原来arguments的类数组就被转化为数组,es6中也同样有实现该功能的函数,Array.from()
var arr = Array.from( arguments );
2.字符串
字符串和字符数组都属于类数组,它们在许多方面都特别相似,都有length属性以及indexOf(...)和concat(...)方法
var a = "foo";
var b = ["f","o","o"];
a.length;
b.length;
a.indexOf( "o" );
b.indexOf( "o" );
var c = a.concat( "bar" );
var d = b.concat( ["b","a","r"]);
a === c;
b === d;
a; //"foo"
b; //["f","o","o"]
javascript中字符串是不可变的,而数组是可变的。
字符串可变是指字符串的成员函数不会改变其原始值,而是创建并返回一个新的字符串。
而数组的成员函数都是在其原始值上进行操作。
数组的许多函数处理字符串很方便,虽然字符串没有这些函数,但可以借用
var c = Array.prototype.join.call( a,"-" );
var d = Array.prototype.map.call ( a, function() {
return v.toUpperCase() + ".";
}).join( "" );
3.数字
javascript只有一种数值类型: number。它包括整数和小数
默认情况下大部分数字都以十进制显示,小数最后的0被省略
特别大和特别小的数都以十进制进行显示,与ToExponential()函数相同
tofixed()方法可指定小数部分显示的位数
toPrecision()可以指定有效数位的显示位数
2.浮点误差
0.1 + 0.2 === 0.3; //false
上面的表达式值为false,说明机器内的小数存在误差,不能用这个来判断相等
最常见的做法就是设置误差范围,通常称为机器精度,es6中这个值定义在Number.EPSILON,在es6之前,我们的polyfill代码如下
if(!Number.EPSILON) {
Number.EPSILON = Math.pow(2,-52);
}
function numbersCloseEnoughToEqual(n1,n2) {
return Math.abs( n1 - n2) < Number.EPSILON;
}
var a = 0.1 + 0.2;
var b = 0.3;
numbersCloseEnoughToEqual( a, b ); //true
numbersCloseEnoughToEqual( 0.01, 0.02); //false
上面的函数numbersCloseEnoughToEqual可以判断浮点数的相等与否
3.浮点数范围与整数范围
Number.MAX_VALUE
Number.MIN_VALUE
Number.MAX_SAFE_INTEGER
Number.MIN_SAFE_INTEGER
整数如果存放不下就需要用字符串来模拟
4.整数检测
Number.isInteger(....)方法 判断是整数
Number.isSafeInteger(....)方法 判断是安全的整数
4.特殊数值
null 空值
undefined 没有值
void的值为undefined
NaN 不是数字但仍然是number类型,比如一些极限值,NaN !=NaN
es6开始我们使用工具函数Number.isNaN(..)
es6之前的NaN存在严重bug,所以在es6之前我们仍然会采用Number.isNaN(..) ,不过是polyfill
if(!Number.NaN) {
Number.isNaN = function(n) {
return (
typeof n === "number" &&
window.isNaN( n )
);
};
}
+-Infinity,正无穷大和负无穷大
正负零 -0字符串化是“0”
JSON.stringify(-0) 0
JSON.parse("-0") -0
判断-0的等式
function isNegZero(n) {
n = Number( n );
return (n === 0) && (1 / n === -Infinity);
}
es6中判断两个值是否绝对相等 Object.is(....)
var a = 2 / "foo"; //NaN
var b = -3 * 0; //-0
Object.is( a,NaN ); // true
Object.is( b, -0 ); //true
Object.is( b, 0 ); //false
polyfill代码
if(!Object.is) {
Object.is = function(v1,v2) {
if(v1 === 0 && v2 === 0) {
return 1 / v1 === 1 / v2;
}
if(v1 !== v1){
return v2 !== v2;
}
return v1 === v2;
}
}
5.值和引用
简单值总是通过值复制的方式来复制,传递,包括null,undefined,字符串,数字,布尔,ES6中的symbol
复合值,对象和函数都是通过引用复制来赋值,传递
由于引用指向的是值本身而非变量,所以一个引用无法更改另一个引用的指向
x和a是值的两个引用,修改x无法引起a的变动
function foo(x) {
x.push( 4 );
x; //[1,2,3,4]
x = [4,5,6];
x.push(7);
x; //[4,5,6,7]
}
var a = [1,2,3];
foo( a );
a; [1,2,3,4]
x.length = 0 ,x.push(4,5,6,7)更改了当前数组,a的指向的值变成了[4,5,6,7]
function foo(x) {
x.push(4);
x; //1,2,3,4
x.length = 0;
x.push( 4, 5, 6, 7);
x; //[4,5,6,7]
}
var a = [1,2,3];
foo( a );
a; //[4,5,6,7]
我们无法自行决定使用值复制还是引用复制,一切有值的类型决定。
如果通过值复制的方式传递复合值,就需要为其创建一个复本,这样传递的就不再是原始值
a.slice() 不带参数会返回当前数组的一个浅复本
如果要将标量基本类型值传递到函数内并进行更改,就需要将该值封装到一个复合值中,然后通过引用复制的方式传递
function foo(wrapper) {
wrapper.a = 42;
}
var obj = {
a: 2
};
foo( obj );
obj.a;