JavaScript复习笔记(3)——数据类型(null、undefined、NaN)与深度克隆
JavaScript中的数据类型:Number、Boolean、String、Object、Function
但是此外还有一些容易混淆的类型如null、undefined、NaN、Array的概念
function showDataType(){ console.log("Number: "+typeof 1); console.log("String:"+typeof "str"); console.log("Boolean:"+typeof true); console.log("Null:"+typeof null); console.log("Undefined:"+typeof undefined); console.log("NaN:"+typeof NaN) var person={name:"lcy"}; console.log("Object:"+typeof person); var arr = ["1","2"]; console.log("Array:"+typeof arr); console.log("Object Array:"+Object.prototype.toString.call(arr) ) console.log("Function:"+typeof showDataType); }
上面这段在控制台的输出结果为:
Number:number String:string Boolean:boolean Null:object Undefined:undefined NaN:number Object:object Array:object Object Array:[object Array] Function:function
总结:
- null是特殊的Object
- NaN是特殊的number
- Array属于Object,但是通过访问内部属性的方式还是可以进行类型判断
进一步对null、undefinde、NaN进行解析:
function showDataType2(){ console.log(null===null);//true console.log(undefined===undefined);//true console.log(NaN===NaN);//false console.log(null==undefined);//true console.log(null===undefined); //false console.log("!null: "+!null);//true console.log("!undefined: "+!undefined);//true console.log(NaN==undefined);//false console.log(NaN===undefined);//false console.log(NaN==null);//false console.log(NaN===null);//false console.log(null instanceof Object)//false }
总结:
- NaN与自己本身也不相等
- null和undefined虽然不属于boolean类型,但是却可以转换成boolean类型进行判断,并且null==undefined是true的
- null的typeof是Object,null却不是Object子类的实例
同时,我们对这些数据类型的constructor也进行一次分析
function showDataType(){ /*constructor*/ var obj=1; console.log("Number:"+obj.constructor);//Number obj="1"; console.log("String:"+obj.constructor);//String obj=true; console.log("Boolean:"+obj.constructor);//Boolean obj=null; //console.log("Null:"+obj.constructor);//报错 obj=undefined; //console.log("Undefined:"+obj.constructor);//报错 obj=NaN; console.log("NaN:"+obj.constructor)//Number obj = {name:"lcy"}; console.log("Object:"+obj.constructor);//Object obj = ["1","2"]; console.log("Array:"+obj.constructor);//Array console.log("Function:"+showDataType.constructor);//Function /*valueOf*/ var obj=1; console.log("Number:"+obj.valueOf());//1 obj="1"; console.log("String:"+obj.valueOf());//1 obj=true; console.log("Boolean:"+obj.valueOf());//true obj=null; //console.log("Null:"+obj.valueOf());//报错 obj=undefined; //console.log("Undefined:"+obj.valueOf());报错 obj=NaN; console.log("NaN:"+obj.valueOf())//NaN obj = {name:"lcy"}; console.log("Object:"+obj.valueOf());//[object Object] obj = ["1","2"]; console.log("Array:"+obj.valueOf());//1,2 console.log("Function:"+showDataType.valueOf());//输出了整个方法的代码 }
了解了多种数据类型以及差别之后,回过头再来看深度克隆的问题,在深度克隆中比较容易出现的瑕疵有:
1.对null undefined类型的克隆
2.克隆后对prototype添加非常规属性,克隆对象与原对象能否区分开来
3.对Array的克隆
function cloneObject(obj) { //null & undefined var o; if(!obj){ return obj; } else{ //array if(Object.prototype.toString.call(obj)=="[object Array]"){ return obj.slice(0)//clone arrry } //object else if(typeof obj ==="object"){ o = new obj.constructor(); for(var key in obj){ if(!obj.hasOwnProperty(key)){ o[key] = cloneObject(obj[key]); } } } //function else if(typeof obj==="function"){ return obj; } //number,string,boolean, else{ o = new obj.constructor(obj.valueOf()); } } return o; }
对以上方法进行测试:
function Obj1(){ this.a = 1 ; this.b = null; this.c = [1,2,3,4]; this.d; this.fn = function(){alert("clone function")}; } Obj1.prototype.arr = [1,2,3,4]; var o1 = new Obj1(); var o2 = cloneObject(o1); console.log(o1); console.log(o2); o1.c[0]=100; o1.d=new Array(1,5,7); o1.fn = function(){alert("clone function success")}; console.log(o1); console.log(o2); o1.arr[0] = 100; console.log(o1.arr); console.log(o2.arr);
输出结果如图所示:
那么基本上是克隆成功了,虽然方法看上去有点臃肿,但是逻辑上比较清晰。
注:
克隆数组的方法:
1.新建一个数字,逐值赋值
2.利用slice()方法
3.利用contact与一个空数组进行合并