gpt4 book ai didi

JavaScript 对象引用

转载 作者:行者123 更新时间:2023-11-28 19:15:09 25 4
gpt4 key购买 nike

我正在尝试使用函数对 Canvas 中的对象进行动画处理,因此我编写了这个对象 - 我正在尝试对其进行动画处理:

var chartElements = {
'bottomLine': {
'width': 0,
setWidth: function (x) {
this.width = x;
},
getWidth: function () {
return this.width;
},
},
};

...并使用以下命令创建它:var cE = Object.create(chartElements);所以我的第一个想法是,用 cE.chartElements.bottomLine.width = 10 更改 var,但这不起作用,所以我编写了一个可以引用 getter 和 setter 的函数:

function changeIt(val, getter, setter) {
console.log(getter());
setter(val);
console.log(getter());
}

现在变得非常非常奇怪,因为首先,getter-函数返回一个未定义,但是在设置之后,它总是返回新变量但不改变cE-对象的实际属性。所以看起来我正在某处创建一个新对象。

那么,出了什么问题,为什么我不能更改 cE 的实际属性?

最佳答案

这里有两个问题。第一个问题是您尝试使用对象 (chartElements) 上不存在的属性。而不是

cE.chartElements.bottomLine.width = 10

应该是

cE.bottomLine.width = 10;

或者,当然,使用您创建的 setter:

cE.bottomLine.setWidth(10);

但是,这给我们带来了第二个问题:

通过做

var cE = Object.create(chartElements);

...您正在创建一个由 cE 引用的对象,该对象使用 chartElements 作为其底层原型(prototype)。在内存中,你得到的东西看起来像这样(爱我一些ASCII艺术):

                         +-------------+                                  chartElements--------+-->|   (object)  |                                                       |   +-------------+      +----------+                                    |   | bottomLine  |----->| (object) |                                    |   +-------------+      +----------+                                    |                        | width: 0 |                     +-----------+  |                        | setWidth |---->(function)cE--->| (object)  |  |                        | getWidth |---->(function)      +-----------+  |                        +----------+                     | __proto__ |--+      +-----------+

That means that cE.bottomLine refers to the prototype's bottomLine property. If you change it, you'll be changing the bottomLine object of the prototype, which would mean if you have other objects you've created via Object.create(chartElements), if they use bottomLine, they'll see the change (because they're all using the same bottomLine).

Instead, you might have a prototype for bottomLine:

var bottomLinePrototype = {
width: 0,
setWidth: function (x) {
this.width = x;
},
getWidth: function () {
return this.width;
}
};

以及用于创建图表元素的构造函数或构建器函数:

这是一个构造函数:

// Constructor function
function ChartElement() {
this.bottomLine = Object.create(bottomLinePrototype);
}

// use it via `new`
var cE = new ChartElement();

这是一个构建器函数:

// Builder function
function buildChartElement() {
return {
bottomLine: Object.create(bottomLinePrototype)
};
}

// Use it *without* `new`
var cE = buildChartElement();

现在,您的对象有了自己的自己 bottomLine 对象:

      +-------------+      cE--->|   (object)  |            +-------------+      +-----------+      | bottomLine  |----->| (object)  |      +-------------+      +-----------+     +----------+                                          | __proto__ |---->| (object) |                                          +-----------+     +----------+                                                            | width: 0 |                                                            | setWidth |---->(function)                                             | getWidth |---->(function)                                             +----------+               

Initially that looks pretty similar, but the difference is that since the object has its own bottomLine object, you can safely use:

cE.bottomLine.width = 10;

cE.bottomLine.setWidth(10);

...设置该实例的 bottomLinewidth,这将遮蔽其原型(prototype)上的实例,从而为我们提供:

      +-------------+      cE--->|   (object)  |            +-------------+      +-----------+      | bottomLine  |----->| (object)  |      +-------------+      +-----------+     +----------+                                          | __proto__ |---->| (object) |                                          | width: 10 |     +----------+                                          +-----------+     | width: 0 |                                                            | setWidth |---->(function)                                             | getWidth |---->(function)                                             +----------+               

这是可行的,因为当您执行 setget 操作时,原型(prototype)属性的工作方式不同:

  • 当您获取时,如果对象本身没有该属性,JavaScript 引擎会查找该对象的原型(prototype)以查看它是否具有该属性。如果是这样,它使用原型(prototype)属性的值。如果没有,它会查找原型(prototype)的原型(prototype),依此类推。

  • 但是,当您设置时,它会在对象本身上设置值,并根据需要在对象上创建新属性,或者更新属性值(如果属性已存在) 。原型(prototype)的属性不受影响。

关于JavaScript 对象引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30013860/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com