原型与原型链
prototype
- prototype 特点
- 存储在 prototype 中的方法可以被对应构造函数创建出来的所有对象共享
- prototype 中除了可以存储方法以外, 还可以存储属性
- prototype 如果出现了和构造函数中同名的属性或者方法, 对象在访问的时候, 访问到的是构造函中的数据
- prototype 应用场景 (储存一类对象共性的部分)
- prototype 中一般情况下用于存储所有对象都相同的一些属性以及方法
- 如果是对象特有的属性或者方法, 我们会存储到构造函数中
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
-
prototype: 每个"构造函数"中都有一个默认的属性 (打引号是因为:普通函数也有), 叫做 prototype prototype 属性保存着一个对象, 这个对象我们称之为"原型对象"
正确但绕的说法: prototype 是个默认的变量, 保存着对象, 该对象属性方法被同类对象共享
-
constructor: 每个"原型对象"中都有一个默认的属性, 叫做 constructor constructor 指向当前原型对象对应的那个"构造函数"
-
__proto__: 通过构造函数创建出来的对象我们称之为"实例对象" 每个"实例对象"中都有一个默认的属性, 叫做 __proto__ __proto__ 指向创建它的那个构造函数的"原型对象"
正确但绕的说法: 构造函数的 prototype 中的内容是构造函数生成的对象的内容
小发现: 隐式存在的东西容易让人懵逼, 我尤其懵逼
Function 与 Object
Function
- JavaScript 中函数是引用类型(对象类型), 即对象, 所以也是通过构造函数创建出来的,所有函数都是通过 Function 构造函数创建出来的对象
- JavaScript 中只要是函数就有 prototype 属性 Function 函数的 prototype 属性指向 Function 原型对象 Function 的特殊之处在于他的 __proto__ 也是指向 Function 原型对象
- JavaScript 中只要原型对象就有 constructor 属性 Function 原型对象的 constructor 指向它对应的构造函数
- Person 构造函数是 Function 构造函数的实例对象, 所以也有 __proto__ 属性 Person 构造函数的 __proto__ 属性指向 Function 原型对象
Object
- JavaScript 中函数是引用类型(对象类型), 所以 Function 函数也是对象
- Function构造函数也是一个对象, 所以也有 __proto__ 属性 Function构造函数的 __proto__属性指向"Function原型对象" (所有函数包括普通函数, Object 的__proto__也是)
- JavaScript中还有一个系统提供的构造函数叫做 Object 只要是函数都是"Function 构造函数"的实例对象
- 只要是对象就有 __proto__ 属性, 所以"Object 构造函数"也有__proto__属性 Object构造函数的 __proto__ 属性指向创建它那个构造函数(也就是 Function)的"原型对象"
- 只要是构造函数都有一个默认的属性, 叫做 prototype (普通函数也有的) prototype属性保存着一个对象, 这个对象我们称之为"原型对象"
- 只要是原型对象都有一个默认的属性, 叫做 constructor constructor 指向当前原型对象对应的那个"构造函数"
原型链 - 构造函数终版优化
- 对象中 __proto__ 组成的链条我们称之为原型链
- 对象在查找属性和方法的时候, 会先在当前对象查找 如果当前对象中找不到想要的, 会依次去上一级原型对象中查找 如果找到 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 的所属函数才完整