数据类型及其常见的隐式转换逻辑:
弱类型特性:
var num = 32; //Number类型
num = “this is string”; //String类型
32+32 //64
“32” + 32 //字符串运算--字符串拼接 “3232”
“32” – 32 //数字运算—相减 0
六种数据类型
5种原始类型: number、string、boolean、null、undefined
1种对象类型:Object(对象)--包括:Function、Array、Date……
JS隐式转换:
一、+和-
字符串:
1.var x = ‘this is me’ + 42; //字符串拼接
2.var y = 42 + ‘this is you’; //字符串拼接
数字:
1.“37” – 7 // 30 减法运算
2.“37” + 7 //377 字符串拼接
Js中不需要显示地去定义变量的类型,实际上,根据不同的类型会有不同的处理。
巧用 +/- 规则转换类型
1. num – 0 //Number类型
2. num + ‘’ //String类型
二、a == b
1.“1.23” == 1.23 //true,隐式转换,把 “1.23”转换为1.23 再进行比较。
2.0 == false //true,隐式转换,0转换为false。
3.null == undefined //true,隐式转换,null转为false, undefined转为false (理解有点问题) 正确:js规范中提到,要比较相等性之前,不能讲null和undefined转换成其他任何值,并且规定null和undefined是相等的。
null和undefined都代表无效的值
4.null === undefined //false 他们不属于同一数据类型。
Typeof null //object 表示没有对象
Typeof undefined //undefined
5.new Object() == new Object() //false
6.[1,2,3] == [1,2,3] //false
解析:
[1,2,3] 相当于 new Array(1,2,3); 这样的操作,也就是说,相当于声明了一个数组。而JS中我们知道,Array是一个引用类型,因此两个[1,2,3]其实是两个包含元素1、2、3的数组,比较他们,其实是在比较指向这两个数组的内存地址(在JS中,其实他俩只是包含元素相同的两个不同的对象)。因此,在JS中一般要比较两个数组里的值是否相同,一般是先通过固定的排序方法,例如从小到大排序,再使用toStirng()方法,将他们转换成字符串后比较。因为String类型的行为和特征与基本类型相似。
三、a === b 全等:首先判断等号两边的类型,类型不同,返回false
类型相同, ===:
- null === null
- undefined === undefined
- NaN ≠ NaN (NaN 和任何相比都不相等)
- new Object() ≠ new Object() 对象都用引用去比较
- var x =new Object(); x==x || x全等x
总结:
类型不同,尝试类型转换(隐式转换)和比较:
- null == undefined 相等 //true
- number == string 转 number 1 == “1.0” //true
- boolean == ?(任何类型) 先boolean转number,ture=>1 false=>0 1 == true //true
- object == number | string 尝试对象转为基本类型 new String(‘hi’) == ‘hi’ //true 其他:false
JavaScript包装对象:
string、number、boolean 这三种原始数据类型 都有对应的包装对象
在javaScript 中,当把一个基本类型尝试以对象的方式去使用它的时候,比如我们去访问它的length属性或者给它增加一些属性,那么当我们做这些操作的时候,js会智能地把基本类型转化为对应的包装类型对象,所以说这里转化为包装对象,相当于new 了一个String()—上面例子,当完成访问—str.length返回 || str.t设置后返回,这个临时对象会被销毁掉,所以str.t = 10 输出str.t为undefined
类型检测:
- typeof 运算符,返回字符串
- instanceof 运算符
- Object.prototype.toString 函数
- constructor 判断constructor
- duck type 用鸭子类型
typeof:返回一个字符串,非常适合函数对象和基本类型的判断
typeof 100 // “number”
typeof true // “boolean”
typeof function // “function”
typeof(undefined) // “undefined”
typeof new Object() // “object”
typeof [1,2] // “object”
typeof NaN // “number” NaN->number类型里面的一个特殊的值
typeof null // “object”
为什么typeof null === “object” ?
历史的原因,事实上在标准规范中,尝试把typeof null 返回的结果为 “null” ,但是修改后导致大量网站无法访问,为了兼容,保持为typeof null === “object”,typeof在判断一些基本类型、函数对象的时候非常方便,但是对于其他对象的类型判断,就无办法,比如判断一个对象是否为数组Array,如果用typeof 会返回 “object”,显然不是我们想要的。
对于判断对象类型,我们更常用的是instanceof
instanceof: 基于原型链去判断的操作符
obj instanceof Object
instanceof期望的左操作数是一个对象,如果不是对象,而是基本类型,会直接返回false;期望的右操作数,必须是一个函数对象或者说函数构造器
例子:
- [1,2] instanceof Array === true
- new Object() instanceof Array === false
本例子分析:
定义两个构造函数—Student/Person;任何一个构造函数都有一个prototype对象属性,那么这个对象属性将用作使用new来new 构造函数 这样的方式去构造出对象的原型。比如这里的Person函数,这个函数就会有一个prototype属性,当我们用new Person()去创建实例的时候,那么这个对象实例就会有一个原型指向Person.prototype这样一个对象。
那么bosn instanceof Person,Person是bosn的父类,那么是否相等呢?
首先,bosn对象会有一个原型__proto__,它的原型会指向它的构造器Student.prototype上,那么这里面,当判断bosn instanceof Person 时,bosn的原型也就是Student.prototype≠Person.prototype
所以,原型链会向上去查找,bosn.proto.proto,即bosn的原型的原型 等于 Person.prototype,所以返回true
注意:由于instanceof 是判断对象是否相等的,我们知道JavaScript是按照引用去判断对象(两个完全相同的空对象比较,因为不是同一个对象,也是不相等),这里有个坑:
不同window或者iframe下,完全相同的对象,也是不相同,不相等。返回false。
Object.prototype.toString:
- Object.prototype.toString.apply([]); === “[object Array]”;
- Object.prototype.toString.apply(function(){}); === “[object Function]”;
- Object.prototype.toString.apply(null) === “[object Null]”;
- Object.prototype.toString.apply(undefined); === “[object Undefined]”;
注意: 兼容性问题 IE6/7/8 Object.prototype.toString.apply(null) 返回 “[object Object]”
construct:
任何一个对象都有一个construct属性,它是继承自原型的,那么这个construct会指向构造这个对象的构造器或者说构造函数。由于construct可以被改写,使用时要小心。
duck type(自查哦): 鸭子类型,比如说我们不知道这个对象是不是数组,可以判断它的length是不是数字,是否有push/pop等数组方法,通过一些特征去判断对象是否属于某些类型。
总结前三种:
- typeof:适合基本类型及function检测,遇到null失效,返回“object”,不能用它去判断null。怎么判断null呢?可以用=== null去判断某一个变量的值是不是null。
- Object.prototype.toString:判断是不是基本类型/数组/函数,注意:遇到null和undefined,在IE 6/7/8会存在兼容问题,返回[object Object]
- Instanceof: 比较适合去判断对象/原生对象,比如判断某一个对象是否属于某一个构造器所构造的,或者是否有继承关系,在判断是不是数组/Date/正则等等对象的类型的判断上,用instanceof会非常好用!但是在不同的iframe和window之间检测会失效,慎重使用!