提问人:nickf 提问时间:2/2/2009 最后编辑:Mario Petrovicnickf 更新时间:10/9/2022 访问量:276212
Javascript 中的结构
Structs in Javascript
问:
以前,当我需要存储许多相关变量时,我会创建一个类。
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 中的结构?
答:
我总是使用对象文字
{id: 1, speaker:"john", country: "au"}
评论
new READABLE_PART(ignore everything in here)
{read: "ignore", everything: "ignore", in: "ignore", here: "ignore"} // and then come up with READABLE_PART
我使用对象 JSON 样式作为哑结构(没有成员函数)。
评论
对象文本和构造对象之间的唯一区别是从原型继承的属性。
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
评论
我认为创建一个类来模拟类似 C 的结构,就像你一直在做的那样,是最好的方法。
这是对相关数据进行分组的好方法,并简化了将参数传递给函数的过程。我还认为,JavaScript类更像是C++结构,而不是C++类,考虑到模拟真正的面向对象的功能需要额外的工作。
我发现试图让 JavaScript 更像另一种语言很快就会变得复杂,但我完全支持使用 JavaScript 类作为无功能结构。
评论
真正的问题是,语言中的结构应该是值类型,而不是引用类型。建议使用对象(引用类型)代替结构。虽然这可以达到其目的,但它回避了程序员实际上希望使用值类型(如基元)代替引用类型的好处。首先,值类型不应导致内存泄漏。
编辑: 有一项提案正在酝酿中,以涵盖这一目的。
//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"];
按照 Markus 的回答,在较新版本的 JS(我认为是 ES6)中,您可以更简单地使用 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
评论
我做了一个小库来定义结构,如果你使用ES6兼容性。
这是一个 JKT 解析器,您可以在此处查看项目存储库 JKT 解析器
举个例子,你可以像这样创建你的结构体
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
设置工作量更大,但如果可维护性胜过一次性工作,那么这可能是您的情况。
/**
* @class
*/
class Reference {
/**
* @constructs Reference
* @param {Object} p The properties.
* @param {String} p.class The class name.
* @param {String} p.field The field name.
*/
constructor(p={}) {
this.class = p.class;
this.field = p.field;
}
}
优势:
- 不受参数顺序的约束
- 易于扩展
- 类型脚本支持:
这是一个似乎尚未解决的老问题。就其价值而言,我使用不变性来获得类似的行为。使用 Typescript:
export class Point {
public readonly X: number;
public readonly Y: number;
constructor(x: number, y: number)
{
this.X = x;
this.Y = y;
}
public static SetX(value: number) : Point {
return new Point(value, this.Y);
}
public static SetY(value: number) : Point {
return new Point(this.X, value);
}
}
这为您提供了复杂值类型的一个关键好处,即您不能通过对对象的引用意外修改对象。
当然,缺点是,如果你确实想修改一个成员,你必须创建一个新实例,因此是静态和函数。SetX
SetY
这是很多语法糖,但我认为对于特殊情况是值得的,例如,如果意外更改值,它可能会被大量使用并导致很多错误。Point
这个过程对我有用。将智能合约从 Hardhat Dev-env 部署到 Ganachi 区块链测试网。
文件:./scripts/deploy,.js
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_;
}
}
下一个:生成填字游戏的算法 [已关闭]
评论