在我的工作中,我有时会看到原型和__proto__,我总是将它们与圆圈进行比较。但是我决定通过查阅相关资料进行总结加深理解,请指出错误的地方。
与__proto__属性相关的两个方法确定该属性是存在于实例对象中还是原型对象中。有几种方法可以获取或遍历对象中的属性。1.原型
每个函数都有一个原型属性,它是一个指向对象的指针。此对象的目的是包含特定类型的所有实例共享的属性和方法。使用此对象的优势在于,所有实例对象都可以共享其拥有的属性和方法
2、__原型_ _
每个实例对象都有一个__proto__属性,它指向构造函数的原型对象。当调用构造函数创建实例对象时,会生成__proto__属性。
功能人员(姓名、年龄、工作){ this.name=namethis.age=年龄;this.job=jobthis . SayName=function(){ console . log(this . name);};//逻辑上等价于声明的函数} var person 1=new person(' Nicholas ',29,'软件工程师');console . log(person 1);控制台日志(人);console . log(person 1 . prototype);//undefinedconsole.log(person1。_ _ proto _ _);控制台.日志(person . prototype);console.log(person1。_ _ proto _ _===person . prototype);//true输出结果如下:
总结:
1.通过调用构造函数创建的实例对象的prototype属性是“undefined”,构造函数的prototype是一个对象。
2.当调用构造函数创建实例对象时,会生成__proto__属性。
3.通过调用构造函数创建的实例对象的__proto__属性指向构造函数的原型。
4.默认情况下,所有原型对象都将自动获得一个构造函数属性,该属性包含一个指向原型属性的函数的指针。
下图显示了使用Person构造函数创建实例后对象之间的关系
上图展示了Person的构造函数、Person的原型属性以及Person的两个现有实例之间的关系。
3.与__proto__属性相关的两种方法
虽然在所有实现中,isPrototypeOf():都不能访问__proto__对象,但是可以通过isPrototypeOf()方法确定对象之间是否存在这样的关系。
alert(person . prototype . is rototype of(person 1));//true alert(person . prototype . is rototype of(person 2));//true object . getprototypeof():在所有支持的实现中,此方法返回__proto__的值。例如:
alert(object . getprototypeof(person 1)=person . prototype);//真正的警报(Object.getPrototypeOf(person1))。姓名);//‘Nicholas’注意:虽然原型中存储的值可以通过对象实例访问,但是原型中的值不能通过对象实例覆盖。如果我们在实例中添加一个与实例原型中的属性同名的属性,我们将在实例中创建该属性,这将屏蔽原型中的属性。请参见以下示例:
函数Person(){ } Person . prototype . name=' Nicholas ';person . prototype . age=29;Person.prototype.job=“软件工程师”;person . prototype . SayName=function(){ alert(this . name);};var Person 1=new Person();var Person 2=new Person();person 1 . name=' Greg ';alert(person 1 . name);//“Greg”——来自实例警报(person 2 . name);//‘尼古拉斯’——来自原型4。要判断实例对象或原型对象中是否存在属性,有以下方法
HasOwnProperty():可以检测实例或原型中是否存在属性。返回值为true表示该属性存在于实例对象中,否则为false。
在运算符:中,属性是否存在于实例或原型中。只要存在于对象中,就会返回True。但是,您可以同时使用hasOwnProperty()方法和in运算符来确定该属性是存在于对象中还是原型中。
var Person 1=new Person();var Person 2=new Person();警报(人员1。hasown属性(' name ');//假警报(“人员1”中的名称');//真人1。名字='格雷格';警报(人员1。姓名);//'格雷格'——来自实例警报(人员1。hasown属性(' name ');//真实警报('人1中的名称');//真警戒(第二人。姓名);//'尼古拉斯'——来自原型警报(人员2。hasown属性(' name ');//假警报(' person2中的名称');//真删除人1。姓名;警报(人员1。姓名);//'尼古拉斯'——来自原型警报(人员1。hasown属性(' name ');//假警报(“人员1”中的名称');//true5、获取或遍历对象中属性的几种方法
供入:通过语句循环的返回的是能够被访问的、可枚举的属性,不管该属性是在实例中,还是存在原型中。
功能人员(姓名、年龄、工作){ this.name=namethis.age=年龄;this.job=job}人。prototype={ SayName : FuncTion(){ return this。姓名;} } var p=新人员('李明',30,'诗人');for(p中的var prop){控制台。原木(道具);//姓名、年龄、职务、姓名}控制台。日志(对象。key(p));//['姓名','年龄','工作]控制台。日志(对象。钥匙(人。原型));//['说出名字']控制台。日志(对象。getownpertynames(person。prototype))/[' constructor ',' sayName'] Object.keys():取得实例对象上所有可枚举的属性对象。getowntpropertynames():获取实例对象所有属性,无论它是否可枚举。
注意:使用对象字面量来重写整个原型对象时,本质上完全重写了默认的原型对象,因此构造器属性也就变成了新对象的构造器属性(指向目标构造函数),不再指向人。但是可以通过在重写原型对象时指定构造器属性,使之还是指向原来的建造者。此时,尽管实例f操作符还能返回正确的结果,但通过构造器已经无法确定对象的类型了。
施工方:的对象实例检测构造器。原型是否存在于参数目标的原型链上。
函数Person(){ } var朋友2=new Person();人。原型={//构造函数:人,名字: '尼古拉斯',年龄: 29,job: '软件工程师',说出名字: function(){ alert(这。姓名);} };var friend=new Person();对象的朋友2实例;//真控制台。日志(人的朋友2实例);//false,控制台。日志(朋友2。构造函数==Person);//真控制台。日志(朋友2。构造函数==Object);//false console.log(对象的朋友实例);//真控制台。日志(人的朋友实例);//真控制台。日志(朋友。构造函数==Person);//假控制台。日志(朋友。构造函数==Object);//真由于原型的动态性,调用构造函数时会为实例添加一个指向最初原型的原型指针,而把原型修改为另外一个对象就等于切断了构造函数与最初原型之间的联系。看下面的例子
函数Person(){ } var friend=new Person();人。原型={构造函数: Person,姓名: '尼古拉斯',年龄: 29,职务:‘软件工程师’,说出名字: function(){ alert(这个。姓名);} };var friend 2=new Person();朋友。SayName();//未捕获类型错误:朋友,说名字不是函数朋友2。说出名字();//尼古拉斯控制台。日志(人的好友实例);//false console.log(对象的朋友实例);//真控制台。日志(人的朋友2实例);//真结果分析:这是因为朋友一的原型指向的是没重写人物原型之前的人。原型,也就是构造函数最初的原型对象。而朋友2的原型指向的是重写人物原型后的人。原型。如下图所示
6、 原型链
基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。最直观的表现就是让原型对象等于另一个类型的实例。
function SuperType(){ this . property=true;} SuperType . prototype . GetSuperVaLue=function(){ return this . property;};function SubType(){ this . subparty=false;}//继承的supertypesubtypeprototype=new super type();subtype . prototype . getsubvalue=function(){ return this . subproperty;};var实例=new SubLe();alert(instance . GetSuperVaLue());//TrueSubType . prototype=new SubType();这段代码使父类型实例中存在的所有属性和方法现在都存在于SubType.prototype中。使实例的构造函数指向父类型。
console . log(instance . constructor===SuperType);//true summary:访问实例属性时,首先在实例中搜索属性。如果找不到属性,将继续搜索实例的原型。当通过原型链实现继承时,搜索过程可以沿着原型链向上继续。当找不到属性或方法时,搜索过程总是在停止之前一个接一个地到达原型链的末尾。
以上面的例子为例,调用instance.getSuperValue()将经历四个搜索步骤:
搜索实例实例;Search SubType.prototype;搜索父类型的实例;搜索SuperType.prototype,最后一步就能找到方法。以上就是本文的全部内容。希望对大家的学习有帮助,支持我们。