JS类型详论
本文主旨: 极尽一切可能的,详细介绍js类型相关内容
主要数据类型两类
- 基本类型: 变量存储值
数字、布尔、undefined、null、字符串、Symbol - 引用类型:变量存储地址,类似于c语言中的指针
函数、数组、对象
判断数据类型
typeof: 能够判断除了null和数组的所有数据类型
console.log(typeof 'a') console.log(typeof true) console.log(typeof Symbol()) console.log(typeof undefined) console.log(typeof null) console.log(typeof {}) console.log(typeof function() {}) console.log(typeof []) // 结果 string boolean symbol undefined object object function objectinstanceof: 实话讲,该方法用的并不多,因为他明显没有typeof用的舒服,且他并不是用来做类型判断的。判断一个对象是否为另一个构造函数的实例。那么因为数组既是对象类型也是数组类型,因此,下面代码均会返回true
console.log(a instanceof Object) console.log(a instanceof Array)constructor: 判断变量的构造器
console.log('a'.constructor) console.log(true.constructor) console.log(Symbol().constructor) // console.log(undefined.constructor) // console.log(null.constructor) console.log({}.constructor) console.log(function() {}.constructor) console.log([].constructor) // 结果 [Function: String] [Function: Boolean] [Function: Symbol] [Function: Object] [Function: Function] [Function: Array] //打印出来等同于 Array 除了undefined和null没有constructor,其他均打印出了各自的原型对象,包括数组。Object.prototype.toString.call: 该方法最为彻底。能够打印变量的真实原型对象
console.log(Object.prototype.toString.call('123')) console.log(Object.prototype.toString.call(123)) console.log(Object.prototype.toString.call(true)) console.log(Object.prototype.toString.call(undefined)) console.log(Object.prototype.toString.call(null)) console.log(Object.prototype.toString.call(Symbol(123))) console.log(Object.prototype.toString.call(function() {})) console.log(Object.prototype.toString.call([1, 2, 3, 4])) console.log(Object.prototype.toString.call({})) // 结果 [object String] [object Number] [object Boolean] [object Undefined] [object Null] [object Symbol] [object Function] [object Array] [object Object]总结:typeof最为便捷,若要判断数组,可以用constructor、tostring和Array.isArray(item)、instance方法。关于null,可以使用if(typeof x !== undefined && !x)结合判断。
事实上上面我们列举的九种数据类型并不是全部。比如还有类数组(能够像数组哪像通过下标获取值,也有length就是没有数组的那些api),NaN(一种不知道为何存在的值, (NaN === NaN) 输出false)等。同时还有与ts的强类型加持,还有什么any、never等等等。
以为精通了数据类型?来小试牛刀一下:
let x = '123' console.log(x instanceof String)猜一猜输出会是啥?
答案是false。原因我们之前说过,instanceof方法是用来判断一个对象是否为另一个构造函数的实例。那么此处怎么让他输出true呢?很简单:
let x = new String(‘123’)js中值为false的情况:
数字0、false、undefined、null、NaN和空字符串’’。注意是空字符串,哪怕多一个空格字符都不行。console.log(‘3’ + 3)的输出是啥?
‘33’。js会默认将数字3转换成字符串。又觉得自己很懂了?再来看一个例子:
// jsone.js import { change } from './jstwo' let obj = { name: 'hhvcg' } change(obj) console.log('obj:', obj) // jstwo.js const change = (obj) => { obj.name = 'chnaged' return 1 } export { change } // 输出: obj: {name: 'chnaged'}有没有被无语到。。。。。。
事实上,通过本文上面的知识,这种情况我们已经能够解释,因为obj是一个对象,可以看成是指针,把这个对象通过参数传递出去,在change中做的改变就是改变的原来的obj,因为不管change定义的参数名是啥,他都是跟obj一样的指针,指向的是同一个数据。
但是,我必须说但是,这种骚操作,实在让我暂时无法接受。我想,学过c/c++或者其他主流语言的同学,看到这一幕,可能会一脸懵逼吧。。。这个东西类似于c语言中的指针,但是,也太随便了。
- map和对象
// 对象示例
const obj = {
name: "Alice",
age: 30
};
// Map示例
const map = new Map();
map.set("name", "Alice");
map.set("age", 30);
map.set({}, "这是一个对象作为键"); // 合法
表现形式都是一个对象,有稍微的区别。map的键可以是任意类型,甚至是‘{}’,对象则只能是字符串/Symbol
- 最后一点补充: 对象的属性值判断方法。
in和hasOwnProperty都可以用来判断一个属性是否在对象中存在但是,前者能够判断自有属性和原型属性,而后者,只专注于自有属性。所以,hasOwnProperty更加的专业。自行测试下面代码。
const obj = {
name: 'dddd'
}
console.log(obj.hasOwnProperty('constructor'))
console.log('constructor' in obj)
js的深拷贝与浅拷贝
这个话题是因为引用类型触发的。所谓深拷贝,就是完全复制,而浅拷贝,是创建一个新的对象或者数组,新对象或者新数组与原对象或者数组的引用相同。
直接上代码:
const obj = {
a: 100,
b: {
x: 1000
},
c: [1,2,3,4]
}
// 浅拷贝
// 方1 扩展运算符号
const obj2 = {
...obj
}
obj2.b.x = 10
console.log(obj)
{ a: 100, b: { x: 10 }, c: [ 1, 2, 3, 4 ] }
// 方2
const shallowCopy = Object.assign({}, originalObject);
// 深拷贝
const deepClone = (obj) => {
const res = {}
for (let key in obj) {
if (!obj.hasOwnProperty(key)) continue
// 还有Date、正则等特殊类型
if (Array.isArray(obj[key])) {
res[key] = obj[key].map((item) => {
if (typeof item === 'object') {
if (!obj[key]) {
return null
} else {
return deepClone(item)
}
} else {
return item
}
})
} else if (typeof obj[key] === 'object') {
if (!obj[key]) {
res[key] = null
} else {
res[key] = deepClone(obj[key])
}
} else {
res[key] = obj[key]
}
}
return res
}
const res = deepClone(obj)
res.c[0] = 222222222222222222
console.log('res',res)
console.log(obj)
// res {
// a: 100,
// b: { x: 222222222222222200 },
// c: { '0': 1, '1': 2, '2': 3, '3': 4 }
// }
// { a: 100, b: { x: 1000 }, c: [ 1, 2, 3, 4 ] }
当然,最最简单粗暴的深拷贝:JSON的序列化反序列化大法。
