- 构造函数
根据函数的调用方式不同,分为普通函数和构造函数,当作为构造函数使用时,会执行以下几个步骤。
- 立即创建一个新的对象(这个对象属于该构造函数类)
- 将这个对象设置为函数中的参数 this ,在构造函数中可以引用新创建的对象。
- 执行函数中的代码
- 最后将创建的对象返回。
- 原型对象
function Person(name){
this.name = name
}
//以构造函数的方式调用Person函数
let p = new Person("张无忌")
//函数对象的prototype属性与函数实例对象都指向了一个对象
console.log(Person.prototype == p.__proto__)
//当访问一个实例上的属性或方法时,会先从实例自身寻找,如果实例自身没有,则去原型对象上去找
//p.printName() //p.printName is not a function
//此时实例对象的原型对象也会先在自身去找,找不到再去实例对象的原型对象的原型对象上去找
//如果最后找到了Object类的原型对象的原型对象,则就会返回null。
console.log('p.__proto__',p.__proto__) //Person类实例对象的原型对象
//这里注意:自定义的构造函数创建出来的实例对象的原型对象(__proto__),默认指向了Object类的实例。
//既然是对象,那么就会有__proto__属性,那么Object类的实例的__proto__属性,也是一个Object实例
//值得注意的是 Object实例的原型对象就没有原型对象了
console.log('object类实例的原型对象',new Object().__proto__) //这是object类实例的原型对象
console.log('object类实例的原型对象的原型对象',new Object().__proto__.__proto__) //Object类实例的原型对象的原型对象
自定义的构造函数的实例对象的原型对象默认是一个object实例。那么Object类实例的原型对象也是Object实例,但是,这个实例的原型对象就是null了。
- 修改Person类的原型对象实例
function MyObject(){
}
//为MyObject类的原型对象添加一个printName方法
MyObject.prototype.printName = function(){
console.log("this",this.name)
}
//将Person类的原型对象引用MyObject的实例
let myObj = new MyObject()
Person.prototype = myObj
let per = new Person("per")
per.printName()
此时Person实例的原型对象是MyObject类实例,而MyObject类的原型对象没有被修改则为Object类实例。
那么此时per实例调用printName时,自身寻找没有,则去原型对象上去找,此时原型对象是myObject,myObject对象有printName方法,则直接使用,如果没有,则继续找myObject的原型对象,myObject的原型对象是Object类实例,如果Object类实例没有,则去Object类原型对象找。如果Object类的原型对象的原型对象是null