1.变量类型
- 值类型:number,boolean,string,undefined,Symbol
- 引用类型:Object和它的子类型例如Array,Set,Map等等
- 特殊的引用类型:null,Function
2.不同类型对象存储方式
值类型的数据是存储在栈内存中,引用类型是存储在堆内存中。
例如:
值类型:let a = 100
在内存中大概就是这样:
如果:let b = a
那么就是这样:
如果:a = 200
那么就是这样:
所以此时:a === 200,b === 100
引用类型:let a = {age:20}
在内存中大概就是这样:
如果:let b = a
那么就是这样:
如果:a.age = 21
那么就是这样:
所以此时:b.age === 21,a === b
3.判断类型的方法
- typeof
判断值类型时,用typeof基本没有什么问题,如果判断引用类型,特殊引用类型Function会返回"function",null返回"object",其他普通引用类型都会返回’object’,因为普通引用类型的对象的原型链最终都会指向Object - instanceof
例如a instanceof B可以用来判断对象a是不是类型B的实例,返回true或者false。准确来说应该是判断"对象a的原型对象"和"类型B的原型对象"是否在同一条原型链上,如果是就会返回true,所以instance不能准确判断对象的具体类型 - constructor
当声明一个函数时,js会自动在这个函数的原型对象加上一个constructor属性并指向自己
function People(name){
this.name = name
}
People.prototype.constructor === People //true
当使用这个函数实例化对象时,这个对象的原型对象又指到这个函数的原型对象
const tony = new People('tony')
tony.__proto__ === People.prototype //true
利用这个特点就可以具体判断对象具体的类型
tony.__proto__.constructor === People //true
tony.__proto__.constructor === Object //false
//当tony.hasOwnProperty('constructor')为false的时候也可以直接这样写
tony.constructor === People //true
tony.constructor === Object //false
但是******但是******但是
如果函数原型对象被修改了,那么这个方法就有可能用不了了
比如:
const newPrototype = {a:1}
People.prototype = newPrototype
const lee = new People('lee')
//此时lee.__proto__ === newPrototype
//而newPrototype.__proto__ === Object.prototype
//因为Object.prototype.constructor === Object
//所以
lee.constructor === People //false
lee.constructor === Object //true
- Object.prototype.toString()
TODO
4.拷贝对象
对象拷贝主要针对引用类型
深拷贝方法
function deepClone(obj){
if(obj == null || typeof(obj) !== 'object'){
return obj
}
let r
if(obj instanceof Array){
r = []
}else{
r = {}
}
for(let key in obj){
//防止复制到原型对象的属性
if(obj.hasOwnProperty(key)){
r[key] = deepClone(obj[key])
}
}
return r
}