关于JS中的原型
任何函数都有prototype;
任何对象都有__proto__;
函数原型也是对象,它除了__proto__,还有一个特殊的constructor。这可能是原型对象和实例对象的区别所在。如果重写了原型,那么constructor就不存在了。但是,原型链上的某一个原型对象总会有constructor
construcor不咋重要,最重要的是__proto__,只要是对象,就有proto
1.每个函数都会创建一个prototype属性,这个属性指向一个对象,包含应该由特定引用类型的实例共享的属性和方法。
(只要三个函数,就比如会附带出现一块对象储存区,链接名为prototype,一定要记住这一点。也就是说,函数,除了arguments等独特的属性,还有一个prototype。对象通过constructor属性指向函数,这样就形成了闭环。函数的prototype->对象,对象contructor->函数。每一个函数都有prototype,每一个对象都有contructor。函数和对象是共生关系,没有无对象的函数,也有离开函数的对象。)
2.对象来源于构造函数。通过new实现。一个函数new以后,就会产生一个实例,实际上也是对象。函数的prototype属性也会传给实例,在实例里面,这个属性叫[[Prototype]],它也指向函数的原型。也就说,所有的函数都有prototype,所有的对象都有contructor和[[Prototype]],这个[[Prototype]]可以通过别名__proto__访问。
3.经过new生成的对象叫实例,这个对象也有contructor和__proto__,contructor指向构造函数,__proto__指向构造函数的原型对象。
4.原型对象也是对象。它也有constructor和__proto__。原型对象的contructor回指向构造函数,但是原型对象的__proto__指向哪里呢?跟实例一样,谁造就它,它就指向谁的原型。一般情况下,对象的生产者都是Object构造函数,因此,自定义函数的原型都指向Object的原型对象。那么Object的原型对象的__proto__又指向谁呢?到根上了,没地方可指向,就给它赋值null.
5.还有一点必须理解。实例与构造函数之间没有直接联系,实例直接联系的是构造函数的原型对象。举个例子,构造函数把实例生出来后就不管他了,而是交给奶妈原型对象去抚养了。
6.凡是都有例外,在js里, 有一个创建对象的方法Object.create(null),会创建一个新对象,真正的无父无母独立遗世,创建出的对象没有__proto__,空空如也。
7.Object.getOwnPropertyNames(),用这个方法可以查看对象的属性和方法,不管是实例还是原型,不管是可枚举还是不可枚举,都可以列出来,是一个很有用的方法。比如,Object.getOwnPropertyNames(Function.prototype),可以调出所有原生构造函数Function的原型对象中定义的属性和方法,以数组形式返回: ['length', 'name', 'arguments', 'caller', 'constructor', 'apply', 'bind', 'call', 'toString'],其中toString属于对Object原型方法的重写。再比如,Object.getOwnPropertyNames(Array.prototype),可以调出所有原生构造函数Array的原型对象中定义的属性和方法: