# 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 来调用,就跟普通函数无区别
    • 约定构造函数首字母大写

# 构造函数的缺点

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