JavaScript 原型对象与原型链

296 阅读4分钟

原型与原型链

prototype

  1. prototype 特点
    1. 存储在 prototype 中的方法可以被对应构造函数创建出来的所有对象共享
    2. prototype 中除了可以存储方法以外, 还可以存储属性
    3. prototype 如果出现了和构造函数中同名的属性或者方法, 对象在访问的时候, 访问到的是构造函中的数据
  2. prototype 应用场景 (储存一类对象共性的部分)
    1. prototype 中一般情况下用于存储所有对象都相同的一些属性以及方法
    2. 如果是对象特有的属性或者方法, 我们会存储到构造函数中
function Person(myName, myAge) {
    this.name = myName;
    this.age = myAge;
    this.currentType = "构造函数中的type";
    this.say = function () {
        console.log("构造函数中的say");
    }
}
Person.prototype = {
    currentType: "人",
    say: function () {
        console.log("hello world");
    }
}

__proto__ 与 prototype

  1. prototype: 每个"构造函数"中都有一个默认的属性 (打引号是因为:普通函数也有), 叫做 prototype prototype 属性保存着一个对象, 这个对象我们称之为"原型对象"

    正确但绕的说法: prototype 是个默认的变量, 保存着对象, 该对象属性方法被同类对象共享

  2. constructor: 每个"原型对象"中都有一个默认的属性, 叫做 constructor constructor 指向当前原型对象对应的那个"构造函数"

  3. __proto__: 通过构造函数创建出来的对象我们称之为"实例对象" 每个"实例对象"中都有一个默认的属性, 叫做 __proto__ __proto__ 指向创建它的那个构造函数的"原型对象"

    正确但绕的说法: 构造函数的 prototype 中的内容是构造函数生成的对象的内容

小发现: 隐式存在的东西容易让人懵逼, 我尤其懵逼

Function 与 Object

Function
  1. JavaScript 中函数是引用类型(对象类型), 即对象, 所以也是通过构造函数创建出来的,所有函数都是通过 Function 构造函数创建出来的对象
  2. JavaScript 中只要是函数就有 prototype 属性 Function 函数的 prototype 属性指向 Function 原型对象 Function 的特殊之处在于他的 __proto__ 也是指向 Function 原型对象
  3. JavaScript 中只要原型对象就有 constructor 属性 Function 原型对象的 constructor 指向它对应的构造函数
  4. Person 构造函数是 Function 构造函数的实例对象, 所以也有 __proto__ 属性 Person 构造函数的 __proto__ 属性指向 Function 原型对象
Object
  1. JavaScript 中函数是引用类型(对象类型), 所以 Function 函数也是对象
  2. Function构造函数也是一个对象, 所以也有 __proto__ 属性 Function构造函数的 __proto__属性指向"Function原型对象" (所有函数包括普通函数, Object 的__proto__也是)
  3. JavaScript中还有一个系统提供的构造函数叫做 Object 只要是函数都是"Function 构造函数"的实例对象
  4. 只要是对象就有 __proto__ 属性, 所以"Object 构造函数"也有__proto__属性 Object构造函数的 __proto__ 属性指向创建它那个构造函数(也就是 Function)的"原型对象"
  5. 只要是构造函数都有一个默认的属性, 叫做 prototype (普通函数也有的) prototype属性保存着一个对象, 这个对象我们称之为"原型对象"
  6. 只要是原型对象都有一个默认的属性, 叫做 constructor constructor 指向当前原型对象对应的那个"构造函数"

原型链 - 构造函数终版优化

  1. 对象中 __proto__ 组成的链条我们称之为原型链
  2. 对象在查找属性和方法的时候, 会先在当前对象查找 如果当前对象中找不到想要的, 会依次去上一级原型对象中查找 如果找到 Object 原型对象都没有找到, 就会报错

注意点: 为了不破坏原有的关系, 在给 prototype 赋值的时候, 需要在自定义的对象中手动的添加 constructor 属性, 手动的指定需要指向谁

function Person(myName, myAge) {
    this.name = myName;
    this.age = myAge;
}

Person.prototype = {
    constructor: Person,
    currentType: "人",
    say: function () {
        console.log("hello world");
    }
}

补充: 在给一个对象不存在的属性设置值的时候, 不会去原型对象中查找, 如果当前对象没有就会给当前对象新增一个不存在的属性

小结

  • 一般实例对象的 __proto__ 指向其构造函数的原型对象 (所以 Function 的特殊之处在于其自己构造了自己)
  • 所有原型对象的 __proto__ 都指向 Object 的原型对象 (Object.prototype.__proto__ 指向 null)
  • constructor 指向其所属对象的所属对象
  • 函数都有 prototype
  • prototype 的 constructor 要指回 prototype 的所属函数才完整