目录
prototype和__proto__的属性联系和区别
constructor属性
关系图
首先我们知道js中函数也是属于对象的,所以Array、String、Boolean、Function、Object这些系统定义好的函数上也是对象,上面有一些定义好了属性像__proto__、prototype和constructor等。
以下说的函数和对象是通过typeof()的结果分开看,且不讨论Object.creat(null)的情况,下面只要是===都是可以完全当数学变量互相替换的,文中A指申明的函数,a指通过A构造出来的对象。
1.对象上是没有prototype的属性的,只有函数上才有,而__proto__属性函数和对象上都有。
2.prototype、__proto__的指向都是对象。
3.对象上的继承即我们通过查找原对象上不存在的属性时,我们会在该对象的属性__proto__所指向的对象去寻找,并可以依次类推查找这个对象上的下一个__proto__属性指向的对象,并把这样一个链接状态称为原型链。而我们在使用构造函数创建对象时会隐式的将__proto__=prototype。这也是为什么每个对象上为什么会有__proto__属性以及能通过设置构造函数的prototype或设置对象的__proto__属性来继承对象。(如果是设置prototype,我们需要注意顺序,先设置构造函数再利用构造函数创建对象,如果是设置__proto__属性,那就可以直接在对象上设置,设置的内容会在添加在原有的__proto__属性上添加,不会替换。)
4.Array/String/Boolean/Object/Function.prototype各自上都有一些定义好了的方法,属性。我们在新建对象时,会隐式的调用__proto__=prototype,所以能从相对应的函数中继承系统中不同的的方法和属性,注意这些prototype属性是各不相同的。例如var a=String(‘a’)。我们能直接使用a.length查看字符串对象的长度,这个length属性就是在String.prototype上定义好的,使用时能在a.__proto__指向的对象上找到该方法。然后这里我们有一条计算机定义好了的,Array/String/Boolean/Function.prototype.__proto__===Object.prototype(可以理解为大家都是对象,所以都继承制Object.prototype)
5.我们在系统中还有已经定义好的__proto__属性。Array/String/Boolean/Object/Function.__proto__===Function.prototype;Object.prototype.__proto__===null(所以称Object.prototype为原型链的终端)。
6.我们申明的函数的__proto__属性===Function.__proto__(比如function A(){};A.__proto__===Function.__proto__),而prototype属性指向一个对象,这个对象只等于本身,可以修改的,但他的__proto__属性===Object.prototype(即A.prototype.__proto__===Object.prototype),注意A.prototype!==Function.prototype(可以说prototype属性指向的对象除了Function.prototype和Object.prototype其他的都是除了自己谁都不等于)
以上可以总结为3点:
A.所有函数的__proto__属性等于Function.prototype(包括Function本身和申明的函数,相当于都继承至Function.prototype,即A/Array/String/Boolean/Object/Function.__proto__===Function.prototype)。
B.Function.prototype.__proto__===Object.prototype。(Object.prototype为原型链的终端,可以得出一个有意思的结论Object.__proto__.__proto__===Object.prototype,像A/Array/String/Boolean/Function都是不等于的,如果只替换左边的Object是等于的)
C.构造函数创建对象时会隐式的将__proto__=prototype(即a.__proto__=A.prototype)
举例:
function A(){};
var a = new A();
通过这2句代码,我们就可以得到以下信息:首先通过A我们可以得到:
1.A/Array/String/Boolean/Object.__proto__===Function.__proto__;
(A/Array/String/Boolean.prototype不等于谁咱不考虑。然后注意对象上是没有prototype属性的。)
然后我们根据A+B的条件能推出
2.A.prototype.__proto__===Object.prototype===Array/String/Boolean/Object/Function.__proto__.__proto__
最后在加上C点a.__proto__===A.prototype,那么我们又可以推出
3.a.__proto__.__proto__===Object.prototype===Array/String/Boolean/Object/Function.__proto__.__proto__
这样关于__proto__和prototype属性咱就讲完了,这些大家可以通过代码去验证,都是个人的理解,有什么问题或题目欢迎讨论。
———————————————————————————————————————————————
然后再讲讲constructor属性。这个比较好理解,他和其他属性的关联不大,咱单独讲,他就是字面意义,谁构造了他,比如Array/String/Boolean/Object/Function这些都是函数,那么他的构造者就是Function,而对象咱看他是由谁构造的。
总结:
函数的constructor属性指向
1.所有函数的constructor属性都指向Function(包括他本身和申明的函数,即A/Array/String/Boolean/Object/Function.constructor===Function)。
2.所有函数的prototype指向的对象的constructor属性都指向本身(A/Array/String/Boolean/Object/Function.prototype.constructor===A/Array/String/Boolean/Object/Function)
然后咱再来看对象的constructor属性指向
3.谁构造的对象的函数指向谁,比如通过new Number(‘1’)构造的对象,那么他的constructor便指向Number函数,再比如new String(‘a’),那么他的constructor便指向String。(直接通过字面量即={}的创建对象的方式,那么他的constructor指向Object)
至于__proto__指向对象的constructor,我们可以通过上文中的__proto__和prototype的联系转化成prototype来求他的constructor。比如申明函数A.__proto__.constructor,通过上面第A条A.__proto__===Function.prototype,那么A.__proto__.constructor===Function.prototype.constructor===Function,这些咱都可以完全像数学变量一样代换的。咱还可以推一些好玩的,大家可以自己去验证,比如:
对象a.__proto__===A.prototype,a.__proto__.__proto__===Object.prototype,那么a.__proto__.__proto__.constructor===Object,
然后Array.__proto__===Function.__proto__===Function.prototype,那么Array.__proto__.constructor===Function,
再然后Array.__proto__.__proto__===Object.prototype,那么Array.__proto__.__proto__.constructor===Object,又可以推出Array.__proto__.__proto__.constructor===a.__proto__.__proto__.constructor同理咱还可以得出A/Array/String/Boolean/Object/Function.__proto__.__proto__.constructor===a.__proto__.__proto__.constructor===Object。
这样关于constructor属性咱就讲完了,这些大家可以通过代码去验证,都是个人的理解,有什么问题或题目欢迎讨论。
———————————————————————————————————————————————
最后我们这里还有一张借用的别人的关系图来方便大家理解:
———————————————————————————————————————————————————————————————————————————————————————————
以上都是个人的理解总结,不喜勿喷,有什么问题或题目欢迎讨论。