Javascript 通过Object.setPrototypeOf()向函数的原型添加属性时,对象为空 让我们考虑下面的代码,
Javascript 通过Object.setPrototypeOf()向函数的原型添加属性时,对象为空 让我们考虑下面的代码,,javascript,object,prototype,Javascript,Object,Prototype,设f=函数(){ 这是a=1; 这是b=2; } 设o=新的f(); f、 原型c=3; log(Object.getPrototypeOf(o))当您Object.setPrototypeOf(f,…)时,链实际上是3长: o的原型是f。f的原型是{c:3} 因此,你们的例子并不完全相同: 1) 在第一个示例中,您将属性c直接添加到f实例将使用的原型中,因此o的原型包含c,因为f是o的构造函数 在最后两个示例中,您将c添加到f的proto中,因此使用创建了原型f。请记住,函数也只是对象,您正在
设f=函数(){
这是a=1;
这是b=2;
}
设o=新的f();
f、 原型c=3;
log(Object.getPrototypeOf(o))
当您Object.setPrototypeOf(f,…)
时,链实际上是3长:
o
的原型是f
。f
的原型是{c:3}
因此,你们的例子并不完全相同:
1)
在第一个示例中,您将属性c
直接添加到f
实例将使用的原型中,因此o
的原型包含c
,因为f
是o
的构造函数
在最后两个示例中,您将c
添加到f
的proto中,因此使用创建了原型f
。请记住,函数也只是对象,您正在设置用作构造函数的函数的原型。因此o
的proto包含f
的proto,其中包含c
2)
在第二个示例中,您获取prototypeof()o
。
在第三步中,您将获得prototypeof()f
。因此,只有第三个示例再次显示c
3)
如果您检查chrome中的元素,您会看到第二个示例的构造函数是f
,因为您询问o
的proto
在第三个示例中,您将看到构造函数是Object
,因为您询问f
的proto,它已设置为Object{c}
,并将proto从o
跳过f
我知道这可能是一个令人困惑的解释
PPS:如果您想要继承,请坚持使用child.prototype=Object.create(parent.prototype);child.constructor=child
或ES6 classclass child扩展父级
时,可以使用它将我个人的困惑降至最低
var first=函数first(){
this.value='第一个函数';
};
//before.prototype.extra,函数的第一个inherist。
log('first-before的构造函数:',first.constructor);
first.prototype.extra='使用.prototype.extra'实现;
//在.prototype.extra之后,first仍然从函数继承,我们没有将任何内容更改为first本身。
log('first after:'的构造函数,first.constructor);
//当第一个被用作原型时,实例将得到“额外的”。
//阿卡,一切从一开始就是天生的。
var first_instance=new first();
log('extra on instance of first:',first_instance.extra);
//f本身没有额外的属性,只有first do的实例。
log('extra on first本身:',first.extra);
console.log('----');
var second=函数second(){
this.value='第二个函数';
};
//在setPrototypeOf之前,函数的第二个inherist,如上所示。
log('console.constructor of second before:',second.constructor);
setPrototypeOf(第二个,{extra:'用.setPrototypeOf()实现);
//在对象的第二个inherist setPrototypeOf之后,我们打破了默认的继承链。
log('console.constructor of second after:',second.constructor);
//通过这样做,我们有效地将秒变成了一个对象。
//它不再是函数,因此我们不能使用.call()或.apply()等函数方法
log('second是对象,而不是函数:function.apply',second.apply);
log('second是object,而不是function:object.hasOwnProperty',second.hasOwnProperty');
//当第二个被用作原型时,实例将不会得到“额外的”。
var second_instance=new second();
log('extra on instance of second:',second_instance.extra);
//second本身确实有额外的属性,因为我们在second使用的原型上分配了它。当使用second作为原型时,则不会。
log('extra on second本身:',second.extra)如果您有obj={}
然后是obj.foo=1
或obj={bar:2}
,则代码>没有太大区别。您正在修改现有对象或替换它o
维护对原始的引用。因此,就添加原型的这两种方式(setPrototypeOf和.prototype)而言,它有什么区别呢?我在回答中对此进行了扩展,但假设上面的代码有obj2=obj
。如果您执行obj.foo=1
操作,您就是在“更改”obj2
,因为它实际上只是对同一对象的新引用。但是obj={bar:2}
将保持obj2
不变,因为现在obj
和obj2
指向不同的对象。哇,我不知道obj={}语法不会修改另一个对象,我知道对象。assign()和用于复制的扩展运算符,但是,请不要阅读这种使对象保持不变的方法,谢谢,现在让我再看看代码。我仍在尝试将其与设置原型的这两种方法联系起来。我遇到的另一件事是,在执行setPrototypeOf()时,它替换了完整的原型属性,其中as.prototype可以添加到它上,这里我可以将您关于引用和复制的解释联系起来感谢您的解释,我会慢慢地看一遍,然后再给你回复。:)在你的句子中我有点困惑,“在第一个例子中,你将属性c直接添加到f实例将使用的原型中”我的假设是setPrototypeOf(f)和f.prototype都将用一些属性设置该函数的原型。是的,我编辑了该行5次。:/这是很难解释的部分f
是o
的原型。但是f
也有一个原型,因为它是一个对象。setPrototypeOf()将设置f
的原型。因此,f
的原型就是用它创建的<代码>o
但是,未创建