JS变量可以包含两种不同类型的数据:原始值和引用值。原始值就是最简单的数据类型,即:undefined、Null、Boolean、Number、String、Symbol。引用值则是由多个值构成的对象。JS不允许直接访问内存位置,所以不能直接操作对象所在的内存空间。
动态属性:
原始值和引用值定义的方式很类似,都是创建一个变量然后对其赋值。但是变量保存了这个值之后,可以对这个值做什么就大不相同了。对于引用值而言,可以随时进行增删改查。
原始值不能有属性,但是给原始值添加属性不会报错。
let a = "pack" a.age = 27 console.log(a.name) / undefined
引用值可以添加属性,在使用new关键字的时候,JS会创建一个Object类型的实例
let a = new Object() a.name = "pack" console.log(a.name) / 27
复制值:
① 除了储存方式不同,原始值和引用值在通过变量复制时也有所不同。在通过变量把一个原始值复制到一个新的变量时,原始值会被复制到新变量的位置。
let num = 5 ; let num2 = num1 此时num和num2的两个5,是完全独立的。这两个变量都可以独立使用,互不干扰。
② 在把引用值从一个变量赋值给另一个变量时,这里复制的其实是一个指针,因为引用值是在堆内存中开辟一个空间,变量在栈内存中,它指向存储在堆内存中的对象。
let obj1 = new Object();let obj2 = obj1 ;
obj1.name = "jack" ; console.log(obj2.name) / jack 在这个例子中,obj1保存了一个新对象的实例,然后这个值被复制到了obj2 ,但是此时两个变量都指向了一个对象,在给obj1添加name属性的时候,obj2也可以访问到这个属性。因为他们都指向了一个对象。
传递参数:
js中所有函数的参数都是按值传递的,这表示函数外的值会被复制到函数内部的参数中,就像从一个变量复制到另一个变量一样。如果是原始值那就跟原始值的复制一样,如果是引用值,那就跟引用值的复制一样。
function add(num) { num += 10 ; return num } ; let count = 20;
let result = add(count) ; console.log(result , count) / 30 , 20这里函数add有一个参数num 这里把count变量传递进去,那么就相当于num复制了count变量的值,此时num和count就互不干扰,所以在函数中改变了num的值,count的值也不会改变。
function add(obj) {
obj.name = "jack"
}
let person = new Object()
add(person)
console.log(person.name) //"jack"
这次我们创建一个对象并把它保存在变量person中,然后调用add()这时person变量保存的地址,就会复制给obj,当在函数内改变obj的属性时,在函数外部的person变量也会反映这个变化。因为obj变量保存的对象保存在全局变量的堆内存中。而obj和person都指向这个对象。
确定类型:
typeof操作符最适合检测一个变量是否为原始值,但是我们通常不关心这个值是不是对象,而是想知道它是什么类型的对象。JS提供了instanceof操作符。
console.log(person instanceof Object) // person是Object数据类型吗?
console.log(person instanceof Object) // person是Object数据类型吗?
console.log(pattern instanceof RegExp) // pattern是RegExp数据类型吗?