Skip to content

原型链

说明

  1. 原型:函数都有prototype属性,称之为原型,也称为原型对象

    • 原型可以放一些属性和方法,共享给实例对象使用
    • 原型可以做继承
  2. 原型链:对象都有 __proto__ 属性,这个属性指向它的原型对象,原型对象也是对象,也有自己的 __proto__ 属性,指向原型对象的原型对象,这样一层一层形成的链式结构称为原型链,最顶层找不到则返回 null

概念

类: 类是一种创建对象的蓝图或模板, 在 js 中, 类本质还是一个构造函数。

构造器(也称 constructor构造函数)

概念

构造函数: 用 new 来执行的函数。

介绍

原本以前是通过一个称为 构造函数 的方式创建实例对象的,而构造函数也称为构造器, 但是这种方式不直观, 给所有实例对象添加共享的属性或方法是通过 构造函数名.prototype.函数名称 = function () {} 的方式来创建的, 这很不符合面向对象的写法。 于是在 ES6+ 出了一种新的语法糖, 使用 class 来定义类, 在类的constructor 方法中或类中定义实例对象的拥有的属性和方法, 若在类中定义的方法或属性通过 static 修饰符修饰, 那么它就是一个类的静态方法, 通过 类名.方法类名.属性 的方式访问, 这样就实现了类和实例对象的属性或方法分离。

对象

概念

对象/实例: 由类通过 new 创建的独立个体。

显式原型(也称 prototype)

介绍

每一个对象都有一个隐式原型 __proto__ 属性, 该属性的值指向对象的构造函数的原型对象, 也就是说, __proto__ 属性指向构造函数的prototype 属性。

js
/**假设下面这个是你创建的函数: 在不同的调用场景下,它的称呼会有一点不同 */
function User(name, age) {
  this.name = name;
  this.age = age;
}

/**1. 直接调用。称为函数: 普通调用的函数, 一半约定俗成函数名都取小驼峰命名 */


/**2. 通过 new 调用。它也可以称为构造函数: 构造函数命名约定俗成, 大驼峰命名 */
User.prototype.tmp = "prototype";

const user = new User("Alice", 25);
/**验证实例对象的隐式原型 指向 构造函数的显示原型:
            实例对象.__proto__ === User.prototype
*/
console.dir(user.__proto__ === User.prototype);

隐式原型(也称 __proto__[[Prototype]])

介绍

显示原型与隐式原型的关系

说明

实例对象的隐式原型 === 构造函数的显式原型

原型链图

JS原型链

原型链

原型链-手绘

直观原型链

完整原型链

提示:

js
// 下面的代码均验证了与图结构的一致性
function Vue() {

}
let vue = new Vue();
/** 对象才有隐式原型 */
// (1)实例对象的隐式原型指向构造函数对象的原型
console.log(vue.__proto__ === Vue.prototype)     // true
// (2) 普通函数是Function构造函数的实例对象
console.log(Vue instanceof Function)            // true
// (3)构造函数的原型是Object构造函数的实例对象
console.log(Vue.prototype instanceof Object)    // true
// (4)构造函数对象(底层通过Function构造函数创造出来的)的隐式原型指向Function原型
console.log(Vue.__proto__ === Function.prototype)   // true
// (5)Function构造函数对象的隐式原型指向Function原型
console.log(Function.__proto__ === Function.prototype)  // true
// (6)Function原型的隐式原型指向Object原型
console.log(Function.prototype.__proto__ === Object.prototype)  // true
// (7)实例对象vue的构造器constructor是构造函数(构造器可以被更改!!!)
console.log(vue.constructor === Vue);   // true
function Vue3() {
    this.name = 'vue3'
}
vue.constructor = Vue3;
console.log(vue.constructor);       // Vue3
console.log(vue.constructor === Vue);  // false