constructor
- 官方定义: constructor 属性返回对创建此对象的数组函数的引用。
- 普遍理解:constructor属性指向的是调用它的构造函数
- 个人理解:每一个引用类型的数据都有一个constructor属性,他指向调用该引用类型原型的构造函数。
- 每一个引用类型都有一个constructor属性,由于自定义构造函数会创建一个特殊的对象类型,因此它的constructor属性在原型未被重写时也就是使用默认原型时指向创建它的构造函数。
<script>
var foo = function (){};
var obj = {};
var arr = [];
var reg = /\d/;
var time = new Date();
var num = Number(123);
var str = String('hello world');
var boo = Boolean(true);
console.log(foo.constructor); // ƒ Function() { [native code] }
console.log(obj.constructor); // ƒ Object() { [native code] }
console.log(arr.constructor); // ƒ Array() { [native code] }
console.log(num.constructor); // ƒ Number() { [native code] }
console.log(str.constructor); // ƒ String() { [native code] }
console.log(boo.constructor); // ƒ Boolean() { [native code] }
console.log(reg.constructor); // ƒ RegExp() { [native code] }
console.log(time.constructor); // ƒ Date() { [native code] }
// 以上为Js的原生对象类型,以下为自定义对象类型
function CarFactory(){};
var car = new CarFactory();
console.log(car.constructor); // ƒ CarFactory(){}
// 这里会截断原型链先返回自定义的对象类型,事实上自定义类型也属于Object类型
console.log(car instanceof CarFactory); // true
console.log(car instanceof Object); // true</script>
- 为什么说constructor指向的不是调用它的构造函数而是调用它的原型的构造函数?
通过下面这个例子可以看出一个构造函数的两部分,实例和原型的constructor属性同时都指向他们的构造函数,那么当其中一个的原型的构造函数发生变化时,实例的constructor会发生变化么?
<script>
function CarFactory(){};
var car = new CarFactory();
console.log(car.constructor); // ƒ CarFactory(){}
console.log(CarFactory.prototype.constructor); // ƒ CarFactory(){}
console.log(CarFactory.prototype.constructor === car.constructor); // true
</script>
- 当其中一个的原型的构造函数发生变化时,实例的constructor也会指向原型的constructor,这个例子就很好的解释了为什么一个构造函数中,实例没有发生变化,但是由于原型重写所导致的实例的constructor指向发生变化。
<script>
function CarFactory(){};
// 重写原型,相当于var CarFactory.prototype = new Object();
// 此时原型的构造函数是原生对象类型Object
CarFactory.prototype = {};
var car = new CarFactory();
console.log(car.constructor); // ƒ Object() { [native code] }
console.log(CarFactory.prototype.constructor); // ƒ Object() { [native code] }
console.log(CarFactory.prototype.constructor === car.constructor); // true
</script>
- 当涉及到原型链时,在没有对其中的原型重写的前提下,constructor会指向最终调用的构造函数。这并不是因为constructor属性被重写了,而是会顺着原型链上每个原型对象的constructor一直找到最后的构造函数。
<script>
// 在原型没有重写情况下,car的原型是WheelFactory的实例,因此顺着原型链找到WheelFactory的原型,
// 而WheelFactory的原型指向ƒ WheelFactory(){}构造函数
function WheelFactory(){};
CarFactory.prototype = new WheelFactory();
function CarFactory(){};
var car = new CarFactory();
console.log(car.constructor); // ƒ WheelFactory(){}
console.log(CarFactory.prototype.constructor); // ƒ WheelFactory(){}
console.log(CarFactory.prototype.constructor === car.constructor); // true
</script>
<script>
// 在原型重写情况下,car的原型是WheelFactory的实例,因此顺着原型链找到WheelFactory的原型,
// 而此时WheelFactory的原型因为被重写指向的是ƒ Object() { [native code] }构造函数
function WheelFactory(){};
WheelFactory.prototype = {}; // 这里重写了原型
CarFactory.prototype = new WheelFactory();
function CarFactory(){};
var car = new CarFactory();
console.log(car.constructor); // ƒ Object() { [native code] }
console.log(CarFactory.prototype.constructor); // ƒ Object() { [native code] }
console.log(CarFactory.prototype.constructor === car.constructor); // true
</script>