js中proto和prototype的区别和关系?
首先,要明确几个点:
1.在JS里,万物皆对象。方法(Function)是对象,方法的原型(Function.prototype)是对象。因此,它们都会具有对象共有的特点。
即:对象具有属性proto,可称为隐式原型,一个对象的隐式原型指向构造该对象的构造函数的原型,这也保证了实例能够访问在构造函数原型中定义的属性和方法。
2.函数(Function)
函数这个特殊的对象,除了和其他对象一样有上述proto属性之外,还有自己特有的属性——原型属性(prototype),这个属性是一个指针,指向一个对象,这个对象的用途就是包含所有实例共享的属性和方法(我们把这个对象叫做原型对象)。原型对象也有一个属性,叫做constructor,这个属性包含了一个指针,指回原构造函数。
好啦,知道了这两个基本点,我们来看看上面这副图。
1.构造函数Foo()
构造函数的原型属性Foo.prototype指向了原型对象,在原型对象里有共有的方法,所有构造函数声明的实例(这里是f1,f2)都可以共享这个方法。
2.原型对象Foo.prototype
Foo.prototype保存着实例共享的方法,有一个指针constructor指回构造函数。
3.实例
f1和f2是Foo这个对象的两个实例,这两个对象也有属性proto,指向构造函数的原型对象,这样子就可以像上面1所说的访问原型对象的所有方法啦。
另外:
构造函数Foo()除了是方法,也是对象啊,它也有proto属性,指向谁呢?
指向它的构造函数的原型对象呗。函数的构造函数不就是Function嘛,因此这里的proto指向了Function.prototype。
其实除了Foo(),Function(), Object()也是一样的道理。
原型对象也是对象啊,它的proto属性,又指向谁呢?
同理,指向它的构造函数的原型对象呗。这里是Object.prototype.
最后,Object.prototype的proto属性指向null。
总结:
1.对象有属性proto,指向该对象的构造函数的原型对象protptype。
2.函数除了有属性proto,还有属性prototype,指向该函数自己的原型对象。
3.原型对象中还有属性constructor,这个指针指回自己所属的原本的构造函数。
也就是说,原型对象不是自己上一级的,而是属于自己本身的与自己同一级别的对象,这个对象存放共享的属性和方法,而原型对象本身也有一个属性constructor来指回原本的构造函数。而proto则是指向自己的构造函数的原型对象prototype。
原型链
函数,对象,prototype和proto之间的各种指向关系,形成的一条到Object.prototype终止的链就是原型链。
实例:
Object.prototype.a = 'a' //给原型对象添加属性a
Function.prototype.b = 'b' //给构造函数的原型对象添加属性b
a = function () { } // a是一个函数类型,函数的构造函数时Function(),所以a.prototype指向Function.prototype,而Function的构造函数又是Object,所以a同时共享属性 a和b
b = {} //b是一个对象,它的构造函数是Object,所以b.__proto__指向Object.prototype,只继承a
c = [] //c是一个数组对象,它的构造函数是Object,所以b.__proto__指向Object.prototype,只继承a
d = 1 //d是一个数字类型,但也是继承自对象,所以也能取到属性a
console.log(a.a,a.b)
console.log(b.a, b.b)
console.log(c.a, c.b)
console.log(d.a)
输出结果: