以前,当我需要存储许多相关变量时,我会创建一个类。
function Item(id, speaker, country) {
this.id = id;
this.speaker = speaker;
this.country = country;
}
var myItems = [new Item(1, 'john', 'au'), new Item(2, 'mary', 'us')];
但我想知道这是否是一个好的做法。还有其他更好的方法来在 JavaScript 中模拟结构体吗?
对象字面量和构造对象之间的唯一区别是从原型继承的属性。
var o = {
'a': 3, 'b': 4,
'doStuff': function() {
alert(this.a + this.b);
}
};
o.doStuff(); // displays: 7
你可以创建一个结构工厂。
function makeStruct(names) {
var names = names.split(' ');
var count = names.length;
function constructor() {
for (var i = 0; i < count; i++) {
this[names[i]] = arguments[i];
}
}
return constructor;
}
var Item = makeStruct("id speaker country");
var row = new Item(1, 'john', 'au');
alert(row.speaker); // displays: john
我总是使用对象文字
{id: 1, speaker:"john", country: "au"}
真正的问题是语言中的结构应该是值类型而不是引用类型。提议的答案建议使用对象(引用类型)代替结构。虽然这可以达到其目的,但它回避了程序员实际上希望获得使用值类型(如基元)代替引用类型的好处的观点。其一,值类型不应该导致内存泄漏。
编辑: 正在制定一项提案来实现这一目的。
//today
var obj = {fname: "Kris", lname: "Kringle"}; //vanilla object
var gifts = ["truck", "doll", "slime"]; //vanilla array
//records and tuples - not possible today
var obj = #{fname: "Buddy", lname: "Hobbs"};
var skills = #["phone calls", "basketball", "gum recycling"];
和 Rest Parameter 更简单地创建“结构”工厂,如下所示:
const Struct = (...keys) => ((...v) => keys.reduce((o, k, i) => {o[k] = v[i]; return o} , {}))
const Item = Struct('id', 'speaker', 'country')
var myItems = [
Item(1, 'john', 'au'),
Item(2, 'mary', 'us')
];
console.log(myItems);
console.log(myItems[0].id);
console.log(myItems[0].speaker);
console.log(myItems[0].country);
运行结果是:
[ { id: 1, speaker: 'john', country: 'au' },
{ id: 2, speaker: 'mary', country: 'us' } ]
1
john
au
你可以让它看起来类似于Python的namedtuple:
const NamedStruct = (name, ...keys) => ((...v) => keys.reduce((o, k, i) => {o[k] = v[i]; return o} , {_name: name}))
const Item = NamedStruct('Item', 'id', 'speaker', 'country')
var myItems = [
Item(1, 'john', 'au'),
Item(2, 'mary', 'us')
];
console.log(myItems);
console.log(myItems[0].id);
console.log(myItems[0].speaker);
console.log(myItems[0].country);
结果:
[ { _name: 'Item', id: 1, speaker: 'john', country: 'au' },
{ _name: 'Item', id: 2, speaker: 'mary', country: 'us' } ]
1
john
au
我对哑结构使用对象 JSON 样式(无成员函数)。
设置起来需要更多工作,但如果可维护性胜过一次性工作,那么这可能就是您的情况。
这为您带来了复杂值类型的一个关键好处,即您不会通过对对象的引用意外地修改该对象。
当然,缺点是如果您确实想要修改成员,则必须创建一个新实例,因此需要静态
SetX
和
SetY
函数。
这是很多语法糖,但我认为对于特殊情况来说这是值得的,比如Point
,如果值被意外更改,可能会被大量使用并导致很多错误。
此功能允许您创建具有预定义属性的结构化对象。调用 Struct 时,您传入一个定义该结构体属性的构造函数。
function Struct(_constructor) {
const struct = [];
const o = new Proxy({}, {
get(object, prop, receiver) { struct.push({key: prop, val: undefined}); },
set(object, prop, value) { struct.push({key: prop, val: value}); },
})
_constructor(o);
return function () {
const object = {};
struct.forEach((obj,index) => {
object[obj.key] = index < arguments.length ? arguments[index] : obj.val
})
return object
}
}
// For example:
const Item = Struct(o => {
o.id
o.speaker
o.country
})
// To create items, simply do
const items = [new Item(1, 'john', 'au'), new Item(2, 'mary', 'us')];
console.log(items)
:
灵活性
可重复使用性缺乏属性的类型检查。
var structJS = { id: 55, title: "GP", iccid: "56", msisdn: "1712844177", imsi: "12345" };
const USIMContract = await ethers.getContractFactory("USIM");
const usimContract = await USIMContract.deploy(89, structJS);
console.log("USIM deployed to: ", usimContract.address);
Solidity 脚本:
struct SolStruct { uint id; string title; string iccid; string msisdn; string imsi; }
contract USIM {
uint private _iccid;
SolStruct private _communicationProfile;
constructor( uint iccid_, SolStruct memory communicationProfile_ )
{
_iccid = iccid_;
_communicationProfile = communicationProfile_;
}
}