1.原型链
- 实例对象具有属性__proto__,指向它的原型对象。而原型对象也是对象,也具有属性__proto__,会继续指向它的原型对象。
- 实例对象在访问属性时,先在自身找,找不到则沿着__proto__查找,找到了就使用,直到__proto__为null。我们把__proto__形成的链条关系称为原型链,可以理解为继承。
2.演示原型链
1.实例对象自身的属性(第一层)
function Person(name) {
this.name = name
this.listenMusic = function () {
console.log('听音乐')
}
}
const person = new Person('clz')
console.log(person)
console.log('实例对象本身是否有listenMusic方法', person.hasOwnProperty('listenMusic'))
person.listenMusic()
2.实例对象的原型对象上的属性(第二层)
function Person(name) {
this.name = name
}
Person.prototype.listenMusic = function () {
console.log('听音乐')
}
const person = new Person('clz')
console.log(person)
console.log('实例对象本身是否有listenMusic方法', person.hasOwnProperty('listenMusic'))
person.listenMusic()
3.原型对象的原型对象上的属性(第三层)
function Person(name) {
this.name = name
}
Person.prototype.__proto__.listenMusic = function () {
console.log('听音乐')
}
const person = new Person('clz')
console.log(person)
person.listenMusic()
4.通过__proto__形成的链条,即原型链:
person => Person.prototype => Object.prototype => null
5.上述例子的图示:
3.进阶(Array()数组,Function()函数)
- 数组和函数都是对象,都继承自Object.prototype
- 所有对象创建时都会自动生成_proto_属性(指针变量),所以构造函数也有_proto_属性
- 构造函数也有它的构造函数,比如Object()是由Function()创建的
- 所有函数都是Function()的实例,而User()和Object()都是函数对象,所以它们的构造函数都是Function()。(User()是自己定义的构造函数,见下面测试代码)
- User()和Object()既是构造函数,也是由Function()构造函数创建的实例对象。所有也会继承Function()的原型对象上的constructor属性
- Function()本身也是函数,所以Function()也是自己的实例,自己创建自己
- 每个构造函数都有两个原型对象,一个显式原型prototype,一个隐式原型__proto__(Function()除外,它的prototype和__proto__指向相同)
测试代码:
//数组
let arr = [1, 2, 3];
let str = arr.toString();
console.log(str); //1,2,3
console.log(arr.__proto__); //Array的原型对象
console.log(Object.prototype); //Object的原型对象
console.log(arr.__proto__ == Array.prototype); //true
console.log(Array.prototype.__proto__ == Object.prototype); //true
console.log(Array.prototype == Object.__proto__); //false
//函数
function User() {}
let u1 = new User();
let u2 = new User();
console.log(u1.__proto__ === u2.__proto__); //true
console.log(u1.__proto__ === User.__proto__); //false
console.log(User.prototype === u1.__proto__); //true
console.log(User.prototype.__proto__ === Function.prototype.__proto__); //true
console.log(User.__proto__ === Function.prototype); //true
console.log(User.__proto__ === Function.__proto__); //true
console.log(Object.__proto__ == Function.prototype); //true
console.log(Function.prototype == Function.__proto__); //true
console.log(Function.prototype.__proto__ === Object.prototype); //true
console.log(Function.__proto__.__proto__ === Object.prototype); //true
console.log(User.constructor === Function); // true
console.log(Object.constructor === Function); // true
console.log(Function.constructor === Function); // true
数组比较好理解,但函数比较特殊,下面是函数的两张图示:
4.练习题
let F = function() {}
Object.prototype.a = function() {
console.log('a()')
}
Function.prototype.b = function() {
console.log('b()')
}
let f = new F()
f.a() // a()
f.b() // b is not a function(报错)
F.a() // a()
F.b() // b()