js数据类型
在ECMAScript规范中,共定义了7种数据类型,分为基本类型和引用类型两大类
1.基本类型(5种)
Undefined、Null、Boolean、Number 和 String,变量是直接按值存放的,存放在栈内存(stack)中的简单数据段,可以直接访问。
2.引用类型
何为引用类型呢?这和它的存储有关,变量保存的其实是一个指向特定位置的地址指针。当我们需要获取该引用类型变量值的时候,首先获取到地址指针,然后再从堆内存(heap)中获取到所需要的数据。在js中引用类型基本就是 Object 、Function 、Array、RegExp、Date
引用类型也称为复杂类型,由于其值的大小会改变,所以不能将其存放在栈中,否则会降低变量查询速度,因此,其值存储在堆(heap)中
js数据类型的判断
1.typeof
1 | typeof 'test'; // string 有效 |
总结上述结论:
- 对于基本类型,除
null
以外,均可以返回正确的结果。对于null
返回object
类型。 - 对于引用类型,除
function
以外,一律返回object
类型。对于function
返回function
类型。
2. instanceof
instanceof是用来判断A是否为B的实例,表达式为: A instanceof B,如果A是B的实例,则返回 true,否则返回 false。
1 | [] instanceof Array; //true |
可以看到instanceof
能够判断出[]
是Array
的实例,但它认为[]
也是Object
的实例,
原因是 instanceof
能够判断出[].__proto__
指向 Array.prototype
,而 Array.prototype.__proto__
又指向了Object.prototype
,最终Object.prototype.__proto__
指向了null
,标志着原型链的结束。因此,[]
、Array
、Object
就在内部形成了一条原型链。
因此 instanceof
只能用来判断两个对象是否属于实例关系, 而不能判断一个对象实例具体属于哪种类型。
所以判断一个对象是数组类,可以使用
1 | functin isArray(obj){ |
3. 有个万能的判断数据类型的方法就是使用 Object.prototype.toString.call()
1 | Object.prototype.toString.call(null) |
js中的深浅拷贝
1.浅拷贝
1.1. 简单的引用复制
1 | // 浅拷贝实现 |
1.2. Object.assign()
Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。
1 | const test = {a: 1, b: 2, c:[1,2,3]} |
1.3. Array的slice和concat方法
类似于第一种情况,具体的拷贝规则如下:
如果该元素是个对象引用 (不是实际的对象),slice 会拷贝这个对象引用到新的数组里。两个对象引用都引用了同一个对象。如果被引用的对象发生改变,则新的和原来的数组中的这个元素也会发生改变。
对于字符串、数字及布尔值来说(不是 String、Number 或者 Boolean 对象),slice 会拷贝这些值到新的数组里。在别的数组里修改这些字符串或数字或是布尔值,将不会影响另一个数组。
2.深拷贝
2.1. JSON对象的parse和stringify
JSON对象parse方法可以将JSON字符串反序列化成JS对象,stringify方法可以将JS对象序列化成JSON字符串,借助这两个方法,也可以实现对象的深拷贝。
这种方法使用较为简单,可以满足基本的深拷贝需求,而且能够处理JSON格式能表示的所有数据类型,但是对于正则表达式类型、函数类型等无法进行深拷贝(而且会直接丢失相应的值)。还有一点不好的地方是它会抛弃对象的constructor。也就是深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成Object。同时如果对象中存在循环引用的情况也无法正确处理。
2.2. 借助lodash.js 中的方法实现深拷贝 _.cloneDeep(value)
2.3. 实现深拷贝
1 | function clone(obj) { |