JavaScript中的原型与原型链

原型

原型就是每一个函数天生就可以调用的属性,这些属性每一个对象都有,对象中有 constructor 属性表示构造函数本身。

  1. 作用:实例共享属性和方法;
  2. 特点:每一个实例化对象天生就可以访问类原型中的所有内容;

就比如,所有的对象都有 toString 和 valueOf 属性,我们就不需要给每个对象一个 toString 和 valueOf。因为 JavaScript 的做法就是把 toString 和valueOf 属性放在一个对象里(暂且叫做公用属性组成的对象),然后让每一个对象的 __proto__ 存储这个「公用属性组成的对象」的地址。

我们先来看下面这段代码:

let obj1 = new Object()
let obj2 = new Object()
console.log(obj1 === obj2)    // false
console.log(obj1.toString === obj2.toString)    // true

在上面的代码中 obj1 和 obj2 是不严格相等的,因为这两个空对象的地址不同,但是他们转为 toString 之后是相等的。虽然我们并没有给这两个空对象添加 toString 属性,但是它们自带了 toString 属性,其实这里的 toString 属性就是一个原型。


原型链

当对象使用属性的时候,首先在自身进行查找,如果有就直接使用,如果没有就沿着 __proto__ 这条链往下查找,直到找到 Object 原型位置,有就返回相应的值,没有就返回 underfined。

var n = new Number()
console.log(n.__proto__ === Number.prototype)    // true
console.log(n.__proto__.__proto__ === Object.prototype)    // true

console.log(Object.prototype.__proto__ === null)    // true
var 对象 = new 函数()

// __proto__ 是对象的属性,prototype 是函数的属性
对象.__proto__ === 函数.prototype

// 函数的 prototype 是对象,这个对象对应的就是函数 Object
函数.prototype.__proto__ === Object.prototype

// 由于函数本身即是函数(最优先被视为函数),也是对象,而函数的构造函数是 Function
函数.__proto__ === Function.prototype

// Function 即是对象,也是函数,但他优先是个函数
Function.__proto__ === Function.prototype

// Function.prototype 也是对象,是普通的对象,所以其对应的函数是Object
Funciton.prototype.__proto__=== Object.prototype

所有函数都是由 Function 构造出来的,因此:

// Object 是函数,是 Function 的实例
console.log(Object.__proto__ === Function.prototype)    // true

最后我们再来看看这张图:

原型与原型链


下面我们来使用下 class:

class People {
  constructor(id, name) {
    this.id = id
    this.name = name
  }
  sayHi() {
    console.log("id 是 " + this.id + ",名字是 " + this.name)
  }
}

class Student extends People {
  constructor(id, name, age) {
    super(id, name)
    this.age = age
  }
  sayHi() {
    console.log("id 是 " + this.id + ",名字是 " + this.name + ",年龄是 " + this.age)
  }
}

let lq = new People(0, 'zww')
console.log(lq)    // People {id: 0, name: "zww"}
lq.sayHi()    // id 是 0,名字是 zww

let zww = new Student(0, 'zww', 18)
console.log(zww)    // Student {id: 0, name: "zww", age: 18}
zww.sayHi()    // id 是 0,名字是 zww,年龄是 18

// class 实际上是函数
console.log(typeof People)    // function
console.log(typeof Student)    // function

console.log(zww.__proto__ === Student.prototype)    // true
console.log(zww.__proto__.__proto__ === People.prototype)    // true

console.log(People.__proto__ === Function.prototype)    // true
console.log(People.__proto__ === Object.__proto__)    // true
console.log(People.__proto__.__proto__ === Object.prototype)    // true
  1. 每个 class 都有显式原型 prototype;
  2. 每个实例都有隐式原型 __proto__;
  3. 实例的 __proto__ 指向对应 class 的 prototype;

posted @ 2020-06-13 22:28  LqZww  阅读(95)  评论(0编辑  收藏  举报