数据类型
原始类型
- number
- string
- boolean
- null
- undefined
- symbol
对象类型
- object
- array 属于 object
- function 属于 object
显式转换
- Number()
主要说一下如果传入的是个复合类型的值,先调用valueOf,如果该返回值是复合类型的,继续调用toString的值,如果依然是复合类型的(比如自己改写了toStirng)则报错 - String()
String如果传入复合类型的值调用顺序正好和Number()方法相反 - Boolean()
输入undefined、null、0、NaN、""的时候为false,其他为true;
隐式转换
“55”+5 //“555”
“55”-5 //50
比如
+""
-0
四则运算 判断语句 等Native调用
相当于被动的调用了显示转换的方法
console.log([]+[])//""
console.log([]+{})//[object Object]
console.log({}+[])//[object Object](chrome、firefox输出0,因为无视了{},直接执行了+[])
console.log({}+{})//[object Object][object Object](不同浏览器的解释差距很大,这里需要后查找资料,这里数据是vscode输出的)(firefox中是NaN)
console.log(true+true)//2
console.log(1+{a:1})//
等于和严格等于
- “123” == 123
- 0 == false
- null == undefined
- [1,2] == [1,2]
- 以上都为true
- new Object() == new Object() //false
严格等于
- “123” === 123 //false
- 0 === false //false
- null === undefined //false
- new Object() === new Object() //false
- [1,2] === [1,2] //false
严格等于在对象类型的比较中比较的是引用值;
NaN和任何对象都不想等,包括自己。
等于会在比较类型不同的时候尝试做类型转换。
包装对象
var a ;
console.log(a);//undefined
a = "string"
console.log(a.length);//6
a.prop = 3;
console.log(a.prop);//undefined
在执行a.length的时候发生了什么?
在js中一个基本类型被当作对象去访问的时候,这个基本类型会转换为一个包装类型对象。
但是完成访问之后,这个临时对象会被销毁。
类型检测
- typeof
- instanceof
- Object.prototype.toString
- construtor //判断构造器 慎用,因为可以被修改
- duck type //使用特征判断,比如
最常用的是typeof 来判断基本类型
typeof 100//number
typeof "123"//string
typeof true //boolean
typeof function //function
typeof undefined//undefined
typeof {}//object
typeof []//object
typeof NaN//number NaN是一个number类型的特殊的值
typeof Infinity //number
typeof null //object 历史遗留原因,规范中规定typeof null的值为null之后导致大量bug出现,所以最后定为object
instanceof基于原型链判断
console.log([1, 2] instanceof Array); //true
console.log("1,2" instanceof Array); //false
console.log("1,2" instanceof Object); //false
console.log("1,2" instanceof String); //false
console.log(new String("1,2") instanceof String); //true
console.log(new String("1,2") instanceof Object); //true
function Person() {};
function Student() {};
Student.prototype = new Person();
Student.prototype.constructor = Student;
var zhaosi = new Person();
var xiaoming = new Student();
console.log(zhaosi instanceof Person); //true
console.log(xiaoming instanceof Person); //true
console.log(xiaoming instanceof Student); //true
//不可以跨窗口调用
obj.__proto__.constructor.name
//获取构造函数的名称
console.log({}.__proto__.constructor.name)
console.log([].__proto__.constructor.name)
console.log(undefined.__proto__.constructor.name)
//null undefined不可用
Object.prototype.toString.apply() 方法
function Person() {};
function Student() {};
Student.prototype = new Person();
Student.prototype.constructor = Student;
var zhaosi = new Person();
var xiaoming = new Student();
var ar = [];
console.log(Object.prototype.toString.apply(ar)); //[object Array]
console.log(Object.prototype.toString.apply(zhaosi)); //[object Object]
console.log(zhaosi+""); //[object Object]
console.log(Object.prototype.toString.apply(123)); //[object Number]
console.log(Object.prototype.toString.apply("123")); //[object String]
//ie 6-8 中null 和undefined 都返回Object
console.log(Object.prototype.toString.apply(null)); //[object Object]
//其他
console.log(Object.prototype.toString.apply(null)); //[object Null]
本阶段练习
给定任意两个数组,判断是否相似;
相似标准:
- 数组中的成员类型相同,顺序可以不同。例如[1, true] 与 [false, 2]是相似的。
- 数组的长度一致。
- 类型的判断范围,需要区分:String, Boolean, Number, undefined, null, 函数,日期, window, Object
var arr1 = [null, 100];
var arr2 = [100, {}];
arraysSimilar(arr1, arr2);
function arraysSimilar(arr1, arr2) {
if (arr1 instanceof Array && arr2 instanceof Array) {
if (arr1.length == arr2.length) {
console.log(JSON.stringify(typeCount(arr1)));
console.log(JSON.stringify(typeCount(arr2)));
if (JSON.stringify(typeCount(arr1)) == JSON.stringify(typeCount(arr2))) {
return true;
}else{
return false;
}
} else {
return false;
}
} else {
return false;
}
function typeCount(array) {
var arrayTypeObject = new typeObject();
if (array instanceof Array) {
for (var i = 0; i < array.length; i++) {
switch (typeof array[i]) {
//先统计基础类型
case "string":
arrayTypeObject.String++;
break;
case "number":
arrayTypeObject.Number++;
break;
case "undefined":
arrayTypeObject.undefined++;
break;
case "boolean":
arrayTypeObject.Boolean++;
break;
case "object":
//继续统计object中包含的 null, 函数,日期, window和普通对象;
if (array[i] === null) {
arrayTypeObject.null++;
} else {
switch (array[i] + '') {
case '[object Function]':
arrayTypeObject.function++;
break;
case '[object Date]':
arrayTypeObject.date++;
break;
case '[object Window]':
arrayTypeObject.window++;
break;
case '[object Object]':
arrayTypeObject.normalObject++;
break;
}
}
break;
default:
console.log('error:' + typeof array[i]);
}
}
} else {
return array + "is not Array Object";
}
return arrayTypeObject;
}
function typeObject() {
this.String = 0;
this.Boolean = 0;
this.Number = 0;
this.undefined = 0;
this.null = 0;
this.function = 0;
this.date = 0;
this.window = 0;
this.normalObject = 0;
}
};
在上面的答案中,因为typeObject这个构造函数是我自己写的,所以在JSON.stringify的时候顺序不会出错。
但是用JSON.stringify来对比两个对象是否相等确实不严谨,如果里面的属性顺序改变会造成误判。
即使属性顺序相同的时候,也无法准确的比较出字符串"1"和数字1的差异。如果key为undefined和日期还有function的适合都会出现不同情况的错误。
同时JS官方也没有给出比较两个对象是否相等的办法。
思考一下如何较为严谨的去比较两个对象的属性和属性值是否完全相等。