原型属性在内存中的工作方式

How a prototype property works in memory?

本文关键字:工作 方式 内存 属性 原型      更新时间:2023-09-26

如果原型在所有实例之间共享,原型属性如何工作?

function Foo() { 
}
Foo.prototype.property = 1;
var a = new Foo();
var b = new Foo();
a.property = 50;
console.log(b.property) // why this line shows 1?

如果未共享,则原型属性和内存中的构造函数属性之间有什么区别?

function Foo() { 
}
Foo.prototype.property = 1;

function Foo() {
     this.property = 1;
}    

其他疑问:

  • 这两种不同的方式在内存中是如何工作的?
  • 哪一个使用更多的内存,为什么?
  • 当我在原型中创建方法时,它在所有实例之间共享对我来说是有意义的,我想我只会在内存中加载一个方法,但我无法理解属性的工作原理。
function Foo() { 
}
// Hey, everybody, if anyone asks you about 'property'
// unless you have your own, use this one.
Foo.prototype.property = 1;
var a = new Foo();
var b = new Foo();
// Hey, you! You're special. You get your own property.
// This one covers the shared one.
a.property = 50;
// Hey you, B! You're using the shared one.
console.log(b.property) // why this line shows 1?

这就是"原型"和本地属性之间的基本区别。

如果在对象上请求该对象没有的属性,它会跑到其父对象并询问"嘿! 我可以用你的吗? 这会将它们全部返回到根对象。

为了真正的乐趣,以及让你的同事讨厌你的可靠方式,设置:

Object.prototype.something = true;

我会到处可用,打破各种东西。


// Everyone share this copy of property
function Foo() { 
}
Foo.prototype.property = 1;

// Hey everybody! You get your OWN copy of property! Ain't you special.
function Foo() {
     this.property = 1;
}    

原型和构造函数之间的区别可以通过在创建对象后修改它们来显示:

var a = new Foo();
var b = new Foo();
Foo.prototype.property = 50;
console.log(b.property); // This will show 50

如果将赋值放在构造函数中,则更改它不会影响已创建的对象。

在内存中,原型是由从它构建的所有对象共享的对象。因此,不是每个对象都有自己的property副本,它们都引用了一个原型对象;这会使用更少的内存。如果引用对象中的属性,它首先检查它是否具有该名称的自己的属性。如果没有,它会通过原型链,寻找属性。

在这方面,方法和其他属性之间没有区别。方法只是一个属性,其值恰好是一个函数。只是在一个类的所有实例之间共享方法比共享值更常见。但是,原型属性是为每个实例提供该属性的默认值的有用方法。

如果原型在所有实例之间共享,则原型属性如何工作?

只有在解析属性名称以获取属性值时,才会访问对象的[[Prototype]]分配给属性时,仅检查对象本身。

> function Foo() {}
> 
> Foo.prototype.property = 1;
> 
> var a = new Foo(); var b = new Foo();
> 
> a.property = 50;
> 
> console.log(b.property) // why this line shows 1?

该行显示1因为在执行作业时:

a.property = 50;

检查对象 A 是否存在名为 Property 的属性,由于它没有属性,因此添加并使用值 50 初始化该对象 A。然后,当您这样做时:

console.log(b.property) // why this line shows 1?

对象 b 没有属性属性,因此[[Prototype]]检查它,并在那里找到值为 1 的属性,因此返回该属性

如果未共享,则原型属性和内存中的构造函数属性之间有什么区别?

术语"构造函数属性"实际上应该是"实例属性"。原型上的属性仅在获取值时访问,然后在设置值时永远不会访问。

这两种不同的方式在内存中是如何工作的?

它们是独立的东西,在一种情况下,您在构造函数的原型上创建了一个属性,而在另一种情况下,您在对象本身上创建了一个属性。它如何"在内存中工作"取决于浏览器作者,真的无关紧要。

哪一个使用更多的内存,为什么?

这真的无关紧要。即使有差异,在事物的计划中也是微不足道的。

当我在原型中创建方法时,它在所有实例之间共享对我来说是有意义的,我想我只会在内存中加载一个方法,但我无法理解属性的工作原理。

"方法"也只是属性。您可以通过读取值来访问它们,这与读取对象或其[[Prototype]]链上任何属性的值相同。但是,当您分配给 Object 属性时,它直接放置在对象本身上,不考虑[[Prototype]]链。