Open maicFir opened 2 years ago
原型链是一个比较抽象的概念,每当被问起这个问题时,总会回答得不是那么准确,好像懂,但自己好像又不太懂,真是尴尬了
原型链
正文开始...
我们知道每一个函数都有一个自身的prototype,每一个对象都有__proto__对象,而这个__proto__我们常称之为隐式原型,正因为它连接起了对象与构造函数的关系
prototype
__proto__
隐式原型
当我们访问一个对象时,首先会在自身属性上找,当自身属性找不到时,会到对象的隐士链上去找,如果隐式链上还没有,那么会构造函数的原型上找,当原型上没有时,会到原型的隐式__proto__上去找,当这个属性还找不到时,就直接返回undefined了,因此才形成了一条原型链。
undefined
针对以上一段常常的话,我们用实际例子来佐证一下
function Person() { this.name = 'Maic'; this.age = 18; } Person.prototype.say = function () { return `hello ${this.name}` } const person = new Person();
我们访问
console.log(person.name); // Maic
现在我在原型上找
function Person() { // 1 this.name = 'Maic'; this.age = 18; } // 3 Person.prototype.name = 'Test'; // 4 Person.prototype.__proto__.name = '999' Person.prototype.say = function () { return `hello ${this.name}` } const person = new Person(); // 2 person.__proto__.name = '8888' console.log(person.say());
从结果上来看,会是依次从1,2,3,4依次查找下去,直到最后找不到name为止,然后就打印undefined
1,2,3,4
name
当我们对构造函数实例化的时候,此时就会返回一个对象person,然后这个person对象就可以访问构造函数内部的属性,以及原型上的方法了。
person
这个person对象为什么可以访问构造函数的属性?以及构造函数原型上的方法?
那是因为通过__proto__这个隐式原型指向的构造函数的prototype
在面试中常有问题到,new的过程中发生了啥?
new
1、创建了一个对象
2、将这个对象的__proto__指向了构造函数的prototype
3、执行构造函数内部方法,并改变构造函数内部的this指向到新对象中
4、返回该构造函数的结果
我们根据以上几点,实现一个类似new的操作,从而真正理解new原生的实现
function mynew(Fn, ...arg) { // 1、创建一个对象 const ret = {}; // 2 将这个对象__proto__执行构造函数的prototype ret.__proto__ = Fn.prototype // or // Object.setPrototypeOf(ret, Fn.prototype); const result = Fn.call(ret, ...arg); return typeof result === 'object' ? result : ret; }
我们再重新看下这段代码
看下下面的几个判断
... console.log(person.__proto__ === Person.prototype) // true console.log(Person.__proto__ === Function.prototype) // true console.log(Person.__proto__ === Object.__proto__); // true console.log(Function.prototype === Object.__proto__); // true console.log(Person.prototype.__proto__ === Object.prototype) // true console.log(Object.prototype.__proto__ === null); // true console.log(person.__proto__.__proto__ === Object.prototype) // true console.log(Function.prototype.__proto__ === Object.prototype); // true
上面的关系画了一个图, 可能更直观点
这个图看起来貌似还是不太容易记住,多理解几遍,应该会掌握八九不离十
另外还有一篇github上关于伢羽老师的原型链文章可以一同参考
理解原型链,每一个函数都有一个原型prototype,每一个对象都有自己的隐式__proto__,当我们访问对象属性时,会优先在自己内部属性寻找,然后会找__proto__上的属性,然后会去构造函数的prototype上寻找,如果构造函数的prototype找不到,会到到构造函数prototype的__proto__上寻找,最后找不到该属性就返回undefined
了解new操作背后的本质
了解构造函数与实例对象的关系
本文示例code example
正文开始...
我们知道每一个函数都有一个自身的
prototype
,每一个对象都有__proto__
对象,而这个__proto__
我们常称之为隐式原型
,正因为它连接起了对象与构造函数的关系当我们访问一个对象时,首先会在自身属性上找,当自身属性找不到时,会到对象的隐士链上去找,如果隐式链上还没有,那么会构造函数的原型上找,当原型上没有时,会到原型的隐式
__proto__
上去找,当这个属性还找不到时,就直接返回undefined
了,因此才形成了一条原型链。针对以上一段常常的话,我们用实际例子来佐证一下
我们访问
现在我在原型上找
从结果上来看,会是依次从
1,2,3,4
依次查找下去,直到最后找不到name
为止,然后就打印undefined
当我们对构造函数实例化的时候,此时就会返回一个对象
person
,然后这个person
对象就可以访问构造函数内部的属性,以及原型上的方法了。这个
person
对象为什么可以访问构造函数的属性?以及构造函数原型上的方法?那是因为通过
__proto__
这个隐式原型指向的构造函数的prototype
new过程
在面试中常有问题到,
new
的过程中发生了啥?1、创建了一个对象
2、将这个对象的
__proto__
指向了构造函数的prototype
3、执行构造函数内部方法,并改变构造函数内部的this指向到新对象中
4、返回该构造函数的结果
我们根据以上几点,实现一个类似
new
的操作,从而真正理解new
原生的实现对象与构造函数关系
我们再重新看下这段代码
看下下面的几个判断
上面的关系画了一个图, 可能更直观点
这个图看起来貌似还是不太容易记住,多理解几遍,应该会掌握八九不离十
另外还有一篇github上关于伢羽老师的原型链文章可以一同参考
总结
理解原型链,每一个函数都有一个原型
prototype
,每一个对象都有自己的隐式__proto__
,当我们访问对象属性时,会优先在自己内部属性寻找,然后会找__proto__
上的属性,然后会去构造函数的prototype
上寻找,如果构造函数的prototype
找不到,会到到构造函数prototype
的__proto__
上寻找,最后找不到该属性就返回undefined
了解new操作背后的本质
了解构造函数与实例对象的关系
本文示例code example