JS基本概念(2)
【4】数据类型:
- 基本数据类型:Undefined、Null、Boolean、Number、String
- 复杂数据类型:Object(本质上是由一组无序的名值对组成的,例:name="value")
1.typeof操作符:typeof()
- "undefined"——如果这个值未定义
- "boolean"——如果这个值是布尔值
- "string"——如果这个值是字符串
- "number"——如果这个值是数值
- "object"——如果这个值是对象或null
- "function"——如果这个值是函数
2.Undefined类型
对未初始化和未声明的变量执行typeof操作符都返回了undefined
3.Null类型
- null值表示一个空对象指针
- 如果定义的变量准备用来保存对象,最好将该变量初始化为null而不是其他值
- !undefined值派生自null值,故 alert(undefined == null); //true
4.Boolean类型
- boolean类型的字面值true和false是区分大小写的
- 要将一个值转换为对应的Boolean值,可以调用转型函数Boolean():
数据类型 | 转换为true的值 | 转换为false的值 |
Boolean | true | false |
String | 任何非空字符串 | ""(空字符串) |
Number | 任何非零数字值(包括无穷大) | 0和NaN |
Object | 任何对象 | null |
Undefined | n/a不适用 | undefined |
这些转换规则对理解流控制语句(如if 语句)自动执行相应的Boolean 转换非常重要,如下代码:
var message = "Hello world!"; if (message){ alert("true"); }
5.Number类型
(1)整数
- 十进制:
- 八进制:第一位必须是0(八进制字面量在严格模式下是无效的,会抛出错误)
- 十六进制:前两位必须是0x
- 在进行算数计算时,所有以八进制和十六进制表示的数值最终都会被转换成十进制数值
(2)浮点数值
- 保存浮点数值需要的内存空间是整数值的2倍,所以ECMAScript会不失时机地把浮点数值转化为整数值
- 极大、极小的数值用e表示法
var num1 = 3.125e7; //31250000 var num2 = 3e-7; //0.0000003
- 在默认情况下,ECMAScript会将小数点后带有6个0的浮点数值转换为以e表示法表示的数值
- 浮点数值最高精度是17位小数
- 在处理浮点数的时候会遇到精度问题
alert(0.1+0.2);//0.30000000000000004 alert(45.6*13); //结果是592.800000000001 alert(0.7+0.1);//输出0.7999999999999999 alert(0.6+0.2);//输出0.8
- 解决方法:
- 一种方法:比如0.7+0.1,先把0.1和0.7都乘10,加完之后再除10
- 另一种方法:定义函数来解决这个问题
// 两个浮点数求和 function accAdd(num1,num2){ var r1,r2,m; try{ r1 = num1.toString().split('.')[1].length; }catch(e){ r1 = 0; } try{ r2=num2.toString().split(".")[1].length; }catch(e){ r2=0; } m=Math.pow(10,Math.max(r1,r2)); // return (num1*m+num2*m)/m; return Math.round(num1*m+num2*m)/m; } // 两个浮点数相减 function accSub(num1,num2){ var r1,r2,m; try{ r1 = num1.toString().split('.')[1].length; }catch(e){ r1 = 0; } try{ r2=num2.toString().split(".")[1].length; }catch(e){ r2=0; } m=Math.pow(10,Math.max(r1,r2)); n=(r1>=r2)?r1:r2; return (Math.round(num1*m-num2*m)/m).toFixed(n); } // 两数相除 function accDiv(num1,num2){ var t1,t2,r1,r2; try{ t1 = num1.toString().split('.')[1].length; }catch(e){ t1 = 0; } try{ t2=num2.toString().split(".")[1].length; }catch(e){ t2=0; } r1=Number(num1.toString().replace(".","")); r2=Number(num2.toString().replace(".","")); return (r1/r2)*Math.pow(10,t2-t1); } //两数相乘 function accMul(num1,num2){ var m=0,s1=num1.toString(),s2=num2.toString(); try{m+=s1.split(".")[1].length}catch(e){}; try{m+=s2.split(".")[1].length}catch(e){}; return Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m); } document.write("使用js原生态方法"); document.write("<br/> 1.01 + 1.02 ="+(1.01 + 1.02)); document.write("<br/> 1.01 - 1.02 ="+(1.01 - 1.02)); document.write("<br/> 0.000001 / 0.0001 ="+(0.000001 / 0.0001)); document.write("<br/> 0.012345 * 0.000001 ="+(0.012345 * 0.000001)); document.write("<br/><hr/>"); document.write("<br/>使用自定义方法"); document.write("<br/> 1.01 + 1.02 ="+accAdd(1.01,1.02)); document.write("<br/> 1.01 - 1.02 ="+accSub(1.01,1.02)); document.write("<br/> 0.000001 / 0.0001 ="+accDiv(0.000001,0.0001)); document.write("<br/> 0.012345 * 0.000001 ="+accMul(0.012345,0.000001));
但是最好还是不要用JS做一些复杂的浮点运算,毕竟JS更多的作用不在于此
(3)数值范围
- Number.MIN_VALUE —— Number.MAX_VALUE
- 如果超出js数值范围内的值,这个数值将被自动转化为特殊的+/-Infinity
- 使用isFinite()函数确定一个数值是不是有穷的,返回true或false
- 访问Number.NEGATIVE_INFINITY和Number.POSITIVE_INFINITY也可以得到负和正Infinity的值
(4)NaN
- NaN,即非数值,用于表示一个本来要返回数值的操作数未返回数值的情况
- 首先,任何涉及NaN的操作都会返回NaN
- 其次,NaN与任何值都不相等,包括NaN本身 alert(NaN == NaN); //false
- ECMAScript定义了isNaN()函数,该函数接受一个参数,该参数可以是任何类型,函数会帮我们确认这个参数是否“不是数值”
alert(isNaN(NaN));//true alert(isNaN(10));//false alert(isNaN("10"));//false(可以转换成数值10) alert(isNaN("blue"));//true alert(isNaN(true));//false(可以转换成数值1)
- 在基于对象调用isNaN()函数时,会先调用对象的valueOf()方法,然后确定该方法返回的值是否可以转换为数值,如果不能,则基于这个返回值再调用toString()方法,再测试返回值
(5)数值转换
- a).Number():
- 如果是Boolean 值,true 和false 将分别被转换为1 和0。
- 如果是数字值,只是简单的传入和返回。
- 如果是null 值,返回0。
- 如果是undefined,返回NaN。
- 如果是字符串,遵循下列规则:
- 如果字符串中只包含数字(包括前面带正号或负号的情况),则将其转换为十进制数值,即"1"会变成1,"123"会变成123,而"011"会变成11(注意:前导的零被忽略了);
- 如果字符串中包含有效的浮点格式,如"1.1",则将其转换为对应的浮点数值(同样,也会忽略前导零);
- 如果字符串中包含有效的十六进制格式,例如"0xf",则将其转换为相同大小的十进制整数值;
- 如果字符串是空的(不包含任何字符),则将其转换为0;
- 如果字符串中包含除上述格式之外的字符,则将其转换为NaN。
- 如果是对象,则调用对象的valueOf()方法,然后依照前面的规则转换返回的值。如果转换的结果是NaN,则调用对象的toString()方法,然后再次依照前面的规则转换返回的字符串值。
- b).parseInt()
- 如果第一个字符不是数字字符或者负号,parseInt()返回NaN(转换空字符串也会返回NaN)
- parseInt(string, radix)
- string:必需。要被解析的字符串。
- radix:可选。表示要解析的数字的基数。该值介于 2 ~ 36 之间。如果省略该参数或其值为 0,则数字将以 10 为基础来解析。如果它以 “0x” 或 “0X” 开头,将以 16 为基数。如果该参数小于 2 或者大于 36,则 parseInt() 将返回 NaN。
- c).parseFloat()
- 从第一个字符开始解析,一直解析到字符末尾,或者解析到遇到一个无效的浮点数字字符为止
- 始终忽略前导的零
- 只解析十进制值
6.String类型
由零或多个16位Unicode字符组成的字符序列,单双引号均可
(1)特殊的字符字面量(转义序列)
字面量 | 含义 |
\b | 退格 |
\f | 进纸 |
\n | 换行 |
\r | 回车 |
\t | 制表 |
\' | 单引号,在用单引号表示的字符串中使用 |
\" | 双引号,在用双引号表示的字符串中使用 |
\\ | 反斜杠 |
\xnn | 以16进制代码nn表示的一个字符(其中n为0-F) |
\unnnn | 以16进制代码nnnn表示的一个Unicode字符(其中n为0-F) |
(2)ECMAScript中字符串是不可变的,也就是说字符串一旦创建,它们的值就不能改变。要改变某个变量保存的字符串,首先要销毁原来的字符串,然后再用另一个包含新值的字符串填充该变量
(3)转换为字符串
- 方法一:toString()方法
数值,布尔值,对象和字符串都有toString()方法,但null和undefined值没有这个方法
在调用数值的toString()方法时,可以传递一个参数:输出数值的基数,默认情况为10(十进制)
- 方法二:String()方法
如果值有toString()方法,则调用该方法(没有参数)并返回相应的结果
如果值是null,则返回"null"
如果值是undefined,则返回"undefined"
7.Object类型
(1)创建对象
- a).new构造函数法
var person = new Object(); person.name = "ls"; person.age = 21;
这种方式使用new关键字,接着跟上Object构造函数,再来给对象实例动态添加上不同的属性。这种方式比较繁琐,一般推荐使用对象字面量来创建对象。
- b).对象字面量
var person = { name:“ls”,age:21 };
这种方式直接通过花括号将对象的属性包起来,使用key/value的方式创建对象属性,每个属性之间用逗号隔开。注意:如果是最后一个属性,后面就不要加逗号,因为在一些旧的浏览器下会报错。
(2)对象实例的属性和方法(因为Object是所有对象的基础,因此所有的对象都具有这些基本的属性和方法。)
a).constructor属性:保存着用于创建当前对象的函数。对于前面的例子,构造函数(constructor)就是Object()。
var obj1 = new Object(); obj1.id = "obj1"; var obj2 = { "id": "obj2" }; console.log(obj1.constructor);//function Object(){} console.log(obj2.constructor);//function Object(){}
b).hasOwnProperty(propertyName)方法:用来检查给定的属性在当前对象实例中(而不是在实例的原型中)是否存在。其中,作为参数的属性名(propertyName)必须以字符串形式指定。
var arr = []; console.log(arr.hasOwnProperty("length"));//true console.log(arr.hasOwnProperty("hasOwnProperty"));//false //在这个例子中,首先通过定义了一个数组对象的实例arr,数组对象实际是通过原型链继承了Object对象,然后拥有自己的一些属性,我们通过hasOwnProperty方法判断length是arr自己的属性,而hasOwnProperty是在原型链上的属性。
c).isPrototypeOf(Object)方法:用于检查传入的对象是否是当前对象的原型。
function MyObject() {} var obj = new MyObject(); console.log(Object.prototype.isPrototypeOf(obj)); //true //我们知道MyObject是继承自Object对象的,而在JS中,继承是通过prototype来实现的,所以Object的prototype必定在MyObject对象实例的原型链上。
d).propertyIsEnumerable(prototypeName)方法:用于检查给定的属性是否能够使用for-in语句来枚举。与hasOwnProperty()方法一样,作为参数的属性名必须以字符串形式指定。
var obj = { name:"objName" }; for(var i in obj){ console.log(i);//name } console.log(obj.propertyIsEnumerable("constructor"));//false
e).toLocaleString()方法:返回对象的字符串表示,该字符串与执行环境的地区对应。
var obj = {}; console.log(obj.toLocaleString());//[object Object] var date = new Date(); console.log(date.toLocaleString());//2016/2/28 下午1:39:27
f).toString()方法:返回对象的字符串表示。
var obj = {}; console.log(obj.toString());//[object Object] var date = new Date(); console.log(date.toString());//Sun Feb 28 2016 13:40:36 GMT+0800 (中国标准时间)
g).valueOf()方法:返回对象的原始值,可能是字符串、数值或布尔值等。通常与toString()方法的返回值相同。
var obj = { name:"obj" }; console.log(obj.valueOf());//[object Object] var arr = [1]; console.log(arr.valueOf());//[1] var date = new Date(); console.log(date.valueOf());//1456638436303