变量类型和计算
typeof能判断哪些类型
typeof 对于原始类型来说,除了 null 都可以显示正确的类型
typeof 1 // 'number'
typeof '1' // 'string'
typeof undefined // 'undefined'
typeof true // 'boolean'
typeof Symbol() // 'symbol'
typeof 对于对象来说,除了函数都会显示 object,所以说 typeof 并不能准确判断变量到底是什么类型
typeof function(){} // 'function'
type null //'object'
typeof [] // 'object'
typeof {} // 'object'
使用=和
- ===严格相等运算符,比较过程没有类型转换。
- 允许类型转换。1*1’ true,而===不会
值类型和引用类型的区别
-
值类型
占用空间固定,保存在栈中(当一个方法执行时,每个方法都会建立自己的内存栈,在这个方法内定义的变量将会逐个放入这块栈内存里,随着方法的执行结束,这个方法的内存栈也将自然销毁了。
因此,所有在方法中定义的变量都是放在栈内存中的;栈中存储的是基础变量以及一些对象的引用变量, 基础变量的值是存储在栈中 ,而引用变量存储在栈中的是 指向堆中的数组或者对象的地址 ,这就是为何修改引用类型总会影响到其他指向这个地址的引用变量。) -
保存与复制的是值本身
-
使用typeof检测数据的类型
-
基本类型数据是值类型
-
引用类型
占用空间不固定,保存在堆中(当我们在程序中创建一个对象时,这个对象将被保存到运行时数据区中,以便反复利用(因为对象的创建成本通常较大),这个运行时数据区就是堆内存。
堆内存中的对象不会随方法的结束而销毁,即使方法结束后,这个对象还可能被另一个引用变量所引用(方法的参数传递时很常见),则这个对象 依然不会被销毁 ,只有当一个对象没有任何引用变量引用它时,系统的垃圾回收机制才会在核实的时候回收它。) -
保存与复制的是指向对象的一个指针
-
使用instanceof检测数据类型
-
使用new()方法构造出的对象是引用型
手写深拷贝
深拷贝
深拷贝复制变量值,对于非基本类型的变量,递归至基本类型后再复制。深拷贝后的对象与原来的对象完全隔离,互不影响。
使用JSON、递归函数进行深拷贝
使用扩展运算符深拷贝(适合用于内层结构都是基本类型的数组或对象)
let arr = [1,2,{name:'user'}]
//在对象原型上添加一个深拷贝的方法
Object.prototype.copy = function(data){
//如果不是对象类型返回本身
if(typeof(data) !='object'){
return data
}else{
//如果是数组类型创建数组,否则创建对象
let deepData = data instanceof Array?[]:{}
//循环拷贝
for(let key in data){
//如果循环项是对象再次调用深拷贝方法进行深拷贝,否则直接赋值
if(typeof(data[key]) == 'object'){
deepData[key] = copy(data[key])
}else{
deepData[key] = data[key]
}
return deepData
}
}
let newArr = copy(arr)
类型转换
- 字符串拼接
+运算符只要有一遍是字符串就会进行隐式转换 - ==
==运算符比较的时候会进行类型转换,只比较值,不比较数据类型
//除了==nul之外,建议一律用===
constObject= {a:100}
if(obj.b ==null){}
//相当于:
if(obj.a ===null || obj.a ===undefined){}
if语句和逻辑运算
//以下是falsely变量,除此之外都是truely变量
!!0 === false
!!NaN === false
!!'' === false
!!null ===false
!!undefined === false
!!false === false