Javascript 中的结构体

问题描述 投票:0回答:11

以前,当我需要存储许多相关变量时,我会创建一个类。

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 中模拟结构体吗?

javascript struct
11个回答
202
投票

对象字面量和构造对象之间的唯一区别是从原型继承的属性。

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

41
投票

我总是使用对象文字

{id: 1, speaker:"john", country: "au"}

27
投票

真正的问题是语言中的结构应该是值类型而不是引用类型。提议的答案建议使用对象(引用类型)代替结构。虽然这可以达到其目的,但它回避了程序员实际上希望获得使用值类型(如基元)代替引用类型的好处的观点。其一,值类型不应该导致内存泄漏。

编辑: 正在制定一项提案来实现这一目的。

//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"];


9
投票

我认为创建一个类来模拟类似 C 的结构,就像您一直在做的那样,是“最好的”方法。 这是对相关数据进行分组并简化向函数传递参数的好方法。我还认为,考虑到模拟真实的面向对象功能所需的“额外工作”,JavaScript 类更像是 C++ 结构而不是 C++ 类。

我发现尝试让 JavaScript 更像另一种语言会很快变得复杂,但我完全支持使用 JavaScript 类作为无函数结构。

按照 Markus 的

answer

8
投票
Arrow Functions

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 样式(无成员函数)。

3
投票

设置起来需要更多工作,但如果可维护性胜过一次性工作,那么这可能就是您的情况。


3
投票

优点:

不受参数顺序限制

易于扩展
  • 输入脚本支持:

如果您使用 ES6 兼容性,我制作了一个小型库来定义结构。


1
投票
JKT Parser

例如,您可以像这样创建结构 const Person = jkt` name: String age: Number ` const someVar = Person({ name: "Aditya", age: "26" }) someVar.name // print "Aditya" someVar.age // print 26 (integer) someVar.toJSON() // produce json object with defined schema

这是一个老问题,似乎还没有得到解决。无论如何,我使用不变性来获得类似的行为。使用打字稿:

0
投票

这为您带来了复杂值类型的一个关键好处,即您不会通过对对象的引用意外地修改该对象。

当然,缺点是如果您确实想要修改成员,则必须创建一个新实例,因此需要静态 
SetX

SetY

函数。

这是很多语法糖,但我认为对于特殊情况来说这是值得的,比如
Point
,如果值被意外更改,可能会被大量使用并导致很多错误。

此功能允许您创建具有预定义属性的结构化对象。调用 Struct 时,您传入一个定义该结构体属性的构造函数。


0
投票

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)


优点

灵活性

可重复使用性
  • 运行时动态属性分配。
  • 缺点

缺乏属性的类型检查。

  • 这个过程对我来说很有效。将智能合约从 Hardhat Dev-env 部署到 Ganachi 区块链测试网。

-1
投票

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_; 
 }
}

© www.soinside.com 2019 - 2024. All rights reserved.