JavaScript中的原型与原型链
原型
原型就是每一个函数天生就可以调用的属性,这些属性每一个对象都有,对象中有 constructor 属性表示构造函数本身。
- 作用:实例共享属性和方法;
- 特点:每一个实例化对象天生就可以访问类原型中的所有内容;
就比如,所有的对象都有 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
- 每个 class 都有显式原型 prototype;
- 每个实例都有隐式原型 __proto__;
- 实例的 __proto__ 指向对应 class 的 prototype;