创建稀疏矩阵,中间会留有一些空白单元,值为undefined
var a = [ ]; a["13"] = 42; a.length; //14从0到12的值都为undefined
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( "" );javascript只有一种数值类型: number。它包括整数和小数
默认情况下大部分数字都以十进制显示,小数最后的0被省略
特别大和特别小的数都以十进制进行显示,与ToExponential()函数相同
tofixed()方法可指定小数部分显示的位数
toPrecision()可以指定有效数位的显示位数
上面的表达式值为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可以判断浮点数的相等与否
Number.MAX_VALUE
Number.MIN_VALUE
Number.MAX_SAFE_INTEGER
Number.MIN_SAFE_INTEGER
整数如果存放不下就需要用字符串来模拟
Number.isInteger(....)方法 判断是整数
Number.isSafeInteger(....)方法 判断是安全的整数
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 ); //falsepolyfill代码
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; } }简单值总是通过值复制的方式来复制,传递,包括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;