类型
js中的变量是没有类型的,只有值才有类型,变量可以随时接受任何类型。例如:
var a = 42; console.log(typeof a); //number a = '44'; console.log(typeof a);//string
undefind 和 undeclared
在js中,已在作用域声明但还没赋值的变量,是undefined。相反还没在作用域中声明过的变量是undeclared
var a; console.log(typeof a); //undefined console.log(b);//Uncaught ReferenceError: b is not defined
需要特别注意的是如果用typeof undeclared 时,会返回undefined。
console.log(typeof b);//undefined
但是这种方式有一个好处就是可以通过typeof来检查变量是否声明过,而不会报错。例如:
if (b) { //这种方式会报错 //do something } if (typeof b !== "undefined") { //do something } if (window.b) { //也可以用这种方式 但如果代码会在其他环境中执行的话,会有问题,例如nodejs,全局对象就不是window了。 //do something }
数组
数组内部可以放任意类型的元素,也可创建稀疏数组。
var a = []; a[0] = '1a'; a[2] = '23';
这里需要注意a[1]的值是undefined。
数组也可以像对象一样有自己的属性,例如:
a['name'] = 'yu'; console.log(a.length);//3
但是数组的属性并不会改变length属性。还有一点需要注意的是,如果属性名称可以转换为十进制数字的话,那么它就会被当做索引来处理。例如:
a['13'] = 'a'; console.log(a.length); //14
类数组
一般在一些dom查询操作返回的元素列表,其实他们并非是真正意义的数组,而是一些类数组。在jq内部经常会使用类数组。
var a = { 1: 'a', 2: 'b', length: 2 };
还一个例子是arguments就是一个类数组,但在es6开始已经废止。
常用的转换类数组为真正的数组的方式为:
var arr = Array.prototype.splice.call(a);
在es6中Array新增了一个内置函数 Array.from() 也可以实现转换功能,例如:
var arr = Array.from(a);
字符串
字符串和字符串数组在很多情况下看起来是一样的,但他们并不是一回事。他们都有length属性和indexof等方法。
var a = 'abc'; var b = ['a', 'b', 'c']; console.log(a.length);//3 console.log(b.length);//3 console.log(a.indexOf('b'));//1 console.log(b.indexOf('b'));//1
但是字符串是不可变的,只能创建一个新的字符串并返回,而字符串数组可以在原始值改变的。
a[1] = 'v';
b[1] = 'v';
console.log(a);//abc console.log(b);//["a", "v", "c"]
在实际开发过程中我们可以借用数组的方法来达到某些目的。
var c = Array.prototype.join.call(a,'-'); console.log(c);//a-b-c
还有一个常见的面试题就是字符串反转问题。
数组上有一个reverse方法,用来反转数组元素,但是我们这里却无法借用,因为字符串是不可变的。
但是我们可以先把字符串转成数组,在进行反转。
var a = 'xyz'; var b = a.split('').reverse().join(); console.log(b); //z, y, x
数字
var a = 42.56; console.log(a.toFixed(0)); //43 四舍五入 console.log(a.toFixed(1)); //42.6 console.log(a.toFixed(3)); //42.560
转换的结果是字符串格式,所以如果指定的位数多于实际的位数,就会用0补齐。
对于.预算符需要特别注意,它会被优先识别为数字常量的一部分,然后才是对象属性访问符。例如:
console.log(45..toFixed(3));//45.000
console.log(45.toFixed(3));//报错
浮点数小数的问题,也就是常见的0.1+0.2===0.3问题
console.log(0.1 + 0.2 === 0.3);//false
这是因为js遵循的ieee754规范的原因,这个规范中浮点数不是很精确,他们的相加的结果是一个十分接近0.3的数字,而不是精确等于0.3。
解决方法:
if (!Number.EPSIlON) { Number.EPSILON = Math.pow(2, -52); }
function numberToEqual(a, b) { return Math.abs(a - b) < Number.EPSILON; } var a = 0.1 + 0.2; var b = 0.3; console.log(numberToEqual(a, b)); //true
整数检测
在es6中可以用Number.isInteger()方法判断
console.log(Number.isInteger(42));//true console.log(Number.isInteger(42.00));//true console.log(Number.isInteger(42.3));//false
在es6版本之前,可以用下面代码做兼容
if (!Number.isInteger) { Number.isInteger = function (num) { return typeof num == "number" && num % 1 === 0; } }
检测是否为安全整数,es6中用Number.isSafeInteger方法
console.log(Number.isSafeInteger(Number.MAX_SAFE_INTEGER)); //true console.log(Number.isSafeInteger(Math.pow(2, 53))); //false
在es6版本之前,可以用下面代码做兼容
if (!Number.isSafeInterger) { Number.isSafeInterger = function (num) { return Number.isInteger(num) && Math.abs(num) <= Number.MAX_SAFE_INTEGER }; }
undefind值从未赋过值,null值曾赋过值,但是目前没有值,
null 是一个特殊关键字,不是标示符,我们不能将其当做变量俩使用和赋值
undefind是一个标示符,可以被当做变量来使用和赋值 undefind=2;
void运算符 void是返回undefined类型的,也就是void 1 void0 等等这些和undefined没有实质的区别
特殊的数字
NaN 是一个不是数字的数字,也就是它是数字类型,但因为运算失败等原因,得到的一个无效数值。
var a = 42 / 'aa'; //NaN typeof a === 'number'; //true
但是NaN有一个特点,就是和自身永远不相等,也就是NaN!=NaN 为true,所以一般判断变量是否为数字时使用:
console.log(!isNaN('a'));//false 不是数字
这个方法虽然有这个功能,但是也可以看到 a既不是一个数字,也不是NaN,但会返回的结果却是true,这显然不太科学。
在es6中新加了一个方法Number.isNaN()方法,之前的版本用下面的代码做兼容
if (!Number.isNan) { Number.isNaN = function (n) { return (typeof n === 'number' && window.isNaN(n)); } } var a = 2 / 'f'; var b = 'fa'; console.log(Number.isNaN(a));//true console.log(Number.isNaN(b));//false
还有一个简单的方法,就是利用NaN自身不相等的特性来判断:
if (!Number.isNan) { Number.isNaN = function (n) { return n !== n; } }
无穷数
在js中 有穷数可以变成无穷数,但是无穷数却不可以变成有穷数,例如:
var a = Number.MAX_VALUE + Number.MAX_VALUE; //无穷数 var b = Number.MAX_VALUE + Number.MAX_VALUE; console.log(a / b);//NaN
因为从js语言的角度来说,这是一个未定义操作,所以返回为NaN
0值 在js中存在负0的情况,但是这种负0的情况只是显示为负0,它的实际的值还是0,例如0===-0 结果为true
在程序中有时候需要以级数形式标书,比如动画帧的速度,符号用来表示移动的方向,所以保留0的符号位防止信息丢失。
console.log(0 / -3);
console.log(0 === -0);