【JavaScript之构造函数、原型和原型链】

1,504 阅读3分钟

JavaScript之构造函数、原型和原型链

举个栗子

我们先使用构造函数创建一个对象:

function Person() {
    this.name = 'zhoukingzz';
}
var person = new Person();
console.log(person.name) // zhoukingzz
Person.prototype.name = 'apple';
console.log(person.name) // zhoukingzz
Person.prototype.sayName = function(){
    console.log(this.name)
};
person.sayName()// zhoukingzz
  • 在这个例子中,Person 就是一个构造函数,我们使用 new 创建了一个实例对象 person。
  • 当new两个实例出来,这个实例会获得构造函数所有的属性和方法,new完后再往构造函数的prototype上挂一个新的方法,那么,这两个new出来的实例都会拥有这个新的方法;但如果添加的是属性,那么并不会改变实例本身的属性值

实例

  • 用new生成的对象称为实例
  • 实例的原型链_proto_,指向原型对象
  • 当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还查不到,就去找原型的原型,一直找到最顶层为止。

new调用构造函数的完整步骤

  • 创建一个Object对象
  • 将Object对象的原型链_proto_指向构造函数的原型prototype
  • 将构造函数的this指向Object对象
  • 执行构造函数中的代码
  • 返回Object对象

原型和原型链

  • 每一个JavaScript对象(除了 null )都具有的一个属性,叫_proto_,这个属性会指向该对象的原型
  • 所有函数的原型对象的_proto_,会指向Object.prototype
  • 原型链的尽头是Object.prototype.proto,为null。

总结

  • 在js中函数也是一个对象,每个函数(除箭头函数外,下文默认)都有一个prototype属性,且prototype是函数才会有的属性,这个属性是一个指针,指向一个对象(原型对象),而这个对象的用途是可以由特定类型的所有实例共享的属性和方法。(一句话:构造函数都有自己的原型对象)
  • 可以说prototype就是通过调用构造函数而创建的那个对象实例的原型对象。默认情况下,所有原型对象会自动获得一个constructor属性,这个属性指向prototype属性所在的指针(原型对象下面有个属性constructor,该属性指向构造函数)
  • 实例和他的原型对象之间有条链接,这条链接就是原型链_proto_(可以从原型链上继承方法)
  • 原型对象还会指向自己的原型对象,一直到Object为止
  • 在构造函数中的this指向实例化的对象

构造函数和普通函数区别

  • 唯一区别:调用方法不同
    • 任何函数,只要通过new来调用,就可以作为构造函数
    • 不通过new来调用,就跟普通函数无区别
    • 约定构造函数首字母大写

构造函数的缺点

  • 通过构造函数为实例对象定义属性,虽然很方便,但是有一个缺点。同一个构造函数的多个实例之间,无法共享属性,从而造成对系统资源的浪费。