JavaScript 对象三角恋关系&原型链
分类:
JavaScript
日期:
2022-5-19标签:
JavaScript原型链
原型和继承是 Javascript 中非常重要的两大概念,Javascript 以原型链的形式,保证函数或对象中的方法、属性可以让向下传递,按照面向对象的说法,这就是继承。而 Javascript 通过原型链才得以实现函数或对象的继承。
构造函数、实例、原型对象之间的三角恋关系#
- 每个"构造函数"中都有一个默认的属性, 叫做 prototype,prototype 属性保存着一个对象, 这个对象我们称之为原型对象
- 每个"原型对象"中都有一个默认的属性, 叫做 constructor,constructor 指向当前原型对象对应的那个构造函数
- 通过构造函数创建出来的对象我们称之为"实例对象",每个"实例对象"中都有一个默认的属性, 叫做 __proto__ ,__proto__指向创建它的那个构造函数的"原型对象"
function Person(myName, myAge) {this.name = myName;this.age = myAge;}let obj1 = new Person('lnj', 34);console.log(Person.prototype);console.log(Person.prototype.constructor);console.log(obj1.__proto__);
Function 函数#
- JavaScript 中函数是引用类型(对象类型), 既然是对象,所以也是通过构造函数创建出来的,"所有函数"都是通过 Function 构造函数创建出来的对象
- JavaScript 中只要是"函数"就有 prototype 属性,"Function 函数" 的 prototype 属性指向"Function 原型对象"
- JavaScript 中只要"原型对象"就有 constructor 属性,"Function 原型对象"的 constructor 指向它对应的构造函数
- Person 构造函数是 Function 构造函数的实例对象, 所以也有 __proto__ 属性,Person 构造函数的 __proto__ 属性指向"Function 原型对象"
function Person(myName, myAge) {this.name = myName;this.age = myAge;}let obj1 = new Person('lnj', 34);// console.log(Function);// console.log(Function.prototype);// console.log(Function.prototype.constructor);// console.log(Function === Function.prototype.constructor); // true// console.log(Person.__proto__);console.log(Person.__proto__ === Function.prototype); // true
Object 函数#
- JavaScript 函数是引用类型(对象类型), 所以 Function 函数也是对象
- "Function 构造函数"也是一个对象, 所以也有 __proto__ 属性,"Function 构造函数 "__proto__ 属性指向"Function 原型对象"
- JavaScript 中还有一个系统提供的构造函数叫做 Object,只要是函数都是"Function 构造函数"的实例对象
- 只要是对象就有 __proto__ 属性, 所以"Object 构造函数"也有 __proto__ 属性,"Object 构造函数"的 __proto__ 属性指向创建它那个构造函数的"原型对象"
- 只要是构造函数都有一个默认的属性, 叫做 prototype,prototype 属性保存着一个对象, 这个对象我们称之为"原型对象"
- 只要是原型对象都有一个默认的属性, 叫做 constructor,constructor 指向当前原型对象对应的那个"构造函数"
function Person(myName, myAge) {this.name = myName;this.age = myAge;}let obj1 = new Person('lnj', 34);// console.log(Function.__proto__);// console.log(Function.__proto__ === Function.prototype); // true// console.log(Object);// console.log(Object.__proto__);// console.log(Object.__proto__ === Function.prototype); // true// console.log(Object.prototype);// console.log(Object.prototype.constructor);// console.log(Object.prototype.constructor === Object); // true// console.log(Object.prototype.__proto__); // null
函数对象关系#
- 所有的构造函数都有一个 prototype 属性, 所有 prototype 属性都指向自己的原型对象
- 所有的原型对象都有一个 constructor 属性, 所有 constructor 属性都指向自己的构造函数
- 所有函数都是 Function 构造函数的实例对象
- 所有函数都是对象, 包括 Function 构造函数
- 所有对象都有__proto__属性
- 普通对象的__proto__属性指向创建它的那个构造函数对应的 "原型对象"
- 所有对象的__proto__属性最终都会指向 "Object 原型对象"
- "Object 原型对象"的__proto__属性指向 NULL
function Person(myName, myAge) {this.name = myName;this.age = myAge;}let obj1 = new Person('lnj', 34);console.log('1', Function.prototype.__proto__);console.log('2', Person.prototype.__proto__);console.log('3', Function.prototype.__proto__ === Person.prototype.__proto__);console.log('4', Function.prototype.__proto__ === Object.prototype);console.log('5', Person.prototype.__proto__ === Object.prototype);
原型链#
- 对象中__proto__组成的链条我们称之为原型链
- 对象在查找属性和方法的时候, 会先在当前对象查找,如果当前对象中找不到想要的, 会依次去上一级原型对象中查找,如果找到 Object 原型对象都没有找到, 就会报错
function Person(myName, myAge) {this.name = myName;this.age = myAge;// this.currentType = "构造函数中的type";// this.say = function () {// console.log("构造函数中的say");// }}Person.prototype = {// 注意点: 为了不破坏原有的关系, 在给prototype赋值的时候,// 需要在自定义的对象中手动的添加constructor属性, 手动的指定需要指向谁constructor: Person,// currentType: "人",// say: function () {// console.log("hello world");// }};let obj1 = new Person('lnj', 34);// obj1.say();console.log(obj1.currentType);// console.log(Person.prototype.constructor);
注意点: 为了不破坏原有的关系, 在给 prototype 赋值的时候, 需要在自定义的对象中手动的添加 constructor 属性, 手动的指定需要指向谁
属性注意点#
在给一个对象不存在的属性设置值的时候,不会去原型对象中查找,如果当前对象没有就会给当前对象新增一个不存在的属性
function Person(myName, myAge) {this.name = myName;this.age = myAge;}Person.prototype = {constructor: Person,currentType: '人',say: function () {console.log('hello world');},};let obj = new Person('lnj', 34);// console.log(obj.currentType); // "人"// console.log(obj.__proto__.currentType); // "人"// 注意点: 在给一个对象不存在的属性设置值的时候, 不会去原型对象中查找,// 如果当前对象没有就会给当前对象新增一个不存在的属性obj.currentType = '新设置的值';console.log(obj.currentType); // 新设置的值console.log(obj.__proto__.currentType); // "人"
总结#
访问对象的一个属性,先在自身查找,如果没有,会访问对象的__proto__,沿着原型链查找,一直找到 Object.prototype.__proto__。
原型链上一切皆对象,即都有__proto__属性,该属性的指向一个原型对象,
构造函数都有 prototype 属性,指向自身构造函数的原型对象。
__proto__链条(原型链)的尽头是 Object.prototype.__proto__,为 null。