这段代码第一行的作用是什么?它是Object还是Constructor Function?
Great question! Let's break this down step by step to make it crystal clear.
1. 第一行 function Bird() { } 的功能
这行代码定义了一个名为Bird的构造函数——这是JavaScript里用来创建特定类型对象实例的函数,行业里习惯把构造函数的首字母大写,方便和普通函数区分开。
这个空的Bird函数本身虽然没有写任何逻辑,但当你用new Bird()调用它时,它会自动生成一个新的Bird实例对象,并且这个实例会和Bird.prototype建立原型关联,后续可以继承原型上的属性和方法。
2. 它属于构造函数还是Object?
其实这两个说法并不冲突,但要分场景看:
- 从角色用途来说,它是一个构造函数:因为它的设计目的就是配合
new关键字来创建实例对象。 - 从JS的底层本质来说,它确实是一个
Object:因为在JavaScript里,所有函数都是Function类型的对象,而Function本身又继承自Object,所以函数本质上也是对象的一种。
不过我们通常会根据它的使用场景,称它为构造函数,这是更贴合它用途的描述。
3. 为什么duck.constructor会指向Animal?
咱们来看后续的代码逻辑:
Bird.prototype = Object.create(Animal.prototype); let duck = new Bird(); duck.constructor // function Animal(){...}
Object.create(Animal.prototype)的作用是生成一个新对象,这个新对象的原型链直接指向Animal.prototype——这行代码是在实现原型继承,让Bird的所有实例都能继承Animal原型上的属性和方法。
但这里有个容易踩的坑:每个构造函数的默认prototype对象,都会自带一个constructor属性,指向构造函数本身(比如原来的Bird.prototype.constructor是Bird)。但当我们直接把Bird.prototype替换成Object.create生成的新对象时,这个新对象并没有自己的constructor属性,它会沿着原型链往上找,最终找到Animal.prototype.constructor,而这个属性指向的就是Animal构造函数,所以duck.constructor就变成了Animal。
如果想让duck.constructor正确指向Bird,我们需要手动修复这个constructor属性:
Bird.prototype = Object.create(Animal.prototype); Bird.prototype.constructor = Bird; // 手动修正constructor的指向 let duck = new Bird(); duck.constructor // 现在会正确指向function Bird(){...}
内容的提问来源于stack exchange,提问作者ajhernandez95

