Javascript 对象引用
Javascript object references
我正在尝试使用一个函数为 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
-Function 返回一个 undefined
,但在设置之后,它总是返回新变量,但不改变实际的 [= cE
-对象的 28=]。所以看起来我正在某处创建一个新对象。
所以,怎么了,为什么我不能更改 cE
的实际 属性?
这里有两个问题。第一个问题是您试图在不存在的对象 (chartElements
) 上使用 属性。而不是
cE.chartElements.bottomLine.width = 10
会是
cE.bottomLine.width = 10;
或者,当然,使用您创建的 setter:
cE.bottomLine.setWidth(10);
但是,这给我们带来了第二个问题:
通过
var cE = Object.create(chartElements);
...您正在创建一个对象,由 cE
引用,它使用 chartElements
作为其底层原型。在记忆中,你会得到这样的东西 (爱我一些 ASCII 艺术):
+-------------+
chartElements--------+-->| (object) |
| +-------------+ +----------+
| | bottomLine |----->| (object) |
| +-------------+ +----------+
| | width: 0 |
+-----------+ | | setWidth |---->(function)
cE--->| (object) | | | getWidth |---->(function)
+-----------+ | +----------+
| __proto__ |--+
+-----------+
也就是说cE.bottomLine
指的是原型的bottomLine
属性。如果您更改它,您将更改原型的 bottomLine
对象,这意味着如果您有其他对象是通过 Object.create(chartElements)
创建的,如果它们使用 bottomLine
,它们会看到变化(因为他们都在使用相同的 bottomLine
)。
相反,您可能有 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)
+----------+
最初看起来很相似,但不同之处在于,由于该对象有自己的 bottomLine
对象,您可以安全地使用:
cE.bottomLine.width = 10;
或
cE.bottomLine.setWidth(10);
...设置该实例的 bottomLine
的 width
,这将在它的原型上隐藏那个,给我们:
+-------------+
cE--->| (object) |
+-------------+ +-----------+
| bottomLine |----->| (object) |
+-------------+ +-----------+ +----------+
| __proto__ |---->| (object) |
| width: 10 | +----------+
+-----------+ | width: 0 |
| setWidth |---->(function)
| getWidth |---->(function)
+----------+
这是可行的,因为当您执行 set 与 get 操作时,原型属性的工作方式不同:
当你得到时,如果对象本身没有属性,JavaScript引擎会寻找对象的原型,看看它是否有 属性。如果是,它使用原型的 属性 的值。如果没有,它会查找原型的原型,依此类推。
当您设置时,它会在对象本身上设置值,必要时在对象上创建一个新的属性或者更新 属性 的值(如果它已经存在)。原型的属性不受影响。
我正在尝试使用一个函数为 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
-Function 返回一个 undefined
,但在设置之后,它总是返回新变量,但不改变实际的 [= cE
-对象的 28=]。所以看起来我正在某处创建一个新对象。
所以,怎么了,为什么我不能更改 cE
的实际 属性?
这里有两个问题。第一个问题是您试图在不存在的对象 (chartElements
) 上使用 属性。而不是
cE.chartElements.bottomLine.width = 10
会是
cE.bottomLine.width = 10;
或者,当然,使用您创建的 setter:
cE.bottomLine.setWidth(10);
但是,这给我们带来了第二个问题:
通过
var cE = Object.create(chartElements);
...您正在创建一个对象,由 cE
引用,它使用 chartElements
作为其底层原型。在记忆中,你会得到这样的东西 (爱我一些 ASCII 艺术):
+-------------+ chartElements--------+-->| (object) | | +-------------+ +----------+ | | bottomLine |----->| (object) | | +-------------+ +----------+ | | width: 0 | +-----------+ | | setWidth |---->(function) cE--->| (object) | | | getWidth |---->(function) +-----------+ | +----------+ | __proto__ |--+ +-----------+
也就是说cE.bottomLine
指的是原型的bottomLine
属性。如果您更改它,您将更改原型的 bottomLine
对象,这意味着如果您有其他对象是通过 Object.create(chartElements)
创建的,如果它们使用 bottomLine
,它们会看到变化(因为他们都在使用相同的 bottomLine
)。
相反,您可能有 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) +----------+
最初看起来很相似,但不同之处在于,由于该对象有自己的 bottomLine
对象,您可以安全地使用:
cE.bottomLine.width = 10;
或
cE.bottomLine.setWidth(10);
...设置该实例的 bottomLine
的 width
,这将在它的原型上隐藏那个,给我们:
+-------------+ cE--->| (object) | +-------------+ +-----------+ | bottomLine |----->| (object) | +-------------+ +-----------+ +----------+ | __proto__ |---->| (object) | | width: 10 | +----------+ +-----------+ | width: 0 | | setWidth |---->(function) | getWidth |---->(function) +----------+
这是可行的,因为当您执行 set 与 get 操作时,原型属性的工作方式不同:
当你得到时,如果对象本身没有属性,JavaScript引擎会寻找对象的原型,看看它是否有 属性。如果是,它使用原型的 属性 的值。如果没有,它会查找原型的原型,依此类推。
当您设置时,它会在对象本身上设置值,必要时在对象上创建一个新的属性或者更新 属性 的值(如果它已经存在)。原型的属性不受影响。