要点
- JavaScript中类型系统是动态、宽松的,所有对象用
typeof
操作都得到Object
- JavaScript没有严格意义上的对象类型,要判断对象类型,只能看创建该对象的构造函数
- 每当使用运算符new调用构造函数时,都将创建一个新的对象实例
- 在JavaScript中,由同一构造函数创建的对象实例,认为它们属于相同的对象类型
- 运算符instanceof可判断对象是否是使用特定构造函数创建的
- 用构造函数创建好对象后,再增删这个对象的属性,其对象类型不变
原因:使用instanceof
运算符来操作对象,结果不变 - 只有使用自定义构造函数创建对象,才能用instanceof判断其对象类型
使用字面量表示法或Object构造函数只能创建最通用的对象,它们是Object构造函数的实例
问题背景
在JavaScript中,创建一个小狗对象和一个汽车对象
引入对象类型:
- 两个小狗对象(有相同属性和方法),它们的对象类型相同
- 小狗对象和汽车对象,他们的对象类型不同
用typeof运算符无法判断对象类型是否相同:JavaScript中,对象是一个动态的结构,无论对象包含哪些属性和方法,其类型都是object
原因:在Java和C++等很多其他面向对象的语言中,有严格的对象类型概念,可以确定对象到底是哪种类型的;
但在JavaScript中不是这样的。由于JavaScript类型系统(对象系统)更动态、更宽泛、更灵活,要确定对象(小狗或汽车)是否属于同一对象类型更难些:这取决于你对小狗或汽车的定义,具体使用运算符instanceof来判断,详见下文
既然typeof不会指出对象是小狗对象还是汽车对象,如何确定对象是哪种类型的呢?
判断对象类型是否相同
JavaScript没有严格意义上的对象类型。要比较两个对象,看它们的对象类型是否相同(是否都是小狗)方法是:
- 由同一构造函数创建的对象,它们属于相同的对象类型
例如:
if ((fido instanceof Dog)&&(spot instanceof Dog))
则它们的对象类型相同(都是Dog)
- 运算符instanceof可判断对象是否是由某个构造函数创建的
- 然而,下面两种情况,无法由instanceof区分其对象类型:
①如果用字面量表示法创建对象
②或用内置构造函数new Object()
创建对象
这样创建的是最通用、最一般的对象,它们都是Object
构造函数的实例
原型链的终点-Object将讨论Object
在js对象系统中所处的位置 - 注意:用构造函数创建好对象后,再增删这个对象的属性,其对象类型不变
(因为创建对象的构造函数不变,则用instanceof判断的结果不变)
ps. 上面说JavaScript的类型系统是动态的,指的就是这个意思
function Dog(name, breed, weight) {
this.name = name;
this.breed = breed;
this.weight = weight;
}
var fido = new Dog("Fido", "Mixed", 38);//由构造函数创建新的对象实例
fido.age = 5;
delete fido.weight;//由构造函数创建好的对象,增删属性,对象类型不变
if(fido instanceof Dog)
console.log("fido is a Dog.");//输出"fido is a Dog."
JavaScript中,原理就是这样的。小狗之所以是小狗,是因为它是由构造函数Dog创建的;而汽车之所以是汽车,是因为它是由构造函数Car创建的。
实际上,你将看到,JavaScript构造函数和对象比你知道的还要灵活。例如,对于使用构造函数Taxi创建的对象,我们可以知道它也是汽车。现在只需了解这一点即可,之后在原型式继承的原理和instanceof中将更详细地介绍。
instanceof工作原理:构造函数创建了对象实例
- 每当使用运算符new调用构造函数时,都将创建一个新的对象实例
因此,如果用构造函数Car创建一个对象,这个对象就是一个Car实例,它也就属于Car这种对象类型 - 实际上,创建对象时,运算符new在幕后存储了一些信息,能帮助确定对象是由哪个构造函数创建的
- 运算符instanceof根据这些信息判断对象是否是某个特定构造函数的实例。
(情况比这里描述的要复杂些,这将在下一章讨论)