JavaScript中的基本类型和引用类型
JS中包含两种不同的数据的类型----基本类型和引用类型。基本类型值的是简单的数据段,引用类型指的是可能由多个值构成的对象。
在将值赋值给一个变量的时候,解析器必须确定这个值是基本类型还是引用类型。
我们常见的五种基本的数据类型Undefined,Null, Boolean,Number,String,这五种数据类型是按照值来进行访问的,因为可以操作保存在变量中的实际的值。
引用类型的值是保存在内存的对象。与其他语言不同的是,JS不允许直接访问内存中的位置,也就是说不能够直接操作对象的内存空间。在操作对象的时候,实际上是在操作对象的引用而不是在操作实际的对象。为此,引用类型的值,是按照引用访问的。
注意: 在很多的语言中,字符串是以对象的形式来表示的,因此会被认为是一个引用类型,但是ECMAScript放弃了这一个传统。
动态属性
定义基本类型和引用类型的方式是类似的:创建一个变量并为这个变量进行赋值。但是当这个值保存到变量中去之后,对不用类型的值可以采用之行的操作是大相庭径的,我们可以为其添加属性和方法,也可以改变和删除其属性和方法。
var person = new Object();
person.name = 'Kevin';
console.log(person.name)
但是我们不能够给基本类型添加属性。就算添加属性的话也是undefined。
复制变量值
除了保存的方式不同之外,从一个变量向另一个变量复制基本类型的值和引用类型的值都会不同。简单的来说,基本类型中的值被赋值之后是是相对独立的单独的个体,但是引用类型被复制会后是同一个个体,这是因为应用类型被赋值的是引用的地址,这些地址指向的是同一个对象。
基本类型的数据保存在 栈内存 中,但是引用类型的值被保存在 堆内存 中。
var num1 = 1;
var num2 = num1;
num1++;
console.log('num1--->',num1);//num1---> 2
console.log('num2--->',num2);//num2---> 1
var objA = new Object();
var objB = objA;
objA.name = 'David';
console.log('objA.name--->',objA.name);//objA.name---> David
console.log('objB.name--->',objB.name);//objB.name---> David
传递参数
ECMAScript中所有函数的参数都是按值传递的。 why ?
在向参数传递基本类型的值的时候,被传递的值会被复制给一个局部变量(即命名参数,就是arguments对象中的一个元素)。在向参数传递引用类型的值的时候,会把这个值存在内存中的地址赋值给一个局部变量,因此这个局部变量的变化会反映在函数的外部。
function addTen(num){
num += 10;
return num ;
}
var count = 20;
var result = addTen(count);
console.log(count);//20
console.log(result);//30
这里的函数有一个参数num,而参数实际上是函数的局部变量。在调用这个函数的时候,变量count作为参数被传递给了函数,这个变量的值被加上了10,但是这一变化不会影响函数外部的count的变化吗。这正好就说明了一点,ECMAScript中参数都是按值传递的。
再来看这个例子:
function setName(obj){
obj.name = 'David';
var obj = new Object();
obj.name = 'Kevin';
}
var person = new Object();
setName(person);
console.log(person.name)
这里如果person是按照引用传递的,那么person就会自动被修改指向其name 属性值为‘Kevin’的新对象,但是接下来访问person.name的时候,显示的仍然是“David”。这就说明即是在函数的内部修改了参数的值,但是原始的引用仍然保持为改变。
【重点来了====》】实际上,当在函数内部重写obj的时候,这个变量引用的就是一个局部对象了。而这个局部对象会在函数执行完毕之后立即被销毁。所以也可以把ECMAScript函数的参数想象成局部变量。
检测类型
要检测一个变量是不是一个基本的数据类型? 使用typeof 是最佳的选择,这个工具可以确定一个变量是字符串,数值、布尔值还是undefined,如果变量的值是一个对象或者null,那么typeof的返回值是object。
但是,通常来讲我们并不是想知道某个值是一个对象,饿哦们想知道他是一个什么样的对象。所以在ECMAScript当中提供了一个instanceof操作符。
var person = new Object();
var color = new Array();
var pattern = new RegExp();
console.log(person instanceof Object);//true 'person 是 Object对象吗?'
console.log(color instanceof Array);//true 'color 是 Array对象吗?'
console.log(pattern instanceof RegExp);//true 'pattern 是 RegExp 对象吗?'
根据规定,所有的引用类型的值都是Object的实例。因此,在检测一个引用类型值和Object 构造函数时,instanceof操作符始终会返回true。当然,如果使用instanceof检测基本类型的值,则该操作符始终会返回false,因为基本类型不是对象。