不好的做法是使用一个函数来改变条件内的东西,使条件依赖于顺序吗?

var a = 1; 

function myFunction() {

++a;

return true;

}

// Alert pops up.

if (myFunction() && a === 2) {

alert("Hello, world!")

}

// Alert does not pop up.

if (a === 3 && myFunction()) {

alert("Hello, universe!")

}

https://jsfiddle.net/3oda22e4/6/不好的做法是使用一个函数来改变条件内的东西,使条件依赖于顺序吗?

myFunction递增一个变量,返回的东西。如果我在if语句中使用这样的函数,该语句包含它递增的变量,则条件将与顺序有关。

这样做是好还是不好的做法,为什么?

回答:

无论您是否更改条件中使用的变量,条件都与订单有关。您用作示例的两个if语句是不同的,不管您是否使用myFunction()都会有所不同。它们等同于:

if (myFunction()) { 

if (a === 2) {

alert("Hello, world!")

}

}

// Alert does not pop up.

if (a === 3) {

if (myFunction()) {

alert("Hello, universe!")

}

}

在我看来,在代码中坏的做法是不是你改变条件的操作数的条件内在价值的事实,但事实证明,您的应用程序状态暴露和处理内函数甚至不接受这个状态改变变量作为参数。我们通常尝试将函数与代码范围之外的代码隔离开来,并使用它们的返回值来影响代码的其余部分。全局变量占用时间的90%是一个糟糕的想法,随着代码库越来越大,它们倾向于创建难以追踪,调试和解决的问题。

回答:

这是不好的做法,有以下原因:

  • 代码远比构建良好的代码的可读性。如果代码稍后由第三方检查,这非常重要。

  • 如果myfunction稍后更改,代码流是完全不可预知的,并且可能需要重大文档更新。

  • 小而简单的更改会对代码的执行产生严重影响。

  • 它看起来业余。

回答:

如果你不得不问,这不是一个好的做法。是的,对于您提到的原因,这是一个不好的做法:更改逻辑操作的操作数顺序不应影响结果,因此通常应避免条件中的副作用。特别是当它们隐藏在一个函数中时。

函数是纯粹的(只读取状态并执行一些逻辑)或者它是否突变状态应该从其名称中显而易见。您有几种选择来解决这个代码:

  • 把函数调用if前:

    function tryChangeA() { 

    a++;

    return true;

    }

    var ok = tryChangeA();

    if (ok && a == 2) … // alternatively: if (a == 2 && ok)

  • 使突变明确的if内:

    function testSomething(val) { 

    return true;

    }

    if (testSomething(++a) && a == 2) …

  • 放被调用函数内部的逻辑:

    function changeAndTest() { 

    a++;

    return a == 2;

    }

    if (changeAndTest()) …

回答:

代码呈现更多然后一个不好的做法,实际上是:

var a = 1; 

function myFunction() {

++a; // 1

return true;

}

if (myFunction() && a === 2) { // 2, 3, 4

alert("Hello, world!")

}

if (a === 3 && myFunction()) { // 2, 3, 4

alert("Hello, universe!")

}

  1. 变异在不同范围的变量。这可能是也可能不是问题,但通常是这样。

  2. 召唤一个if语句条件中的函数。 这本身并不会造成问题,但它并不十分干净。 将该函数的结果分配给变量(可能使用描述性名称)是一种更好的做法。这将帮助阅读代码的人理解您想要在if声明中检查的内容。顺便说一句,该函数总是返回true

  3. 使用一些神奇的数字。想象一下其他人阅读该代码,它是一个大型代码库的一部分。这些数字是什么意思?一个更好的解决方案是将它们替换为命名常量。

  4. 如果你想支持更多的信息,你需要增加更多的条件。 更好的方法是使这个可配置。

如下我想重写代码:

const ALERT_CONDITIONS = { // 4 

WORLD_MENACE: 2,

UNIVERSE_MENACE: 3,

};

const alertsList = [

{

message: 'Hello world',

condition: ALERT_CONDITIONS.WORLD_MENACE,

},

{

message: 'Hello universe',

condition: ALERT_CONDITIONS.UNIVERSE_MENACE,

},

];

class AlertManager {

constructor(config, defaultMessage) {

this.counter = 0; // 1

this.config = config; // 2

this.defaultMessage = defaultMessage;

}

incrementCounter() {

this.counter++;

}

showAlert() {

this.incrementCounter();

let customMessageBroadcasted = false;

this.config.forEach(entry => { //2

if (entry.condition === this.counter) {

console.log(entry.message);

customMessageBroadcasted = true; // 3

}

});

if (!customMessageBroadcasted) {

console.log(this.defaultMessage)

}

}

}

const alertManager = new AlertManager(alertsList, 'Nothing to alert');

alertManager.showAlert();

alertManager.showAlert();

alertManager.showAlert();

alertManager.showAlert();

  1. 一类具有精确的函数,使用的而不是一组函数依赖于一些可变其自己的内部状态,这可能位于任何地方。无论是否使用课堂,这都是一个选择的问题。它可以以不同的方式完成。

  2. 使用配置。这意味着你想添加更多的消息,你根本不需要触摸代码。例如,想象来自数据库的配置。

  3. 正如你可能会注意到,这个变异的功能的外部范围的变量,但在这种情况下,它不会引起任何问题。

  4. 使用具有明确名称的常量。 (好吧,这可能会更好,但考虑到这个例子,请忍受我)。

回答:

MyFunction违反了原则Tell, Don't Ask。

MyFunction改变的东西的状态下,从而使其成为一个命令。如果MyFunction成功或以某种方式无法增加a,则不应该返回true或false。它被赋予了一份工作,它必须试图成功,或者如果它发现现在工作是不可能的,它应该抛出异常。

在if语句中的谓语,MyFunction用作查询。

一般来说,查询应不表现出副作用(可以观察到的,即不改变的东西)。一个好的查询可以像计算一样对待,因为对于相同的输入,它应该产生相同的输出(有时被描述为“幂等”)。

知道这些指南可以帮助您和其他人了解代码的原因也很重要。代码可以引起混淆,。对代码的混淆是对错误的孵化。

像Trier-Doer模式那样有很好的模式可以像你的代码示例一样使用,但是每个阅读它的人都必须理解通过名称和结构发生了什么。

回答:

改变内容的函数。这个世界到底是什么?这个函数必须改变东西,并在每次调用时返回不同的值。

考虑一副扑克牌的dealCard函数。它处理卡1-52。每次调用它都会返回一个不同的值。

function dealCard() { 

++a;

return cards(a);

}

/*我们只能假定阵列卡是洗牌*/

/*为简便起见,我们假设在甲板上是无限的,在52 */

不循环

以上是 不好的做法是使用一个函数来改变条件内的东西,使条件依赖于顺序吗? 的全部内容, 来源链接: utcz.com/qa/260347.html

回到顶部