Javascript 如何将方法添加到对象的原型中

Javascript 如何将方法添加到对象的原型中,javascript,Javascript,有许多方法可以创建对象。然而,我想知道为什么我在尝试学习这种方法时会出现错误——错误消息中的“未定义”是什么意思? 问题与对象第一次实例化的方式无关,因为我尝试了var Obj={};得到了同样的结果。 Thx OP的有趣示例值得仔细检查,以便更好地掌握产生的错误以及如何改进代码 将null传递给Object.create会生成一个未定义的对象,从而导致错误发生。修正涉及传递原型对象,例如对象。结果:Obj拥有一个有效的定义对象,该对象具有对象原型的所有方法 变量描述符包含一个有效对象,其原型可

有许多方法可以创建对象。然而,我想知道为什么我在尝试学习这种方法时会出现错误——错误消息中的“未定义”是什么意思? 问题与对象第一次实例化的方式无关,因为我尝试了var Obj={};得到了同样的结果。 Thx


OP的有趣示例值得仔细检查,以便更好地掌握产生的错误以及如何改进代码

将null传递给Object.create会生成一个未定义的对象,从而导致错误发生。修正涉及传递原型对象,例如对象。结果:Obj拥有一个有效的定义对象,该对象具有对象原型的所有方法

变量描述符包含一个有效对象,其原型可以作为descriptor.constructor.prototype访问。有关构造函数的更多信息

向Obj添加属性的语句是正确的,但用处有限。它将属性直接添加到Obj,而不是其原型。因此,将方法f添加到原型中是很尴尬的,因为它只能访问特定对象Obj的属性p0,因为该属性不属于Obj的原型。最终语句表明,当执行以下代码时,方法f相对于Obj正确工作:

"严格使用",; //创建未定义的对象 var Obj=Object.createnull; console.logObj是+Obj.constructor; //实例化Object类型的Obj Obj=Object.create对象; console.logObj现在是对象的实例?+对象的Obj实例; 变量描述符={ 值:37,可写:true,可枚举:true,可配置:true}; //直接将属性添加到对象Obj Object.definePropertyObj,'p0',描述符; //向Obj原型添加新方法 Obj.prototype.f=函数{ 返回hello+Obj.p0; };
console.logObj.f OP的有趣示例值得仔细检查,以便更好地掌握产生的错误以及如何改进代码

将null传递给Object.create会生成一个未定义的对象,从而导致错误发生。修正涉及传递原型对象,例如对象。结果:Obj拥有一个有效的定义对象,该对象具有对象原型的所有方法

变量描述符包含一个有效对象,其原型可以作为descriptor.constructor.prototype访问。有关构造函数的更多信息

向Obj添加属性的语句是正确的,但用处有限。它将属性直接添加到Obj,而不是其原型。因此,将方法f添加到原型中是很尴尬的,因为它只能访问特定对象Obj的属性p0,因为该属性不属于Obj的原型。最终语句表明,当执行以下代码时,方法f相对于Obj正确工作:

"严格使用",; //创建未定义的对象 var Obj=Object.createnull; console.logObj是+Obj.constructor; //实例化Object类型的Obj Obj=Object.create对象; console.logObj现在是对象的实例?+对象的Obj实例; 变量描述符={ 值:37,可写:true,可枚举:true,可配置:true}; //直接将属性添加到对象Obj Object.definePropertyObj,'p0',描述符; //向Obj原型添加新方法 Obj.prototype.f=函数{ 返回hello+Obj.p0; };
console.logObj.f 所以,基本上,我认为这归结为对原型的根本误解。对象的单个实例没有.prototype,而是有一个指向从中创建对象实例的构造函数原型的内部链接。这以前被称为。_uproto__;AKA dunder proto,但后来被正式弃用

最近,要引用对象实例的构造函数原型,可以访问名为.constructor的属性*注意*:。构造函数可能未定义,具体取决于对象的创建方式。从这里,您可以访问.prototype

类似地,可以使用Object.getPrototypeOfobj和Object.setPrototypeOfobj,其中obj是对象的实例

例如:

var x=Object.createnull; console.logx.prototype,x.prototype; var y=Object.create{a:foo};
console.logic.prototype:,y.prototype 所以,基本上,我认为这归结为对原型的根本误解。对象的单个实例没有.prototype,而是有一个指向从中创建对象实例的构造函数原型的内部链接。这以前被称为。_uproto__;AKA dunder proto,但后来被正式弃用

最近,要引用对象实例的构造函数原型,可以访问名为.constructor的属性*注意*:。构造函数可能未定义,具体取决于对象的创建方式 ed.从这里,您可以访问.prototype

类似地,可以使用Object.getPrototypeOfobj和Object.setPrototypeOfobj,其中obj是对象的实例

例如:

var x=Object.createnull; console.logx.prototype,x.prototype; var y=Object.create{a:foo};

console.logic.prototype:,y.prototype;这意味着Obj.prototype未定义。可能是@barmar的副本,谢谢。为什么没有定义?原型不是隐式创建的吗?@NoChance使用object创建对象。创建传入的参数是对象的原型。此选项为对象或空。您已传入null,在本例中它将其视为未定义。@无更改,因为默认情况下只有使用.prototype属性创建的函数对象。这意味着Obj.prototype未定义。可能与@barmar重复,谢谢。为什么没有定义?原型不是隐式创建的吗?@NoChance使用object创建对象。创建传入的参数是对象的原型。此选项为对象或空。您传入了null,在本例中它将其视为未定义。@无更改,因为默认情况下只有使用.prototype propertyThank创建函数对象。Obj.p0=描述器对我来说确实是新的!不完全是,f应该在Obj的原型上,而不是Obj本身。Obj.hasOwnPropertyf应为false@mhodges,你又对了。该代码仅适用于一个对象。你可能想把你的评论放在一个答案中。这会把Obj从一个普通的对象变成一个构造函数。不确定OP是否需要感谢大家的评论;我们已经相应地修改了代码,所以这应该是一个很大的改进。谢谢。Obj.p0=描述器对我来说确实是新的!不完全是,f应该在Obj的原型上,而不是Obj本身。Obj.hasOwnPropertyf应为false@mhodges,你又对了。该代码仅适用于一个对象。你可能想把你的评论放在一个答案中。这会把Obj从一个普通的对象变成一个构造函数。不确定OP是否需要感谢大家的评论;我们已经相应地修改了代码,所以这应该是一个很大的改进。感谢您对问题的详细解释。总有一天,我可能会明白这种语言是如何工作的。请删除任何关于不推荐的proto getter/setter的提及。不,对象本身没有_proto _,它们有一个内部原型链链接-通常称为[[prototype]]。应该始终使用Object.getPrototype来访问它。@Bergi True,我认为这是一个语义问题,这就是为什么我没有说_proto_____属性的原因。你说得对,原型只是一个内部原型链链接。你关于它被弃用的观点是正确的,我只是用它作为例子来说明区别。说getPrototype when.prototype是未定义的可能会很混乱。不过,为了将来的读者,我会用你的建议更新我的帖子。@mhodges y确实有一个原型。但是,它是其构造函数的一个属性。试试这个:console.logic.constructor.prototype==Object.prototype@我不同意。y指向一个原型,但它本身并不拥有一个原型。因此,在不更改对象构造函数的原型的情况下,您无法更改对象实例的原型-它只能通过其构造函数引用。感谢您对该问题的详细解释。总有一天,我可能会明白这种语言是如何工作的。请删除任何关于不推荐的proto getter/setter的提及。不,对象本身没有_proto _,它们有一个内部原型链链接-通常称为[[prototype]]。应该始终使用Object.getPrototype来访问它。@Bergi True,我认为这是一个语义问题,这就是为什么我没有说_proto_____属性的原因。你说得对,原型只是一个内部原型链链接。你关于它被弃用的观点是正确的,我只是用它作为例子来说明区别。说getPrototype when.prototype是未定义的可能会很混乱。不过,为了将来的读者,我会用你的建议更新我的帖子。@mhodges y确实有一个原型。但是,它是其构造函数的一个属性。试试这个:console.logic.constructor.prototype==Object.prototype@我不同意。y指向一个原型,但它本身并不拥有一个原型。因此,如果不更改对象构造函数的原型,就无法更改对象实例的原型-只能通过其构造函数引用它。
'use strict';
 var Obj=Object.create(null);
 var descriptor={
    value: 37, writable: true, enumerable: true, configurable: true};
 Object.defineProperty(Obj, 'p0' , descriptor);   
 // Next line causes an error: Cannot set property 'f' of undefined
 Obj.prototype.f = function() { //define a method f() on Obj PROTOTYPE
        return (`hello ${this.p0}`); 
  };
 console.log(Obj.f());