JavaScript对象-不同的类型取决于上下文

JavaScript Object - Different Type Depending on Context

本文关键字:类型 取决于 上下文 对象 JavaScript      更新时间:2023-09-26

我首先要说的是,我认为这是不可能的,但希望有人知道JavaScript中的一些特殊方法。我有一个JavaScript对象定义如下:

var t = {
  "fields": {
    "a": ["99", "98"]
  }
};

我正在寻找一种方法,这样我就可以用不同的值两次定义数组的同一元素,这些值可以在两个不同的上下文中使用——比如这样:

var t = {
  "fields": {
    "a": ["99", "98"],
    "a": "99|98"
  }
};

如果我使用语法t.fields["a"]查询它,它会返回"99|98",但如果我使用t.fields["a"][0]查询它,那么它将返回"99"。我知道如果我在不指定索引的情况下查询数组,它会以字符串的形式返回"99,98",但我需要它返回用"|"而不是","分隔的条目。

也可以使用getter函数,如下所示:

var t = {
    "fields": {
        "_a": ["99", "98"],
        "a": function (index) {
            if (typeof index != 'undefined')
                return this._a[index];
            else
                return this._a.join('|');
        }
    }
};
console.log(t.fields['a']()); // 99|98
console.log(t.fields['a'](1));// 98

您还可以为所有字段提供全局获取功能:

var t = {
    "fields": {
        "_a": ["99", "98"],
        get: function (field, index) {
            if (typeof index != 'undefined')
                return this['_' + field][index];
            else
                return this['_' + field].join('|');
        }
    }
};
console.log(t.fields.get('a')); // 99|98
console.log(t.fields.get('a', 1)); // 98

要实现您想要的目标,您有一些选择。根据您的编码风格、环境等,选择最适合您的选项。

选项1

您可以很容易地替换Array.prototype.toString()方法,以返回由竖线(|)分隔的值,而不是通常的逗号。你可以这样做:

Array.prototype.toString = function() {
    return this.join("|");
};

现在你可以轻松地做你想做的事:

var t = {
    "fields": {
        "a": ["99", "98"]
    }
};
console.log("My array is: " + t.fields);
// My array is: 99|98
console.log("Its first element is: " + t.fields[0]); 
// Its first element is: 99

顺便说一句,更改默认对象的方法/属性并不总是最好的选择,因为某些库或本机方法可能会使用它们并导致错误,因为它们已被修改。

选项2

为了实现您想要的,如果您只需要使用几个阵列,您可以修改它们的prototype,而不是默认的Array.prototype,如下所示:

// Let's assume you have arrays a, b and c
var a = [1, 2],
    b = [3, 4],
    c = [5, 6];
a.toString =
b.toString =
c.toString = function() {
    return this.join("|");
};

如果您只使用少数数组,这是一种更好的方法,否则更改您使用的每个数组的每个原型将非常繁重,最好使用Array.prototype(就像我的第一个示例)。

选项3

构建您自己的函数并使用它。建议这样做,因为它不会更改任何现有的prototype方法,这可能会导致一些错误,具体取决于您如何使用数组。

// Create your own function
function myJoin(array) {
    return array.join("|");
}
var a = [1, 2, 3];
myJoin(a); // "1|2|3"
// Or add it to the prototype
Array.prototype.myJoin = function() {
    return this.join("|");
}
var b = [11, 22, 33];
b.myJoin(); // "11|22|33"

感谢@marco bonelli和其他所有人,我已经解决了以下问题:

var t = {
  "fields": {
    "a": ["99", "98"],
    "b": ["77", "76"]
  },
  "token": "|"
};
Object.keys(t).forEach(function(key) {
  t.fields[key].toString = function() {
    return this.join(t.token);
  };
});

"t"对象是根据用户数据动态生成的(需要小心转义),因此"fields"对象中可能有多个元素。