JavaScript是一门弱语言,不像大学时候学的C语言,用一个变量,还要先定义数据类型,定义成了int整型,就不能放字符串进去。
JavaScript定义的变量,就是你先放了数字进去,它就变成了数字类型,后面改放了字符串进去,也就变了字符串类型。
所以,在进行一些运算的时候,虽然灵活,但也会出毛病,这也是它的弱点。
数据类型的种类
最新的ECMAScript定义了7种数据类型:
Number 数值类型,不区分整数和浮点数。
String 字符串类型。
Boolean 布尔值类型,只有true和false。
Object 对象(Function函数、内置的Date、Array、Math都是对象类型)。
undefined value值未定义。
null 空的值。
Symbol (ES6新增,表示实例唯一且不可变的数据类型)
一、Number数字类型
如果都是1+1=2这样的运算,那么也简单多了,问题是,0.1+0.2 != 0.3是不是就有点看不懂了。
number数值类型包括所有的数字和一个NaN(not a number).
在js中数字取值的范围是 [-1.7976xxxxe308 ~ -5e-324, 0, 5e-324 ~ 1.7976xxxxe308]。
数字常用的表示形式有:
3; //整数 0.314; //浮点数 -23; //负数 10.2e3; //科学计数法,表示10.2*1000=10200 1.5e-3; //表示1.5*0.001=0.0015 0x10; //十六进制,用0x开头,后面用0-9,a-f表示。还有八进制,二进制那些,了解即可。 NaN; //not a number,不是数字的数值类型,计算不出结果的时候表示为NaN。 Infinity; // Infinity表示无限大,当数值超过了JavaScript的Number所能表示的最大值时,就表示为Infinity
有一个Number()函数可以显性把其他类型的值转换成数字类型。
//Number()函数的转换规则 true -> 1 false -> 0 Null -> 0 undefined -> NaN 'abc' -> NaN '123' -> 123 [] -> 0 [5] -> 5 [1,2] -> NaN {} -> NaN function(){} -> NaN '192.168.14.25' -> NaN
由此可见,Number是把( )里面的参数作为一个整体来转换,能够转成数字的就转,不能转成数字的就是NaN。
那如果遇到'200px'这样的值,需要获取200这个数字,就不能用Number()来硬转了,需要借用parseInt()来实现。
parseInt('200px') -> 200 parseInt('21.8px') -> 21 parstInt('-200px') -> -200
parseInt():从数据的左边开始,一个值一个值的转,直到不是数字为止。只能转出整数的数字类型。
如果是小数呢?就可以用parseFloat()。
parseFloat('12.5元') -> 12.5 parseFloat('192.168.12.4') -> 192.168 parseFloat('-128.32546元') -> -128.32546
parseFloat(): 从数据的左边开始,一个数字一个数字的转,认识一个小数点,但是遇到第二个小数点或别的符号就停止了。
小技巧:利用这两个函数可以判断一个数值是否是整数。
var num=12.25; if(parseInt(num)==parseFloat(num)){ alert(num+"是一个整数"); } else{ alert(num+'是一个小数'); }
注意:Number()/parseFloat/parseInt()是JavaScript的全局函数,可以处理任何数据类型,只不过在处理数字的时候很在行。
既然有显性转换,也就存在隐性转换。
通过一些运算符,把字符串转换成了数字类型。
'200' - '3' -> 197 '200' * '200' -> 40000 '200' / '4' -> 50 '200' % '3' -> 2
还有累加累减,++ 、 -- 也能把字符串转换成数字。
var a='10'; a++; alert(a);
还有>、<、==等比较运算符。
'10' > 9 -> true 有一方是数字,就转成为数字来比较大小 '10' > '9' -> false 两方都是字符,则是一位一位的比较,先拿10里面的第一位1来和9比较,9大,则不论1后面是什么值,都小于9. '10' == 10 -> true
以及一个特殊的取反‘!’运算符,不管后面跟什么数据类型,都能转成布尔值。
!0 -> true !'0' -> false !{} -> false !NaN -> true !200 -> false !'ok' -> false ![] -> false
需要注意的是number的精度问题,计算机存储是二进制,JS 遵循 IEEE 754 规范,采用双精度存储(double precision),占用 64 bit。
1位用来表示符号位
11位用来表示指数
52位表示尾数
所以,无穷尽的数字是放不完的,会导致精度丢失。
0.1+0.2=0.30000000000000004 ,所以不等于0.3.
这种问题可以考虑把浮点数乘以倍数变成整数,再除以倍数变回正确的值。
(0.1*10+0.2*10)/10==0.3 -> true
这些底层的知识真是太让人痛苦了。具体文章可以看:JavaScript数字精度丢失问题总结
二、String字符串类型
字符串由零个或多个字符构成。字符包括字母、数字、标点符号和空格。字符串必须放在引号里——单引号和双引号都允许使用。
如果字符串包含双引号字符,就应该把整个字符串放在单引号中;如果字符串包含单引号字符,就应该把整个字符串放在双引号中。
字符串创建的时候直接把字符串赋值给变量即可。
var str1="hello world"; var city='ChengDu'; var price='24'
可以使用‘+’进行字符串连结。
var price='24元'; var f_name='苹果'; alert(f_name+'的价格是'+price);
其实JavaScript有一个String字符串对象,但是我们不用 var string1 = new String("Hello")这种方式去创建字符串,JavaScript会自动帮助我们将字符串转换成字符串对象。
既然是对象,所以String提供了很多属性和方法给字符串使用。
最常见的就是length属性。
var company='成都华信智原有限公司' alert(company.length);
以及charAt()、indexOf()函数等。这些函数在后面专门讲对象的内容再细说。
三、Boolean布尔值类型
就只有true和false两个值。
if条件判断语言会自动执行Boolean的转换。
不同类型的数据都有对应的Boolean值。
数据类型 | true | false |
Number | 任何非零数值(包括无穷大) | 0和NaN |
String | 任何非空字符串 | ""空字符串(不是" "," "是包含空格的字符串) |
Boolean | true | false |
Object | 非null的任何对象 | null |
Undefined | 无 | undefined |
四、Object对象类型
这是一个嗨复杂的类型,比如Function函数,Array数组都是常见的对象。
书上说的:对象就是一组数据和功能的集合。
记得上大学的时候,老师讲对象,讲构造函数,我是一脸懵逼的,觉得好抽象啊。所以面向对象的语言,理解了对象这个关键的概念,才算入了点门。
对象根据环境,有本地对象( ECMAScript 实现提供的对象)、内置对象(Math)、宿主对象(DOM、BOM)。
具体可以查看w3school的官方文档:ECMAScript 对象类型
1、创建对象实例的两种基本方法
第一种是用new操作符后面跟上Object构造函数。
var person=new Object(); //创建Object引用类型的一个新实例,并且把该实例保存在变量person中。 person.firstName="John"; //对象的实例.属性=属性值; person.lastName="Doe"; person.age=35; person.address="ChengDu"; person.fullName=function(){ return this.firstName+" "+this.lastName; }
第二种是使用对象字面量的方法。对象字面量是对象定义的一种简写方式,目的在于简化创建包含大量属性的对象的过程。
var person={ firstName:"John", //属性:属性值, lastName:"Doe", age:35, address:"ChengDu", fullName:function(){ //方法是存储为属性的函数。 return this.firstName+" "+this.lastName; //在函数定义中,谁拥有这个函数,谁就是this。 } };
属性是描述对象的数据,方法是对象的功能行为。比如一辆车,可以用颜色、重量等属性来描述车的状态,用发动、停止等动作来表示它的功能。
2、访问属性和方法
访问属性主要有“.”语法和[]两种。
objectName.propertyName || objectName["propertyName"] //比如访问person里面的firstName属性 person.firstName; person["firstName"]; //如果这个属性名称不是变量,需要加上引号。 //方括号语法的主要优点是可以通过变量来访问属性,如果属性中包含会导致语法错误的字符,或者属性名使用的是关键字或保留字,也可以使用方括号表示法。
访问方法就是在调用函数。
objectName.methodName() //比如调用person的fullName方法。 person.fullName(); //也可以把函数的值赋给一个变量。 name=person.fullName(); //如果函数不带(),则返回的是函数定义本身。 name=person.fullName;
注意:虽然String、Number、Boolean的确是一种本地对象,但是我们最好不要用申明对象实例的方式去用它。
也就是说不要这样用:
var str=new String(); var num=new Number(); var b=new Boolean();
而应该直接赋值给一个普通的变量:
var str="hello world"; var num=20; var t=true;
因为定义为对象和定义成一个普通的变量,存放的内存方式不一样,销毁的方式也不一样,并且让代码复杂化和降低了执行速度。
五、undefined未定义
定义了一个变量,但是还没有赋值,则这个变量的值是undefined,数据类型也是undefined.
var a;
通过将值设为undefined,可以清空任何变量。
a=undefined;
六、null
null表示空,“nothing”,但是它的数据类型是对象,所以可以表示一个空对象。
var timer=null; //定义了一个timer变量,存放了一个null对象。表示没有对象。
也可以通过设置为null来清空一个对象。
var person={ firstName:"John", //属性:属性值, lastName:"Doe", age:35 } person=null; //值为null,数据类型为object。
也可以设置为undefined来清空对象。
var person={ firstName:"John", //属性:属性值, lastName:"Doe", age:35 } person=undefined;//值和数据类型都是undefined。
是不是觉得undefined和null很相似,没有啥区别。
可以简单粗暴的说null和undefined就是值相同但是数据类型不一样。
typeof null -> object typeof undefined -> undefined null==undefined -> true null===undefined -> false
Number(null) -> 0 Number(undefined) -> NaN !null -> true !undefined -> true
详细说明可以看看这篇文章:js 中null,undefined区别
七、Symbol类型
是ES6新增的一种原始类型。在学习ES6的时候再说了。
八、typeof运算符
JavaScript的数据类型分为两大类,一种是原始类型(primitive type),一种是复杂类型(complex type)。
原始类型指的是这种数据类型的值是单个简单的数据值,没有其他属性或方法。
所以,JavaScript有五个原始类型:Number、String、Boolean、Null、Undefined,现在新增了一个Symbol,就六个了。
复杂类型就是object、function这种。
用typeof运算符可以查看它们的数据类型:
typeof 4 -> number typeof "abc" -> string typeof true -> boolean typeof undefined -> undefined typeof null -> object //返回的是Object类型
按理说typeof null就应该返回null,结果返回的是object,object类型应该属于复杂类型,但是null又表示空对象,技术上还是属于原始类型,所以这个错误真的让人很晕。
type of {name:'John', age:34} -> object type of [1,2,3] -> object //数组返回的也是object type of function(){} -> function
typeof不能返回数组对象为array,但是可以返回function函数对象。
如果想精准的获取对象的类型时,可以使用Object.prototype.toString方法。
console.log(Object.prototype.toString.call("jerry"));//[object String] console.log(Object.prototype.toString.call(12));//[object Number] console.log(Object.prototype.toString.call(true));//[object Boolean] console.log(Object.prototype.toString.call(undefined));//[object Undefined] console.log(Object.prototype.toString.call(null));//[object Null] console.log(Object.prototype.toString.call({name: "jerry"}));//[object Object] console.log(Object.prototype.toString.call(function(){}));//[object Function] console.log(Object.prototype.toString.call([]));//[object Array] console.log(Object.prototype.toString.call(new Date));//[object Date] console.log(Object.prototype.toString.call(/\d/));//[object RegExp] function Person(){}; console.log(Object.prototype.toString.call(new Person));//[object Object]
可以这样使用:
//判断是否为函数 function isFunction(it) { return Object.prototype.toString.call(it) === '[object Function]'; } //判断是否为数组: function isArray(o) { return Object.prototype.toString.call(o) === '[object Array]'; }
发表评论:
◎请发表你卖萌撒娇或一针见血的评论,严禁小广告。