数组,字符串,数字是程序的基本组成部分,但也有你不知道的另一面。
数组
数组可以容纳任何类型的值。
- 稀疏数组
var a = [];
a[0] = 1;
a[2] = 3;
a[1] // undefined
a.length; // 3
数组通过数字进行索引,数组也是对象,所以也可以包含字符串键值和属性。
var a = [];
a[0] = 1;
a['foobar'] = 2;
a.length; //2
a.foobar //2
a['13'] = 42;
a ; //(14)[1, empty × 12, 42, foobar: 2]
- 类数组
类数组,就是一组可以通过数字索引的对象。可以通过Array.prototype.slice.call(arguments) //返回一个数组副本
ES6的Array.from同样可以实现,Array.from(arguments);
字符串
字符串 VS 字符串数组
var a = 'foo';
var b = ['f','o','o'];
字符串,字符串数组是两码事,字符串也有length属性以及indexOf(),concat()方法。
字符串是类数组。
字符串也可以借用数组的方法达到变更自己的目的。
var a = 'foo'
var b = Array.prototype.join.call(a,'-')
b //"f-o-o"
字符串的反转(面试常见问题)
var a = 'foo'
//将字符串转换为数组,反转,再转换为字符串
Array.from(a).reverse().join('') // oof
a.split("").reverse().join("") //oof
join方法,是将字符串数组转化为字符串。
split()方法是将字符串分割,转化为数组。
数字
javascript没有真正意义上的整数,10.0等同于10。
0Xf3; //243的十六进制,javascript严格模式下将不支持
0363; //243的八进制
0.1+0.2 === 0.3 // false
0.1+0.2 //0.30000000000000004
0.1+0.2 > 0.3 //true
0.1 + 0.2 - 0.3 = 5.551115123125783e-17
5.551115123125783e-17.toFixed(20) //"0.00000000000000005551"
Math.pow(2,-52) //表示2的-50次幂,就等于Number.EPSILON
ES6引入了Number.EPSILON,它的值是2.220446049250313e-16。表示1与大于1的最小浮点数之间的差。其实就是JavaScript能够表示的最小精度,目的是为浮点数设置一个误差范围。
//误差检查函数
function withinErrorMargin (left, right) {
return Math.abs(left - right) < Number.EPSILON * Math.pow(2, 2);
}
withinErrorMargin(0.1 + 0.2, 0.3) //true
ES6的Number.isInteger()方法检测一个值是否为整数:
Number.isInteger( 42 ); // true
Number.isInteger( 42.000 ); // true
Number.isInteger( 42.3 ); // false
特殊数值
不是值的值:
undefined,从未赋过值
null,空值
表达式void _没有返回值,返回结果是undefined。void并不改变表达式的结果,只是让表达式不返回值。
var a = 42;
console.log(void a, a); //undefined 42
void 0; // undefined
按照惯例用void 0来获取undefine(这源自C语言,void true或者void 表达式也是可以的)。void 1,void 1和undefined之间没有实质区别。
不是数字的数字NaN
NaN,不是一个数字,”无效数值“,”失败数值“,”坏数值“
NaN是一个警戒值,用于指出数字类型中的错误情况,”执行数学运算没有成功,这是失败返回后的结果“。
var a = 2 / 'foo'; //NaN
var b = 'foo';
isNaN(a) //true
isNaN(b) //true-------------晕【这是个bug!!!!】
判断一个变量是不是NaN,方法isNaN(a); // 检查参数是否不是NaN,也不是数字。
可以利用NaN是javascript中唯一一个不等于自身的值
判断两个值相等
ES6新增的方法Object.is()来判断绝对相等。
但是== 和 === 的效率要比Object.is()的效率要高,所以尽可能使用前者。
值的引用
javascript中简单值(基本类型)总是通过值复制方式来赋值/传递,null,undefined,string,number,boolean,symbol。
复合值(对象和函数,数组)是通过引用复制来赋值/传递。
引用指向的是值本身,而不是变量,所以一个引用无法更改另一个引用的指向。
var a = [1,2,3];
var b = a;
b = [4,5,6];
a //[1,2,3]
b //[4,5,6]
出个题:
function foo(x){
x.push(4);
console.log(x); //[1,2,3,4]
x = [4,5,6];
x.push(7);
console.log(x); //[4,5,6,7]
}
var a = [1,2,3];
foo(a);
console.log(a) //[1,2,3,4]
函数参数x实际上将引用a的副本赋值给x,a指向仍然是[1,2,3]。通过引用x更改了数组的值,后又将x指向另外一个数组[4,5,6]。
a.slice()//不会改变当前数组,返回一个浅副本