第一步
解说:
先说构造函数(1),咱们只要new一下就能得到实例对象(2)
构造函数(1)如何访问到原型(3),很简单通过.prototype
通过实例对象(2),我们如何访问,通过对象.__proto__
方式虽然不同,但是我们拿到的都是同一个对象
代码演示:
function Person(userName, age) {
this.userName = userName
this.age = age
}
var p1 = new Person('猪八戒', 18)
// 这两个相等返回true
console.log(Person.prototype)
console.log(p1.__proto__)
console.log(Person.prototype === p1.__proto__) // true
第二步
图解
prototype(3)本身也是一个对象,既然也是一个对象,那么这个对象就应该有它自己的构造函数(4),因为它也是由构造函数生成的。
那也就是说它也能访问到自己的原型(5)。
这就是JS中最基本的继承机制!
代码演示:
function Person() {
}
Person.prototype = new Object()
new Person().toString() // 从原型上继承过来的
/*
* 我写了这样一个函数,大家告诉我有没有继承发生?
* 继承其实现在已经发生了,你虽然看不见,但是浏览器已经帮我们做过了 Person.prototype = new Object() 这句话我虽然不用写,但是浏览器会帮我们自动添加的
*
* 一上来就new Person().toString(),toString()方法哪来的想过没有?你在函数里写什么?什么也没有写啊,这个toString()继承的不就是Object吗
* 这个就是JS的默认继承(原型继承)
* */
new Object() // 也是一个对象,它虽然现在是Person的原型,可是它本身也是一个对象。所以说这个原型对象是不是也该有自己的原型呢?
console.log(Person.prototype.__proto__ === Object.prototype) // true, 因为Person.prototype 就是一个 new Object() 的实例(Person.prototype = new Object()),我们开始也说了实例对象通过__proto__访问,通过构造函数是通过prototype进行访问,但是他们俩是同一个且他们是绝对等价的
第三步
图解
Object的原型(5),这里依旧是一个对象,那么这里它的构造函数是谁?
如果你找5的构造函数,它其实就是Object,也就是说5这个对象也是new 了 一个 Object ,new出来的,还是它自己的实例。
所以如果你试图在往下找原型,不好意思这边就真的没有了,访问不到了,到达顶层了就会返回null。
链条怎么产生的?链条其实就是2 ->3 -> 5
当你实例化var p1 = new Person()
后,访问p1.age
的时候会先从实例对象(2)里找看一下有没有age这个属性,如果没有找到就沿着自己的原型链条,找到自己的原型(3)去里面看看有没有age属性,找了一圈没发现,继续沿着链条往上找在5中查找,在哪里找到了就断开了继续查找。如果没有找到就返回null