三个东西真的很常见,但是看到就烦,为了让自己心情好点,索性好好琢磨一下。
__proto__ 是为了找对象的原型,继续找原型的原型,最终为null,是
真正的原型链
。里面会有js默认的对象属性和方法,普通函数和构造函数都可以直接用。可以把它理解为一种结构形式的链式关系。看下图prototype 是构造函数继承链,也就是说只有在构造函数中才会有,通过它找到原型对象。(所有才会有原型函数可以直接调用prototype:对象.prototype。只是用于构建用new
关键字创建的对象,将构造器函数的prototype的引用指向
于构建的对象的__proto__。
但它们并不同,构造函数的prototype其实是指向Function对象的Prototype,Function对象的Prototype和__proto__是相同的,所以它们的关系是间接的
看下图
constructor 是为了找原型的方法和属性,便于继承。在普通函数和构造函数中都有。new一个对象后,它的constructor会是原型对象本身,并循环嵌套不止。看下图
根据上面的console,大概是这样的关系:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
function Person(name,age) { this.name=name; this.age=age; this.sayHello = function () { console.log(this.name+' say hello') } } function Person2(name,age) { this.name=name; this.age=age; } Person2.prototype.sayHello = function(){ console.log(this.name + " say hello"); } //prototype是可以被继承的,所以可以通过“实例化对象.sayHello”来执行。但是如果 Person2.sayHello = function(){ console.log(this.name + " say hello"); } //实例化对象.__proto__.constructor.sayHello()。其实不管能否访问,总归就是不方便 |
其实上面的理解比较简单粗暴,我是直接通过打印结果来区分的
1 2 3 4 5 6 7 |
let a = new Person; console.log(a.__proto__ === Person.prototype) //true 对象a的__proto__值取自构造函数Person的prototype值 console.log(a.constructor === Person); //true 对象a的构造函数是Person console.log(Person.prototype.constructor === Person); //true |
这里有个小总结:
1、我们需要牢记两点:①__proto__和constructor属性是对象所独有的;② prototype属性是函数所独有的,因为函数也是一种对象,所以函数也拥有__proto__和constructor属性。(从上面的截图可以看出来)
2、__proto__属性的作用就是当访问一个对象的属性时,如果该对象内部不存在这个属性,那么就会去它的__proto__属性所指向的那个对象(父对象)里找,一直找,直到__proto__属性的终点null,然后返回undefined,通过__proto__属性将对象连接起来的这条链路即我们所谓的原型链。
3、prototype属性的作用就是让该函数所实例化的对象们都可以找到公用的属性和方法,即a.__proto__ === Persion.prototype。
4、constructor属性的含义就是指向该对象的构造函数,所有函数(此时看成对象了)最终的构造函数都指向Function。
参考
:https://blog.csdn.net/cc18868876837/article/details/81211729
https://www.cnblogs.com/me10zyl/p/5549215.html