小知识,大挑战!本文正在参与“ 程序员必备小知识 ”创作活动
本文同时参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金
分类
基础类型
存储在栈内存,被引用或拷贝时,会创建一个完全相等的变量
- Undefined
- Null
- Boolean
- String
- Number
- Symbol
- BigInt
引用类型(共享)
存储在堆内存,存储的是地址,多个引用指向同一个地址
-
Object
- Array
- RegExp
- Date
- Math
- Function
类型检测
typeof
-
基础类型
- 除了null返回'object',其他返回相应类型
-
引用类型
- 除了function会返回"function",其他都是'object'
instanceof
-
基础类型
- 无法判断
-
引用类型
- 可以准确判断
Object.prototype.toString.call()
- 返回格式为"[Object Xxx]"
类型转换
强制转换
-
Number()
-
布尔值
- true=>1
- false=>0
-
数值
- 自身
-
null
- 0
-
undefined
- NaN
-
字符串
-
数字
数字或者是 0X / 0x 开头的十六进制数字字符串,允许包含正负号
- 十进制
-
有效的浮点格式
- 浮点数值
-
空字符串
- 0
-
其他
- NaN
-
-
Symbol
- 抛出错误
-
Object
- 下面细讲
-
-
parseInt()
-
parseFloat()
-
toString()
-
String()
-
Boolean()
-
undefined、 null、 false、 ''、 0(包括 +0,-0)、 NaN
- false
-
其他
- true
-
隐式转换
-
==
-
类型相同
- 不用转换
-
null == undefined为true,其他都是false
-
?== Symbol
- false
-
string和number相比
- 字符串转number
-
与boolean相比
- 转成number
-
object与(string、number 或者 symbol)
- object转基本类型
-
-
-
与字符串相加,另一数值调用toString() ; 与数字相加,另-是调用Number();与对象相加,则要将对象转基本类型
-
数字+数字
- 加法
-
字符串+字符串
- 字符串拼接
-
字符串+(undefined/null/布尔型/数字)
'1' + 3 => '13'
- 调用toString()拼接
-
(字符串/数字)+(纯对象/数组/正则等)
- 对象转基本类型再拼接
-
数字+(undefined/null/布尔型/数字)
- 转成数字(Number())再加法
-
-
对象转换
-
语法
- Symbol.toPrimitive
- valueOf(),为基础类型才返回
- toString(),为基础类型才返回
- 都不是基础类型,报错
-
示例
-
[] + []
- “”
- [].valueOf()非基础类型,toString()是空字符串,相当于""+""
-
[] + {}
- '[object Object]'
- {}.valueOf()非基础类型, toString()是'[object Object]'
-
{} + {}
- NaN
- 第一个{}被js引擎解释成空的代码块并忽略,所以相当于+{}=>Number({})=>Number({}.toString())=>Number(['object Object'])=>NaN
-
({}+{})
- '[object Object][object Object]'
- 加上括号就变成表达式,而非代码块
-
{} + []
- 0
- 第一个{}被js引擎解释成空的代码块并忽略,所以相当于+[]=>Number([])=>Number({}.toString())=>Number('')=>0
-
10+{}
- 10['object Object']
-
{}+10
- 10
- {}被当作空代码块忽略
-
模拟实现浅拷贝
- 对基础类型做一个最基本的一个拷贝;
- 对引用类型开辟一个新的存储,并且拷贝一层对象属性。
const shallowClone = (target) => {
if (typeof target === 'object' && target !== null) {
const cloneTarget = Array.isArray(target) ? [] : {}
for (let prop in target) {
if (target.hasOwnProperty(prop)) {
cloneTarget[prop] = target[prop]
}
}
return cloneTarget
} else {
return target
}
}
// 1.基础类型
let v1 = 'string1'
let v2 = shallowClone(v1)
v2 = 'string2'
console.info('v1:', v1) // v1: string1
console.info('v2:', v2) //v2: string2
// 2.引用类型,属性值为基础类型的不会互相影响,为引用类型的就会
const obj = { a: 2, d: { name: '张三' } }
const newObj = shallowClone(obj)
newObj.a = 33
newObj.d.name = '李四'
console.info(JSON.stringify(newObj), 'newObj')
// {"a":33,"d":{"name":"李四"}} newObj
console.info(JSON.stringify(obj), 'obj')
// {"a":2,"d":{"name":"李四"}} obj
JSON.stringify实现深拷贝存在问题
function Obj() {
this.func = function () {
alert(1)
} //消失
this.und = undefined //消失
this.sym = Symbol(1) // 消失
this.obj = { a: 1 }
this.arr = [1, 2, 3]
this.reg = /123/ //{}
this.date = new Date(0) //字符串
this.NaN = NaN // null
this.infinity = Infinity // null
}
let obj1 = new Obj()
Object.defineProperty(obj1, 'innumerable', {
enumerable: false,
value: 'innumerable'
}) //会消失
console.log('原obj1', obj1)
console.log('obj1', JSON.stringify(obj1))
let str = JSON.stringify(obj1)
let obj2 = JSON.parse(str)
console.log('obj2', JSON.stringify(obj2))
手写递归实现深拷贝
function deepClone(target) {
let cloneObj = {}
for (let key in target) {
if (typeof target[key] == 'object') {
cloneObj[key] = deepClone(target[key]) //递归
} else {
cloneObj[key] = target[key]
}
}
return cloneObj
}
// let obj1 = {
// a: 2
// }
// let obj2 = deepClone(obj1)
// obj2.a = 55
// console.info('obj2:', obj2) // {a:55}
// console.info('obj1:', obj1) // {a:2}
// let newObj1 = {
// a: { b: 22 }
// }
// let newObj2 = deepClone(newObj1)
// newObj2.a.b = 55
// console.info('newObj2:', newObj2) // { a: { b: 55 } }
// console.info('newObj1:', newObj1) // { a: { b: 22 } }
// 对各种属性类型做验证
// let newObj1 = {
// a: { b: 22 },
// fun1: function () {
// //函数可以拷贝
// console.info(22)
// },
// und: undefined, // undefined的正常
// sym: Symbol(2), // symbol正常
// date: new Date(), //变成字符串
// reg: new RegExp(/\s+/), //变成空对象
// nan: NaN, // 正常
// inf: Infinity // 正常
// }
// Object.defineProperty(newObj1, 'enumeration', {
// enumerable: false, // 不可枚举的属性拷贝不了
// value: '枚举'
// })
// let newObj2 = deepClone(newObj1)
// newObj2.a.b = 55
// console.info('newObj2:', newObj2) // { a: { b: 55 } }
// console.info('newObj1:', newObj1) // { a: { b: 22 } }
let arr1 = [1, 2, 3]
let arr2 = deepClone(arr1) //返回的是{0: 1, 1: 2, 2: 3}
arr2.push(33) //因为是非数组对象,所以报错
console.info(arr1, arr2)