所谓引用类型,在ECMAScript中表示一种数据结构,其中有一些数据和方法,在其他语言中大多被称为类,但是在这里我们一般不这样称呼。即使ECMAScript是一门面向对象语言,但是它不具备传统面向对象语言中所支持的类和接口。他们描述的是一类对象所具有的属性和方法。引用类型的值就是一个对象,它是引用类型的一个实例。 新对象是用一个new操作符后面跟上一个构造函数创建的。所谓构造函数本质上是一个函数,这个函数的目的是为了创建某一类对象,函数中包含了创建该对象所需要的东西。 ECMAScript中提供其他各种类型的引用类型。
JavaScript 中的变量与其他语言的变量有很大差别,独特的松散类型的特性,决定了它只是特定时间用来保存特定值的一个名字而已。它的数据类型在生命周期中是可以随时改变的。Crazy and Powerful !
在一个变量中可能存在两种不同数据类型的值:基本类型值和引用类型值。基本类型值是按值引用的,我们可以操作保存在变量中实际的值。但是引用类型就不同了,引用类型的值是保存在内存中的对象,而JavaScript是不允许直接操作内存空间的。所以说我们在操作对象的时候操作的是对象的引用而不是实际的对象。所以对象是按引用访问的。
引用类型具有动态的属性
两种类型在定义的时候是相似的,创建一个变量并且为它赋值。但是引用类型允许我们更改其属性和方法,而基本类型值没有这个功能。当我们为基本类型值增添属性后虽然不会报错,但是却是无效的。
变量值的复制
对于基本类型值来说,从一个变量复制给另一个变量的时候,会在新的变量上创建一个新值,然后把值复制过去。从此这两个值就没了联系,不会相互影响了。但如果是从一个变量向另一个变量复制引用类型的值的时候,复制过去的其实是一个指针,指向存在堆中的一个对象,然后两个变量引用同一个对象,改变一个,会影响另一个:
let obj1 = new Object(); let obj2 = obj1; obj1.name = 'Baoyuan'; console.log(obj2.name); //'Baoyuan'
参数的传递
ECMAScript 中所有函数的参数都是按值传递的。
向函数传递基本类型的值的时候,被传递的值被复制给命名参数。而对于引用类型来说,会把这个值在内存中的地址复制给命名参数,这会导致函数内值的改变反应在函数外部:
function setName (obj) { obj.name = 'Baoyuan'; }; let people = new Object(); setName(people); // 将people对象地址复制给了函数内部的obj,也就是说引用同一个对象。 console.log(people.name); //'Baoyuan'
即使这个对象是按值传递的,因为 people 指向的对象在堆内存中只有一个, obj 会按引用来访问同一个对象。
我们先来看最常见用的最多的一种-Object。
Object是典型的引用类型值,虽然它的实例中并不具备很多功能,但是大多数我们所见的引用类型值都是他的实例。而且对于我们在程序中存储和传输数据来说是不可或缺的。 通常我们可以使用new方法来创建一个对象:
let peopele = new Object(); people.age = 23; people.name = 'Baoyuan';
我们创建了一个people对象并为其设置了姓名和年龄属性,同样的使用对象字面量也可以有相同的效果:
let people = { name: 'Baoyuan', age: 23 };
在使用这种方式的时候属性名也可以用字符串表示,一般我们推荐使用字面量创建,它的代码简洁而且它也是向函数传递大量参数的首选方式。 我们可以通过点访问法访问其属性:
console.log(people.name); //Baoyuan
除此之外还有一种更为灵活的方式,当我们的属性名中含有包含会导致语法错误的字符串或者是保留字的话,我们可以使用[]来访问:
people['name'] = 'Bao yuan'; //属性名以字符串形式放入,属性值中含有空格。
这种方式还可以通过变量来访问属性:
let item = 'name'; people[item]; //Baoyuan
同常来说除非必须使用[]的情况下,一般建议用点表示法。
除此之外引用类型还有Array、 Date、 RegExp、 Function等。
在检测基本数据类型的时候我们使用typeof,但是如果我们在引用类型上使用的话都会返回object,这并不是我们想要的。为此ECMAScript提供了instanceof:
result = variable instanceof constructor
它会根据原型链来识别,比如:
console.log(people instanceof Array); //变量people是Array类型吗?