构造函数名一般为大写字母开头,与new运算符一起使用来实例化对象。
// 构造函数
function Person() {
this.name = 'Denise'
}
// 创建对象(实例化)
var p = new Person()
// 打印出来看看
console.log(Person.prototype)
console.log(p)
什么是原型呢?
构造函数在创建的过程中,系统自动创建出来与构造函数相关联的一个空的对象。可以由构造函数 .prototype 来访问到。如上述代码,在实例化对象p的过程中,系统就自动创建出了构造函数的原型 Person.prototype 。
每个对象的 __proto__ 属性指向自身构造函数的prototype。如上述代码,对象p的 __proto__ 指向 Person.prototype。
constructor属性是原型对象Person.prototype 的属性,指向这个原型对象所对应的构造函数,即Person。
关键在于 __proto__ ,那 __proto__ 到底是什么呢?
简单来说,每个对象都会有一个 __proto__ 属性,当我们访问一个对象的属性时,如果这个对象本身不存在这个属性,那么它就会去 __proto__ 里找这个属性,这个 __proto__ 又会有自己的 __proto__ ,于是就这样一直找下去,这就是所谓的原型链。
在上面这个例子中的p对象的原型链结构图如下:
p -----> Person.prototype (p.__proto__) -----> Object.prototype (p.__proto__.__proto__) -----> null
那么,new 到底做了什么?
// 构造函数
function Person() {
this.name = 'Denise'
}
// 创建对象(实例化)
var p = new Person()
// 模拟推导过程 -->
var p = {};
p.__proto__ = Person.prototype;
Person.call(p);
1.创建一个空对象 p
2.把这个空对象 p 的属性 __proto__ 指向函数 Person 的 prototype
3.将构造函数 Person 的作用域赋给新对象 p,即 this 指向了 p
4.执行Person 中的代码,为p添加属性 name
5.返回新对象