在javascript规范中,定义了七种数据类型,分为值类型
和引用类型
两大类.
保存在栈中,占用空间固定,使用后被销毁
当一个方法执行时,每个方法都会建立自己的内存栈,在这个方法内定义的变量将会逐个放入这块栈内存里,随着方法的执行结束,这个方法的内存栈也将自然销毁了,因此,所有在方法中定义的变量都是放在栈内存中的
注意: 栈中存储的是一些基础变量和对象的引用变量,基础变量的值是存储在栈中,而引用变量存储在栈中的是指向堆中的数组/对象的地址
基本类型的值不可变
let name = 'Aley'
name.toLowerCase() // aley
console.log(name) // Aley
保存与复制的是值本身
使用typeof检测数据类型
typeof识别所有值类型以及函数, 判断是否是引用类型
let a
typeof a // undefined
typeof '123' // string
typeof 123 // number
typeof true // boolean
typeof Symbol() // symbol
typeof null // object
typeof function() {
} // function
typeof console.log // function
// 用typeof识别引用类型返回的都是 object, 除了函数
typeof [] // object
typeof {
} // object
引用类型可以说就是对象,对象是属性和方法的集合。也就是说引用类型可以拥有属性和方法,属性又可以包含基本类型和引用类型
保存在堆中,占用空间不固定,使用后不一定被销毁,只有一个对象没有任何引用时,系统的垃圾回收机制才会回收销毁
使用instanceof检测数据类型
如果变量是给定引用类型(根据它的原型链来识别)的实例,那么instanceof 操作符就会返回 true
let obj = {
}
obj instanceof Array // false
obj instanceof Object // true
// 发现数组用instanceof不好区分
[] instanceof Array // true
[] instanceof Object // true
// 检测数组
Array.isArray([])
或者
if (!Array.isArray) {
Array.isArray = function(arg) {
return Object.prototype.toString.call(arg) === '[object Array]';
}
}
使用new()方法构造出的对象是引用型
字符串拼接
字符串转数值: ‘100’ * 1
数值转字符串: 100 + ‘’
let a = 100 + 10 // 110
注: ''不要写成' ',否则 字符串长度会加1
let b = 100 + '' // '100'
let c = '100' * 1 // 100
typeof c // number
==(不考虑变量类型) 和 ===(考虑变量类型)
除了== null之外,其他一律用 ===
100 == '100' //true
100 === '100' //false
0 == '' //true
null == undefined //true
const obj = {
x: 100}
if (obj.a == null) {
} 相当于 if (obj.a === null && obj.a === undefined) {
}
if语句
let a = true
if(a){
}
let b = 100
if(b){
} // 把数字转换为true
let c = ''
if(c){
} // 把空字符串转换为false
逻辑运算
除 0, ’ ', false, NaN, null, undefined是falsely变量,其余都是truely变量
console.log(10&&0); // 0 把10转换成true
console.log('' || 'abc'); // 'abc' 把空字符串转换为false
console.log(!window.abc); //true window.abc是undefined 把非undefined转换成true
//判断一个变量会被当做true还是false
let a = 100
console.log(!!a); // true
浅拷贝(shallowCopy):增加了一个指针指向已存在的内存地址,如果原地址发生改变,那么浅复制出来的对象也会相应的改变
Object.assign() :Object.assign()拷贝的是属性值,.如果对象的属性值为值类型,通过Object.assign({},srcObj),得到的新对象为深拷贝;如果属性值为引用类型,那对于这个对象而言其实是浅拷贝的;
Array.from() 方法从一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例
函数:
function shallowCopy(obj) {
if(typeof obj !== 'object'){
return obj
}
let newObj = Array.isArray(obj) ? [] : {
}
for(let key in obj) {
if(obj.hasOwnProperty(key)){
newObj[key] = obj[key]
}
}
return newObj
}
let obj = {
age: 19,
name: 'aley',
address: ['昆明', '建水']
}
let newobj = shallowCopy(obj)
obj.address[0] = 'uu'
obj2.address[0] // 'uu'
深拷贝(deepCopy): 增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的内存, 如果原对象的值改变,深拷贝的值不会改变
JSON.parse()和JSON.stringify():
function deepCopy(obj) {
let _obj = JSON.stringify(obj);
let objClone = JSON.parse(_obj);
return objClone;
};
let arr = [1,2,3],
_arr = deepCopy(arr);
arr[0] = 2;
console.log(arr,_arr)//[2,2,3] [1,2,3]
递归函数:
function deepCopy(target, obj) {
if(!obj) return
// 不是对象直接返回
if(typeof obj !== 'object'){
return obj
}
let ret = target || []
for (let key in obj) {
// 属性的值为对象,递归
if (obj[key] instanceof Object){
ret[key] = obj[key].constructor=== Array ? []: {
}
deepCopy(ret[key], obj[key])
} else {
ret[key] = obj[key]
}
}
return ret
}
let obj = {
age: 19,
name: 'aley',
address: ['昆明', '建水']
}
let newobj = deepCopy({
}, obj)
console.log(newobj)