Last active
August 29, 2015 14:09
-
-
Save endash/125e9713c97b7c72d305 to your computer and use it in GitHub Desktop.
Structs in JS - http://bl.ocks.org/endash/125e9713c97b7c72d305
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>Struct</title> | |
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.15.0.css"> | |
</head> | |
<body> | |
<div id="qunit"></div> | |
<div id="qunit-fixture"></div> | |
<script src="http://code.jquery.com/qunit/qunit-1.15.0.js"></script> | |
<script src="struct.js"></script> | |
<script src="struct-tests.js"></script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict"; | |
test("Can define a struct with arguments or an array", function () { | |
var a, b; | |
ok(a = Struct("a", "b", "c")); | |
ok(b = Struct(["a", "b", "c"])); | |
equal(a.attrs.length, 3); | |
equal(b.attrs.length, 3); | |
}); | |
test("Cannot define an empty struct", function () { | |
throws(function () { Struct(); }); | |
throws(function () { Struct([]); }); | |
}); | |
test("Passed attributes must match the definition", function () { | |
var struct = Struct("a", "b", "c"); | |
throws(function () { new struct(); }); | |
throws(function () { new struct({a: 5}); }); | |
throws(function () { new struct({a: 5, b: 8, c: 9, d: 8}); }); | |
}); | |
test("Struct is frozen", function () { | |
var struct = Struct("a", "b", "c"); | |
var obj = new struct({a: 1, b: 2, c: 3}); | |
throws(function () { obj.a = 5 }); | |
}); | |
test("Can read attributes from a struct", function () { | |
var StructA = Struct("a", "b", "c"); | |
equal((new StructA({a: 1, b: 2, c: 3})).a, 1); | |
}); | |
test("Anonymous struct toString", function () { | |
var StructA = Struct("a"); | |
equal(StructA.toString(), "Struct<a>"); | |
}); | |
test("Anonymous struct instance toString", function () { | |
var StructA = Struct("a", "b"); | |
var obj = new StructA({a: 1, b: 2}); | |
equal(obj.toString(), "Struct<a=1,b=2>"); | |
}); | |
test("Named struct toString", function () { | |
var StructA = Struct("name").named("Person"); | |
equal(StructA.toString(), "Person<name>"); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
window.Struct = (function () { | |
"use strict"; | |
function arrayEquals(array1, array2) { | |
if (array1.length != array2.length) { return false; } | |
var i = 0, len = array1.length; | |
for (i; i < len; i++) { | |
if (array1[i] !== array2[i]) { return false; } | |
} | |
return true; | |
} | |
return function(attrNames) { | |
if (arguments.length == 0) throw "Cannot define an empty struct"; | |
if (attrNames.constructor != Array) { attrNames = Array.prototype.slice.call(arguments); } | |
if (!attrNames.length) throw "Cannot define an empty struct"; | |
var sortedAttrNames = attrNames.slice().sort(); | |
var joinedAttrNames = sortedAttrNames.join(", "); | |
var attrsLength = attrNames.length; | |
var name = "Struct"; | |
var func = function (attrs) { | |
if (arguments.length == 0 || attrs.constructor != Object) throw "Must pass a hash of attributes to a Struct"; | |
var keys = Object.keys(attrs).sort(); | |
if (!arrayEquals(keys, sortedAttrNames)) { | |
throw "Attributes (" + keys.join(", ") + ") do not match the struct factory definition (" + joinedAttrNames + ")"; | |
} | |
var i = 0; | |
var attrName; | |
for (i; i < attrsLength; i++) { | |
attrName = attrNames[i]; | |
this[attrName] = attrs[attrName]; | |
} | |
Object.freeze(this); | |
} | |
func.named = function (newName) { | |
if (name != "Struct") throw "This Struct has already been named: '" + name + "'"; | |
name = newName; | |
return this; | |
}; | |
func.toString = function () { return name + "<" + joinedAttrNames + ">"; }; | |
func.attrs = sortedAttrNames; | |
func.prototype = { | |
toString: function () { | |
var attrStrings = [] | |
for (var i = 0, attr; i < sortedAttrNames.length; i++) { | |
attr = sortedAttrNames[i]; | |
attrStrings.push(attr + "=" + this[attr]); | |
} | |
return name + "<" + attrStrings.join(",") + ">"; | |
} | |
}; | |
return func; | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment