前言
由于js 属于弱类型的语言,按照ECMA-262的定义,js的变量与其他变量有很大的区别,其中包括了不存在定义哪一种变量必须要保存哪一种数值类型,比如,在java语言规范中字符串类型的数值必须显式的声明为String类型,而在js中统一使用var声明,在ES6中提供了let,const进行变量声明
javaScript定义两种不同类型的变量:基本数值类型 和 引用数值类型 ,基本数值类型是指简单的数据段,而引用数据类型是指那些可能由多个值构成的对象
栗子
在js规范中,有五种基本数值类型,分别是Undefined,Null,Boolean,Number和String,这 5种基本数据类型是按值访问 的,因为可以操作保存在变量中的实际的值。
引用类型一般是一个保存在内存中的对象,按照约定,js不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间,所以我们在操作对象时实际是在操作对象的引用,而不是实际对象(引用类型的值是按引用来访问的)
动态属性
定义一个基本类型和引用类型的方式是类似的,都是创建一个变量并为他赋值,但是当这个值保存之后,对于不同类型的值可以执行的操作就是不一样的了 对于引用类型,我们可以为他动态的添加属性或者方法,下面输入这段话去IDE,你也可以和我一样F12使用谷歌的控制台输入
var person = new Object();
person.name='谭婧杰';
console.log(person.name)
是的,不难看出,上述代码中我们创建了一个object对象并将他保存在了person中,这个名为name的属性创建之初本来是不存在的,我们通过对象名.属性名的方法动态的给它创建的属性name,并且为他赋值,如果这一个对象不被销毁或者删除,这个属性会一直存在,但是对于基本类型来说,我们不能给基本类型添加属性,,给基本类型添加属性是毫无意义的,在下一次访问,这个属性会变为Undefined,以数值为例
var a = 12.3;
console.log(a.toFixed(3)); # 输出"12.300"
a.foo = 'bar';
console.log(a.foo);# 输出undefined
变量与变量之间的复制拷贝
除了上述动态的保存之外,变量与变量之间的复制,拷贝也是不一样的 对于基本类型来说,一般会在变量对象上创建一个新值,然后把这个值复制到为新变量分配的类型上面
注意这两个值是不会相互影响的,他们都是独立存在的
例如,上面的例子中我改变num2的值,num1的值仍然是10
对于引用类型来说,也会将存储在变量对象的值复制一份到新变量的内存空间中,但是这个值的副本其实是一个指针,这个指针指向我们被赋值的对象,即不管怎么样,引用类型的赋值其实都是引用的同一个对象
忽略中间小小的意外之后,可以看出我并没有操作jack变量,但是它却随着tom的改变而改变
函数里的参数传递
ECMAScript中所有的函数都是按值传递的,在传递基本类型变量时,被传递的值会复制到一个arguments对象中的一个元素,传递引用类型的值时,复制的是它内存中的地址,输入
function addTen(num) {
num += 10;
return num;
}
var count = 20;
var res = addTen(count);
alert(count); # 20 没有任何变化
alert(res) # 30
当我们把基本类型换成为对象引用类型
function setName(obj) { obj.name = "Nicholas"; }
var person = new Object(); setName(person); alert(person.name); # "Nicholas"
上述代码中obj和person其实是引用的同一个对象,person指向的代码在堆中只存在一个(全局对象),即使变量obj是按值传递的,obj也会按照引用来访问同一个对象
ps:函数内部重写 obj 时,这 个变量引用的就是一个局部对象。而这个局部对象会在函数执行完毕后立即被销毁
最后
检查一个变量是否是基本类型可以使用typeOf,但是对于引用类型typeof会统一返回一个Object,因为所有的引用类型都应该是Object的实例,兵来将挡水来土掩,那么引用类型怎么办,这时候我们就可以使用instanceof了,instanceof 叫英文解释实例,如person instanceof Object, 变量 person 是 Object 吗? 如果是返回true