手机版

向我学习原型 getPrototypeOf javascript和__proto__

时间:2021-09-22 来源:互联网 编辑:宝哥软件园 浏览:

对原型、getPrototypeOf和_ proto _的深刻理解。

Prototype、getPropertyOf和_ proto _是访问prototype的三种方法。它们的命名方式相似,很容易混淆。

它们的用法如下:

C.prototype:通常用于为类型建立其原型继承对象。例如C.prototype=xxx,这样通过使用new C()得到的对象的原型对象就是xxx。当然,使用obj.prototype也可以得到obj的原型对象。Getpropertyof:object。getpropertyof (obj)是ES5中用来获取obj对象原型对象的标准方法。_ proto _: obj。_ proto _是获取obj对象原型对象的非标准方法。为了全面了解获取原型的各种方法,以下是一个示例:

函数User(name,password hash){ this . name=name;this . password hash=password hash;} User . prototype . tostring=function(){ return '[User ' this . name ']';};user . prototype . checkpassword=function(password){ return hash(password)==this . password hash;};var u=新用户(' sfalken ',' 0ef 33 AE 791068 EC 64 b 502d 6cb 0191387 ');用户函数有一个默认的原型属性,其值是一个空对象。在上面的例子中,两个方法被添加到原型对象中,即toString和checkPassword。当调用用户构造函数来获取一个新的对象u时,它的原型对象将被自动分配给User.prototype对象。也就是说,u.prototype===User.prototype将返回true。

用户函数、用户原型和对象u之间的关系可以表示如下:

上图中的箭头表示继承关系。当访问一个U对象的一些属性时,你会首先尝试读取U对象上的属性,如果U对象上没有这样的属性,你会找到它的原型对象。

例如,当调用u.checkPassword()时,因为checkPassword是在其原型对象上定义的,所以在u对象上找不到该属性,所以按照u- u.prototype(User.prototype)的顺序在u的原型上搜索。

如前所述,getPrototypeOf方法是ES5中用来获取对象原型对象的标准方法。因此:

object . getprototypeof(u)===user . prototype;//true在某些环境中,还提供了一个非标准的_ proto _ attribute来获取对象的原型对象。当环境没有提供ES5的标准方法getPrototypeOf方法时,可以临时使用这个属性来代替。您可以使用以下代码来测试环境中是否支持_ proto _ 1:

单位_ _ proto _ _===User.prototype//true因此在JavaScript中,类的概念是由构造函数(User)和原型对象(User.prototype)完成的,用于在实例之间共享方法。构造函数负责构造每个对象的唯一属性,例如上面示例中的名称和密码属性。原型对象负责存储所有对象共有的属性,例如上面例子中的checkPassword和toString方法。如下图所示:

其次,首先使用Object.getPrototypeOf而不是_ proto _来获取对象。

在ES5中,Object.getPrototypeOf被引入作为获取原型对象的标准API。但是,在许多执行环境中,会提供一个特殊的_ proto _ attribute来实现相同的目的。

因为不是所有的环境都提供这个_ proto _ attribute,并且每个环境的实现方式都不同,所以有些结果可能不一致,例如,对于具有空原型的对象:

//在某些环境中,var empty=object . create(null);//空中没有原型“_proto _”的对象;//false(在某些环境中)//var empty=Object.create(null)在某些环境中;//空中没有原型“_proto_”的对象;//true(在某些环境中)所以当环境支持Object.getPrototypeOf方法时,最好使用它。即使不支持,也可以实现:

if(type of object . getprototypeof==' undefined '){ object . getprototypeof=function(obj){ var t=type of obj;if(!obj || (t!=='object' t!==' function '){引发新的TypeError('不是对象');}返回obj。_ proto _};}上面的代码将首先检查当前环境,如果已经支持Object.getPrototypeOf,就不会再定义了。

第三,永远不要修改_ proto _。

与Object.getPrototypeOf相比,_ proto _的特殊之处还在于它可以修改对象的原型继承链。因为是属性,所以除了获取它的操作之外,还可以进行设置。

但是,千万不要修改_ proto _。原因如下:

首先,最明显的原因是便携性。因为不是所有的JavaScript执行环境都支持这个属性,所以在使用_ proto _后,代码不能在不支持_ proto _的环境中运行。其次是性能考虑。如今,JavaScript引擎的实现对访问对象属性进行了大量的优化,因为这些操作是最常用的。当对象的_ proto _被修改时,它相当于修改了对象的整个继承结构,这导致许多优化不再可用。最后,最重要的原因是需要保证程序的可靠性。因为在更改了_ proto _ property之后,对象的原型继承链可能会完全改变。当程序中的其他代码依赖于原始继承链时,会出现意外错误。一般来说,原型继承链需要稳定。当需要将原型对象分配给新创建的对象时,可以使用ES5提供的Object.create方法。对于不实现ES5标准的环境,可以给出不依赖于_ proto _的Object.create方法的实现。

第四,解决_ proto _的兼容性问题,让构造函数不再依赖新的关键字。

当使用函数作为构造函数时,有必要确保通过new关键字调用函数。

函数User(name,password hash){ this . name=name;this . password hash=password hash;}如果在调用上述构造函数时忘记使用new关键字,那么:

var u=User(' bara veli ',' d8b 74 df 393528d 51 CD 19980 AE 0aa 028 e ');u;//未定义this.name//' bara veli ' this . passwordhsh;//' d8b 74 df 393528d 51 CD 19980 a e0aa 028 e '您可以发现获得的u是未定义的,而this.name和this.passwordHash是赋值的。但这里指的是全局对象。

如果构造函数被声明为依赖于严格模式:

函数User(name,passwordshash){ '使用strict ';this.name=namethis . password hash=password hash;} var u=User(' bara veli ',' d8b 74 df 393528d 51 CD 19980 AE 0aa 028 e ');//error:这是未定义的,因此当您忘记使用new关键字时,在调用this.name=name时将引发TypeError错误。这是因为在严格模式下,这个的默认点将被设置为undefined,而不是全局对象。

那么,有没有办法保证在调用一个函数的时候,不管有没有使用new关键字,这个函数都可以看作是一个构造函数呢?下面的代码是使用instanceof操作的实现:

函数User(name,passwordshash){ if(!(用户的此实例){返回新用户(名称,密码哈希);} this.name=namethis . password hash=password hash;} var x=User(' bara veli ',' d8b 74 df 393528d 51 CD 19980 AE 0aa 028 e ');var y=新用户(' baravelli ',' d8b 74 df 393528d 51 CD 19980 AE 0aa 028 e ');用户的x实例;//用户的真实实例;//如果高于true的代码块用于处理不使用new进行调用的情况。当不使用new时,它不会指向User的实例,但是当使用new关键字时,它会指向User类型的实例。

更适合在ES5环境中使用的另一个实现如下:

函数User(名称,密码哈希){ var self=User的这个实例?这个:对象。创建(用户。原型);self.name=nameself . password hash=password hash;回归自我;} Object.create方法是ES5提供的方法,可以接受一个对象作为新创建对象的原型。然后,在非ES5环境中,您需要实现一个对象。

if(type of object . create===' undefined '){ object . create=function(prototype){ function C(){ } C . prototype=prototype;返回新的C();};}事实上,Object.create方法有一个版本,它接受第二个参数,该参数表示分配给新创建的对象的一系列属性。

当用new调用上述函数时,可以正确获得新创建的对象。感谢构造函数覆盖模式。这种模式的含义是,使用new关键字的表达式的返回值可以被显式返回覆盖。与上面的代码一样,return self用于显式定义返回值。

当然,上述工作在某些情况下是不必要的。然而,当一个函数需要作为构造函数被调用时,必须解释它。这是一种使用文档的方式,也是一种用大写字母命名函数的方式(基于JavaScript语言的一些约定)。

以上是对javascript的原型、getPrototypeOf和__proto__的深入研究,希望对大家的学习有所帮助。

版权声明:向我学习原型 getPrototypeOf javascript和__proto__是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。