如何更新依赖于函数中另一个变量的变量?
How to update a variable that depends on another variable in a function?
在下面的示例代码中,请注意变量 dependent
的值取决于变量 prereq
。当调用函数 changePrereq
时,它会更改 prereq
的值。如果已记录,则会显示此更改,但不会反映在 dependent
的值中。相反,当 dependent
被放入一个跨度中时,它显示 Some text - undefined
.
如何根据 prereq
的值更改 dependent
?
P.S。感谢大家的建议。对于我自己,我选择了 "ztcollazo" 的答案作为正确的决定。
"outis" - 感谢您的解释。我一定会关注您的建议,并会更详细地研究它们!
var display = document.getElementById('text'),
prereq,
message = "Some text - " + prereq;
function updateDisplay() {
display.innerHTML = message;
console.log(prereq);
}
function changePrereq() {
prereq = "I am some text.";
updateDisplay();
}
<p><span id="text"></span></p>
<button onclick="changePrereq()">Click</button>
将 changeMyText 变量移动到 changeTextFunc 函数中。
代码看起来像这样
function changeMyText(m){
var changeMyText = "Some text - " + someText1;
if (m > 0) {
myText.innerHTML = changeMyText;
} else {
console.log('m < 0');
}
}
问题是 changeMyText
不会在 someText
更新时更新。您需要在 changeTextFunc
函数内部定义 changeMyText
,然后将 someText
作为参数传递。
示例:
var myText = document.getElementById('text');
var someText1;
var m1 = 1;
function changeTextFunc(someText, m) {
var changeMyText = "Some text - " + someText;
if (m > 0) {
myText.innerHTML = changeMyText;
} else {
console.log('m < 0');
}
}
function changeText() {
someText1 = "I a'm some text.";
changeTextFunc(someText1, m1);
}
<div>
<button onclick="changeText()">Click</button>
<p id="text"></p>
</div>
如果你想让一个变量基于另一个而改变,你必须在另一个改变之后设置它的值。有各种方法,具有各种实现。您可以将其分解为不同的方面进行更改:
- 内容:
- globals(注意:avoid global variables 在生产中,并在其他上下文中谨慎使用)
- 本地人
- 对象
- 其中:
- 内联,在站点引用一个变量
- 在为职责创建的单独函数中
- 当:
- 先决条件变量已更改
- 使用因变量
以上不同方面的一些选项不打算合并,或者不能合并。例如,1.3(对象)旨在与 2.2(单独的函数)一起使用,而 1.3.2(getters/setters)需要 2.2,因为对象 getters 和 setters 是函数( 2.2 基本上意味着“使用 getter 或 setter”,但不一定使用 getter/setter 语法)。你可能会想到其他方面,或者以上方面的其他可能性。
ztcollazo 显示了一个解决方案,该解决方案使用全局作为先决条件 (1.1),使用本地作为依赖项 (1.2),并在使用依赖项 (3.2) 时更新内联 (2.1)。如果 changeTextFunc
设置 changeMyText
中的行改为移动到 changeText
(并且使用全局),你将有 1.1 + 2.1 + 3.1.
有关更多示例实现,请检查以下内容。它说明了上述四个不同的选项,并在评论中注明。
var display = document.getElementById('output'),
dependent, prereq;
/* options 1.1, 2.2, 3.1: global, separate function, prereq change */
function setPrereq(value) {
prereq = value;
dependent = "global prereq setter: " + prereq;
}
function updateDisplayFromVariable() {
display.innerText = dependent;
}
function changePrereq_updateWhenSet(value="setter") {
setPrereq(value);
updateDisplayFromVariable();
}
/* options 1.1, 2.2, 3.2: global, separate function, dependent used */
function getDependent(value) {
return dependent = "global dependent getter: " + prereq;
}
function updateDisplayFromGetter() {
display.innerText = getDependent();
}
function changePrereq_updateWhenUsed(value="inline, no setter") {
prereq = value;
updateDisplayFromGetter();
}
/* options 1.3.2, 2.2: (local) object getter/setter */
/* wrapped in self-called function to prevent polluting global namespace */
var dependency = (function () {
let display = document.getElementById('output'),
/* options 1.3.2, 2.2, 3.2: (local) object getter, dependent used */
inGetter = {
prereq: 'initial',
/* note: `dependent` is entirely synthetic */
get dependent() {
return "object's dependent getter: " + this.prereq;
},
},
/* options 1.3.2, 2.2, 3.1: (local) object setter, prereq changed */
inSetter = {
/* note: when using setter, can't use same name for the
* backing property; instead, must also define getter. */
_prereq: 'initial',
get prereq() {
return this._prereq;
},
set prereq(value) {
this._prereq = value;
this.dependent = "object's prereq setter: " + value;
},
};
function updateDisplay(from) {
display.innerText = from.dependent;
}
/* expose 1.3.2, 2.2, 3.1 */
function whenSet(value) {
inSetter.prereq = value;
updateDisplay(inSetter);
}
/* expose 1.3.2, 2.2, 3.2 */
function whenUsed(value) {
inGetter.prereq = value;
updateDisplay(inGetter);
}
return {whenSet, whenUsed};
})();
<button onclick="changePrereq_updateWhenSet('thimbles')">Use global setter</button>
<button onclick="changePrereq_updateWhenUsed('care')">Use global getter</button>
<button onclick="dependency.whenSet('forks')">Use object setter</button>
<button onclick="dependency.whenUsed('hope')">Use object getter</button>
<p><span id="output"></span></p>
与任何设计一样,以上各有优点和缺点,但应该首选使用对象 setters/getters (1.3.2),因为它是最可靠的方法。使用独立函数(不是 getters/setters)和更新内联都更脆弱,因为程序员可能无法在某处使用它们,而是直接分配和引用变量。内联更新也更难维护,因为必须在执行更新的每一行上进行任何更改。全局变量有自己的问题,比如:
- 模块中有限的代码重用(注意
updateDisplay(from)
如何适用于两种不同的情况,而 changePrereq_updateWhenSet
和 changePrereq_updateWhenUsed
各自需要不同的显示功能),并且
- 不灵活(即,为新行为组合现有功能受到更多限制;换句话说,这限制了客户端代码的代码重用),
- 当不同的模块使用相同的全局变量时命名冲突,导致它们相互冲突。
至于更新先决条件setter(1.3.2 + 2.2 + 3.1)中的依赖还是使用getter无后盾的依赖属性(在某些圈子里,这被称为“合成 属性”)取决于其他要求(基本上,是否允许依赖项被分配独立于先决条件的值)。例如,您可以对两个属性使用 getters 和 setters。
在下面的示例代码中,请注意变量 dependent
的值取决于变量 prereq
。当调用函数 changePrereq
时,它会更改 prereq
的值。如果已记录,则会显示此更改,但不会反映在 dependent
的值中。相反,当 dependent
被放入一个跨度中时,它显示 Some text - undefined
.
如何根据 prereq
的值更改 dependent
?
P.S。感谢大家的建议。对于我自己,我选择了 "ztcollazo" 的答案作为正确的决定。
"outis" - 感谢您的解释。我一定会关注您的建议,并会更详细地研究它们!
var display = document.getElementById('text'),
prereq,
message = "Some text - " + prereq;
function updateDisplay() {
display.innerHTML = message;
console.log(prereq);
}
function changePrereq() {
prereq = "I am some text.";
updateDisplay();
}
<p><span id="text"></span></p>
<button onclick="changePrereq()">Click</button>
将 changeMyText 变量移动到 changeTextFunc 函数中。 代码看起来像这样
function changeMyText(m){
var changeMyText = "Some text - " + someText1;
if (m > 0) {
myText.innerHTML = changeMyText;
} else {
console.log('m < 0');
}
}
问题是 changeMyText
不会在 someText
更新时更新。您需要在 changeTextFunc
函数内部定义 changeMyText
,然后将 someText
作为参数传递。
示例:
var myText = document.getElementById('text');
var someText1;
var m1 = 1;
function changeTextFunc(someText, m) {
var changeMyText = "Some text - " + someText;
if (m > 0) {
myText.innerHTML = changeMyText;
} else {
console.log('m < 0');
}
}
function changeText() {
someText1 = "I a'm some text.";
changeTextFunc(someText1, m1);
}
<div>
<button onclick="changeText()">Click</button>
<p id="text"></p>
</div>
如果你想让一个变量基于另一个而改变,你必须在另一个改变之后设置它的值。有各种方法,具有各种实现。您可以将其分解为不同的方面进行更改:
- 内容:
- globals(注意:avoid global variables 在生产中,并在其他上下文中谨慎使用)
- 本地人
- 对象
- 其中:
- 内联,在站点引用一个变量
- 在为职责创建的单独函数中
- 当:
- 先决条件变量已更改
- 使用因变量
以上不同方面的一些选项不打算合并,或者不能合并。例如,1.3(对象)旨在与 2.2(单独的函数)一起使用,而 1.3.2(getters/setters)需要 2.2,因为对象 getters 和 setters 是函数( 2.2 基本上意味着“使用 getter 或 setter”,但不一定使用 getter/setter 语法)。你可能会想到其他方面,或者以上方面的其他可能性。
ztcollazo 显示了一个解决方案,该解决方案使用全局作为先决条件 (1.1),使用本地作为依赖项 (1.2),并在使用依赖项 (3.2) 时更新内联 (2.1)。如果 changeTextFunc
设置 changeMyText
中的行改为移动到 changeText
(并且使用全局),你将有 1.1 + 2.1 + 3.1.
有关更多示例实现,请检查以下内容。它说明了上述四个不同的选项,并在评论中注明。
var display = document.getElementById('output'),
dependent, prereq;
/* options 1.1, 2.2, 3.1: global, separate function, prereq change */
function setPrereq(value) {
prereq = value;
dependent = "global prereq setter: " + prereq;
}
function updateDisplayFromVariable() {
display.innerText = dependent;
}
function changePrereq_updateWhenSet(value="setter") {
setPrereq(value);
updateDisplayFromVariable();
}
/* options 1.1, 2.2, 3.2: global, separate function, dependent used */
function getDependent(value) {
return dependent = "global dependent getter: " + prereq;
}
function updateDisplayFromGetter() {
display.innerText = getDependent();
}
function changePrereq_updateWhenUsed(value="inline, no setter") {
prereq = value;
updateDisplayFromGetter();
}
/* options 1.3.2, 2.2: (local) object getter/setter */
/* wrapped in self-called function to prevent polluting global namespace */
var dependency = (function () {
let display = document.getElementById('output'),
/* options 1.3.2, 2.2, 3.2: (local) object getter, dependent used */
inGetter = {
prereq: 'initial',
/* note: `dependent` is entirely synthetic */
get dependent() {
return "object's dependent getter: " + this.prereq;
},
},
/* options 1.3.2, 2.2, 3.1: (local) object setter, prereq changed */
inSetter = {
/* note: when using setter, can't use same name for the
* backing property; instead, must also define getter. */
_prereq: 'initial',
get prereq() {
return this._prereq;
},
set prereq(value) {
this._prereq = value;
this.dependent = "object's prereq setter: " + value;
},
};
function updateDisplay(from) {
display.innerText = from.dependent;
}
/* expose 1.3.2, 2.2, 3.1 */
function whenSet(value) {
inSetter.prereq = value;
updateDisplay(inSetter);
}
/* expose 1.3.2, 2.2, 3.2 */
function whenUsed(value) {
inGetter.prereq = value;
updateDisplay(inGetter);
}
return {whenSet, whenUsed};
})();
<button onclick="changePrereq_updateWhenSet('thimbles')">Use global setter</button>
<button onclick="changePrereq_updateWhenUsed('care')">Use global getter</button>
<button onclick="dependency.whenSet('forks')">Use object setter</button>
<button onclick="dependency.whenUsed('hope')">Use object getter</button>
<p><span id="output"></span></p>
与任何设计一样,以上各有优点和缺点,但应该首选使用对象 setters/getters (1.3.2),因为它是最可靠的方法。使用独立函数(不是 getters/setters)和更新内联都更脆弱,因为程序员可能无法在某处使用它们,而是直接分配和引用变量。内联更新也更难维护,因为必须在执行更新的每一行上进行任何更改。全局变量有自己的问题,比如:
- 模块中有限的代码重用(注意
updateDisplay(from)
如何适用于两种不同的情况,而changePrereq_updateWhenSet
和changePrereq_updateWhenUsed
各自需要不同的显示功能),并且 - 不灵活(即,为新行为组合现有功能受到更多限制;换句话说,这限制了客户端代码的代码重用),
- 当不同的模块使用相同的全局变量时命名冲突,导致它们相互冲突。
至于更新先决条件setter(1.3.2 + 2.2 + 3.1)中的依赖还是使用getter无后盾的依赖属性(在某些圈子里,这被称为“合成 属性”)取决于其他要求(基本上,是否允许依赖项被分配独立于先决条件的值)。例如,您可以对两个属性使用 getters 和 setters。