JS 中的原型和原型链

在了解原型和原型链之前,先明确几个概念:

  1. 一切引用类型(数值、对象、函数)都是对象,都是可以自由扩展属性的,null 除外;
  2. 对象是属性的集合;
  3. 每个对象都是通过构造函数创建的;
  4. 每个函数都有一个 prototype 属性(此属性是一个对象),也就是 原型;对象都有一个 __proto__ 属性,此属性是隐式属性,JS不希望开发者调用到这个属性;
  5. 每个对象的 __proto__ 属性 指向创建该对象的构造函数的 prototype 属性;
  6. Object.prototype.__proto__ 指向的是 null (要不然就无穷无尽了);
  • 原型

// 构造函数
function Foo (name, age) {
    this.name = name;
    this.age = age;
}
// 所以函数上都有一个 prototype 属性,此属性是一个对象,则就可以扩展属性
Foo.prototype = {
    showName () {
        console.info('Name: ' + this.name);
    },
    showAge () {
        console.info('Age: ', this.age);
    }
}
let fn = new Foo('静静', 16);
fn.showName(); // Name: 静静
fn.showAge(); // Age:  16

个人理解:原型可以扩展构造函数,避免将全部的属性或者方法都初始在构造函数中,继而在生成实例时,占用太多内存资源。

  • 原型链

访问一个对象的属性时,先在本地属性中查找,如果没有,就会去它的构造函数上的 prototype 属性去找,由于 prototype 属性本身也是一个对象,则就有 __proto__ 属性,再沿着__proto__这条链向上找,这就是原型链。

// 构造函数
function Foo (name, age) {
    this.name = name;
    this.age = age;
}
Object.prototype.toString = function () {
    console.info(`Name: ${this.name}, Age: ${this.age}`);
}
let fn = new Foo('静静', 16);
fn.toString(); // Name: 静静, Age: 16
console.info(fn.toString === Foo.prototype.__proto__.toString); // true

console.info(fn.__proto__ === Foo.prototype); // true

console.info(Object.prototype === Foo.prototype.__proto__); // true

console.info(Object.prototype.__proto__ === null); // true

分析:fn 是一个对象,有 __proto__ 属性,依据上述概念5可知,fn 上的 __proto__ 属性指向 其构造函数 Foo 上的 prototype 属性;Foo.prototype 的构造函数是 Object,Object 函数上有 prototype 属性;Foo.prototype 是一个对象,则就有 __proto__ 属性,则 Foo.prototype.__proto__ 属性 指向 Object.prototype;Object.prototype 属性就指向 null 。

原文地址:https://www.cnblogs.com/idspring/p/11863121.html