Setter 函数用于动态访问数组中的字段,该数组是一个属性

Setter function to dynamically access fields within an array which is a property

本文关键字:数组 属性 一个 字段 动态 用于 函数 访问 Setter      更新时间:2023-09-26

我有一个表示物理模型的javascript模块,其数据在数据对象中提供。此模块导出一个 setter 函数以设置数据对象的属性(注意:在下面的示例中删除了导出(

这在顶层层次结构级别上非常有效,但是如何在属性中设置特定值,例如数组属性的特定字段?

var modeldata = {
  current: 100,
  pipeline: [150,200,210,220]
}
set = (variable, val) => {
  if (modeldata[variable] == undefined) {
    console.log('modeldata['+variable+'] is not defined');
  } else {
    if (modeldata[variable] == val) {
      console.log('no change necessary');
    } else {
      var old = modeldata[variable];
      modeldata[variable] = val;
      console.log('changing modeldata['+variable+']: ' + old + ' to ' + modeldata[variable])
    }
  }
}
set('curren', 100);   // modeldata[curren] is not defined, OK
set('current', 100);  // no change necessary, OK
set('current', 120);  // changing modeldata[current]: 100 to 120, OK
set('pipeline[0]', 42); // modeldata[pipeline[0]] is not defined, FAIL

如何使set函数问题modeldata['pipeline'][0] = 42;,但仍允许设置current属性,因为它现在工作?

我可以简单地为每个属性创建一个特定的 setter,但我有 100 个属性>并且属性的数量不是固定的。

此外,我可以调用set('pipeline', ...)并简单地覆盖整个数组,包括新数据。但如上所述,我只想更改数组的特定字段,而不知道或触摸其他所有内容。

更新:我正在寻找一种解决方案,其中modeldata仅在set函数中访问,并且没有可用的get函数。因此,set是我唯一的界面 modeldata .

这是对 set 函数的编辑,以允许数组和子属性更改:

set = (variable, val) => variable.split('.').reduce((prev, curr, i, arr) => {
  if (i === arr.length - 1) {
    if (prev[curr] == undefined) {
      console.log('modeldata[' + variable + '] is not defined');
    } else {
      if (prev[curr] == val) {
        console.log('no change necessary');
      } else {
        var old = prev[curr];
        prev[curr] = val;
        console.log('changing modeldata[' + variable + ']: ' + old + ' to ' + prev[curr]);
        return prev[curr];
      }
    }
  } else {
    return prev[curr];
  }
}, modeldata)

你将拥有

set('curren', 100); // modeldata[curren] is not defined, OK
set('current', 100); // no change necessary, OK
set('current', 120); // changing modeldata[current]: 100 to 120, OK
set('pipeline.0', 42); // changing modeldata[pipeline.0]: 150 to 42, OK

走这条路就行了。

var modeldata = {
    current: 100,
    pipeline: [150, 200, 210, 220]
}
function set(variable, val) {
    var path = variable.replace(/'[('d+)']/g, '.$1').split('.'),
        target = path.pop(),
        reference = path.reduce(function (r, k) { return r[k]; }, modeldata);
    if (target in reference) {
        if (reference[target] === val) {
            alert(variable + ' = ' + val + ''nno change necessary');
        } else {
            reference[target] = val;
        }
    } else {
        alert(variable + ' is not defined');
    }
}
set('curren', 100); // modeldata[curren] is not defined, OK
set('current', 100); // no change necessary, OK
set('current', 120); // changing modeldata[current]: 100 to 120, OK
set('pipeline[0]', 42); // changing modeldata[pipeline.0]: 150 to 42, OK
document.write('<pre>' + JSON.stringify(modeldata, 0, 4) + '</pre>');

我通过在 set -function 的最开头添加此代码创建了一个快速而肮脏的解决方法:

set = (variable, val) => {
  if (variable.indexOf('[')>0 && variable.indexOf(']')>0) {
    var old = eval('modeldata.'+variable);
    eval('modeldata.'+variable+'='+val);
    console.log('changing modeldata.'+variable+': ' + old + ' to ' + val)
    return;
  }

它有效,但使用eval()感觉并不好。我很想看到更好的答案。

您可以参考以下代码:

    var getBothIndexVariables = function (input) {
        var openingIndex = input.indexOf('[');
        var secondVal = "";
        var indexVariable;
        if (openingIndex != -1) {
            secondVal = input.substring(openingIndex + 1, input.length - 1);
            indexVariable = {
                firstIndexVariable: input.substring(0,openingIndex),
                secondIndexVariable: secondVal,
            }
        }
        return indexVariable;
    }
    var modeldata = {
        current: 100,
        pipeline: [150, 200, 210, 220]
    }
    set = (variable, val) => {
        var tempVariable = getBothIndexVariables(variable);
        if (tempVariable) {
            debugger;
            var value = modeldata[tempVariable.firstIndexVariable][tempVariable.secondIndexVariable];
            modeldata[tempVariable.firstIndexVariable][tempVariable.secondIndexVariable] = val;
            console.log(value);
            return;
        }
        if (modeldata[variable] == undefined) {
            console.log('modeldata[' + variable + '] is not defined');
        } else {
            if (modeldata[variable] == val) {
                console.log('no change necessary');
            } else {
                var old = modeldata[variable];
                modeldata[variable] = val;
                console.log('changing modeldata[' + variable + ']: ' + old + ' to ' + modeldata[variable])
            }
        }
    }
    set('curren', 100);   // modeldata[curren] is not defined, OK
    set('current', 100);  // no change necessary, OK
    set('current', 120);  // changing modeldata[current]: 100 to 120, OK
    set('pipeline[0]', 42); // modeldata[pipeline[0]] is not defined, FAIL

此条件if (modeldata[variable] ....检查对象中是否存在不同的命名属性modeldata
扩展函数set以便它可以考虑数组键:

var modeldata = {
        current: 100,
        pipeline: [150,200,210,220]
    }
    var set = (variable, val, array_key) => {
        var prop = (typeof array_key == "number")? modeldata[variable][array_key] : modeldata[variable];
        if (prop == undefined) {
            console.log('modeldata['+variable+'] is not defined');
        } else {
            if (prop == val) {
                console.log('no change necessary');
            } else {
                var old = prop;
                if (typeof array_key == "number"){
                    modeldata[variable][array_key] = val;
                } else {
                    modeldata[variable] = val;
                }
                console.log('changing modeldata['+variable+']: ' + old + ' to ' + modeldata[variable])
            }
        }
    };
    set('curren', 100);   // modeldata[curren] is not defined, OK
    set('current', 100);  // no change necessary, OK
    set('current', 120);  // changing modeldata[current]: 100 to 120, OK
    set('pipeline', 42, 0); // m
    console.log(modeldata);
    // the output:
    Object {current: 120, pipeline: Array[4]} .....
    current: 120
    pipeline: Array[4]
             0: 42
             1: 200
             2: 210
             3: 220
             length: 4