How to get an array from ArrayBuffer? - javascript

I have an ArrayBuffer which looks like:
This buffer is placed under variable named myBuffer and what I'm interested in, is to get the Uint8Array from this object.
I tried to loop as:
myBuffer.forEach(function(element) {
console.log(element);
});
and to directly access to the Array as:
console.log(myBuffer['[[Uint8Array]]']);
console.log(myBuffer['Uint8Array']);
but seems none of this is the correct approach

Those pseudo-properties you are seeing are something the developer console is putting there for your benefit. They aren't really there at all, as a property or a symbol (AFAIK), and even if they were it would be non-standard.
You can easily get a Uint8Array view of your buffer the standard way like this though:
new Uint8Array(myBuffer)

You will first need to convert the array buffer into a typed array, then from there you can use the spread operator to create an array
const typedArray = new Uint8Array(myBuffer);
const array = [...typedArray];

Related

How to serialize a Map in javascript?

So...there is this type in js called Map and it is really nice...it is faster than an Object for iterations and calculations so I really like it. However...you can't pass Maps around as you could with objects.
I know that I could turn Map into JSON but it is costly to do so and it kind of looses the point of using Maps in the first place.
JSON format is not meant for Maps...it was meant for Objects.
So...lets move from the JSON format a little.
Is there a way for me to serialize a Map into a string in any way so that I can then do the opposite - from said serialized Map to end up with a Map
Preferably this method should be as easy to perform as JSON.stringify or its counterpart JSON.parse.
I want to use Map as it is faster and better but I need to send my data as string. The format of the string is not important as long as I can parse it back into a Map
-- edit: Added the missing JSON Stringify function during serialization -
There is a native way of doing this in Javascript.
the Map object has a method called entries() that returns an iterator that will yield each entry in the map as an array with 2 values in it. It will look like [key, value].
To avoid writing any looping code yourself, you can use Array.from() which can consume an iterator and extract each item from it. Having that, the following will give you your Map object in a serialized form.
let mySerialMap = JSON.stringify(Array.from(myMap.entries()))
console.log(mySerialMap)
Now, that's not even the coolest part. But before getting there, let me show you one possible way of using the Map constructor.
let original = new Map([
['key1', 'the-one-value']
['second-key, 'value-two']
])
The array of array that you can see being passed to the Map object is in the same format as what you get from using Array.from(myMap.entries()).
So you can rebuild you map in a single line using the following sample code:
let myMap = new Map(JSON.parse(mySerialMap))
And you can use myMap as you would any Map.
let myMap = new Map(JSON.parse(mySerialMap))
let first = myMap.get('some-key')
myMap.set('another-key', 'some value')
I guess the whole point of Maps/Dictionaries is that you can use objects as keys in them, so:
let a = {}, b = {}, m = new Map();
m.set(a,b);
m.get(a); // b
So you get b since you have a reference on a. Let's say you serialize the Map by creating an Array of arrays, and stringify that to json:
function serialize (map) {
return JSON.stringify([...map.entries()])
}
let s = serialize(m); // '[[{}, {}]]'
// '[[<key>, <val>], … ]'
Than you could:
let m2 = JSON.parse(s).reduce((m, [key, val])=> m.set(key, val) , new Map());
But the question now is: How to get a certain key? Since there does not exist any reference, due to the fact that all objects have been stringified and recreated, it is not possible to query a dedicated key.
So all that would only work for String keys, but that really takes most of power of maps, or in other words, reduces them to simple objects, what is the reason maps were implemented.
To #philipp's point, people who care about the serialization of the Map will probably prefer objects (leverages intuition, reduces '[]' arithmetic). Object.entries() and Object.fromEntries() can make that a bit more literate:
writeMe = new Map()
writeMe.set('a', [1])
writeMe.set('b', {myObjValue: 2})
// ▶ Map(2) {'a' => Array(1), 'b' => {…}}
written = JSON.stringify(Object.fromEntries(writeMe.entries()))
// '{"a":[1],"b":{"myObjValue":2}}'
read = new Map(Object.entries(JSON.parse(written)))
// ▶ Map(2) {'a' => Array(1), 'b' => {…}}
read.get("b")
// ▶ {myObjValue: 2}

Node.JS behaves strange

I have a variable called uids
var uids = [];
Then I write some value to it property
uids[16778923] = "3fd6335d-b0e4-4d77-b304-d30c651ed509"
But before it
if (!uids[user.id]) {
uids[user.id] = generateKey(user);
}
This thing behaves ok. If I try to get the value of it property
uids[currentUser.id]
It will give me a value of this property. If I try to call some methods like
Object.keys(uids);
It will give me, what I expected. And here the mystery comes...
uids;
RAM rest in piece. See the node eating ram
I am very confused now. What's wrong?
This is because you are creating a huge array and node will reserve memory for it - who knows what comes. I'd say that's a scenario where you would use a Map (or a plain object, but Map feels better here.
var uids = new Map();
var key = 456464564564654;
if (! uids.has(key)) {
uids.set(key, generateKey(user))
}
You are creating an empty array (length is zero), then you assign some value to an arbitrary index. This will make the array grow as big as the index and assign the value to that index. Look at this example using node.js REPL:
> var a = []
undefined
> a[5] = "something"
'something'
> a
[ , , , , , 'something' ]
> a.length
6
Instead of creating an array, you could create a Map() or an common javascript object (singleton). Javascript objects behave like Maps but only Strings can be used as keys. If you assign a Number to be key, javascript will convert it to String automatically.
Personally, I would go with objects because they perform better. Instantiating an object takes longer than instantiating a Map (and it doesn't seem like you need to create several groups of "uids"), but once done, adding new keys and retrieving values from any key in faster when using common objects. At least that's how things go in my node.js v6.7.0 on ubuntu 14.04 but you could try for yourself. And it would also make the least alteration to your code.
var uids = {} // common/ordinary empty javascript object instead of array.
if (!uids[user.id]) { // getting value from one key works the same.
uids[user.id] = generateKey(user) // assignment works the same.
}
////
uids[16778923] = "3fd6335d-b0e4-4d77-b304-d30c651ed509" // key will be "16778923".
uids[16778923] // getting value for key "16778923" can be done using 16778923 instead of "16778923".
////
uids[currentUser.id] // still returning values like this.
Object.keys(uids) // still returning an array of keys like this. but they are all Strings.

How does JSON.parse() work?

I have not worked too much on javascript. And, I need to parse a JSON string. So, I want to know what exactly JSON.parse does. For example :
If I assign a json string to a variable like this,
var ab = {"name":"abcd", "details":{"address":"pqrst", "Phone":1234567890}};
Now when I print 'ab', I get an object.
Similarly when I do this :
var pq = '{"name":"abcd", "details":{"address":"pqrst", "Phone":1234567890}}';
var rs = JSON.parse(pq);
The 'rs' is the same object as 'ab'. So what is the difference in two approaches and what does JSON.parse did differently ?
This might be a silly question. But it would be helpful if anybody can explain this.
Thanks.
A Javascript object is a data type in Javascript - it's have property and value pair as you define in your first example.
var ab = {"name":"abcd", "details":{"address":"pqrst", "Phone":1234567890}};
Now What is Json : A JSON string is a data interchange format - it is nothing more than a bunch of characters formatted a particular way (in order for different programs to communicate with each other)
var pq = '{"name":"abcd", "details":{"address":"pqrst", "Phone":1234567890}}';
so it's is a String With json Format.
and at last JSON.parse() Returns the Object corresponding to the given JSON text.
Here is my explanation with a jsfiddle.
//this is already a valid javascript object
//no need for you to use JSON.parse()
var obj1 = {"name":"abcd", "details":"1234"};
console.log(obj1);
//assume you want to pass a json* in your code with an ajax request
//you will receive a string formatted like a javascript object
var str1 = '{"name":"abcd", "details":"1234"}';
console.log(str1);
//in your code you probably want to treat it as an object
//so in order to do so you will use JSON.parse(), which will
//parse the string into a javascript object
var obj2 = JSON.parse(str1);
console.log(obj2);
JSON, or JavaScript Object Notation, is a minimal, readable format for structuring data. It is used primarily to transmit data between a server and web application, as an alternative to XML.
Your 'ab' variable isn't a string, it is a proper javascript object, since you used the {} around it. If you encased the whole thing in "" then it would be a string and would print out as a single line.
Data Type!! That is the answer.
In this case, ab is an object while pq is a string (vaguely speaking). Print is just an operation that displays 'anything' as a string. However, you have to look at the two differently.
String itself is an object which has properties and methods associated with it. In this case, pq is like an object which has a value: {"name":"abcd", "details":{"address":"pqrst", "Phone":1234567890}} and for example, it has a property called length whose value is 66.
But ab is an object and you can look at name and details as its properties.
What JSON.parse() did differently was that, it parsed (converted) that string into an object. Not all strings can be parsed into objects. Try passing {"name":"abc" and JSON.parse will throw an exception.
Before parsing, pq did not have any property name. If you did something like pq.name, it'll return you undefined. But when you parsed it using JSON.parse() then rs.name will return the string "abcd". But rs will not have the property length anymore because it is not a string. If you tried rs.length then you'll get a value undefined.

Javascript pushing objects into array changes entire array

I'm using a specific game making framework but I think the question applies to javascript
I was trying to make a narration script so the player can see "The orc hits you." at the bottom of his screen. I wanted to show the last 4 messages at one time and possibly allow the player to look back to see 30-50 messages in a log if they want. To do this I set up and object and an array to push the objects into.
So I set up some variables like this initially...
servermessage: {"color1":"yellow", "color2":"white", "message1":"", "message2":""},
servermessagelist: new Array(),
and when I use this command (below) multiple times with different data called by an event by manipulating servermessage.color1 ... .message1 etc...
servermessagelist.push(servermessage)
it overwrites the entire array with copies of that data... any idea why or what I can do about it.
So if I push color1 "RED" and message1 "Rover".. the data is correct then if I push
color1"yellow" and message1 "Bus" the data is two copies of .color1:"yellow" .message1:"Bus"
When you push servermessage into servermessagelist you're really (more or less) pushing a reference to that object. So any changes made to servermessage are reflected everywhere you have a reference to it. It sounds like what you want to do is push a clone of the object into the list.
Declare a function as follows:
function cloneMessage(servermessage) {
var clone ={};
for( var key in servermessage ){
if(servermessage.hasOwnProperty(key)) //ensure not adding inherited props
clone[key]=servermessage[key];
}
return clone;
}
Then everytime you want to push a message into the list do:
servermessagelist.push( cloneMessage(servermessage) );
When you add the object to the array, it's only a reference to the object that is added. The object is not copied by adding it to the array. So, when you later change the object and add it to the array again, you just have an array with several references to the same object.
Create a new object for each addition to the array:
servermessage = {"color1":"yellow", "color2":"white", "message1":"", "message2":""};
servermessagelist.push(servermessage);
servermessage = {"color1":"green", "color2":"red", "message1":"", "message2":"nice work"};
servermessagelist.push(servermessage);
There are two ways to use deep copy the object before pushing it into the array.
1. create new object by object method and then push it.
servermessagelist = [];
servermessagelist.push(Object.assign({}, servermessage));
Create an new reference of object by JSON stringigy method and push it with parse method.
servermessagelist = [];
servermessagelist.push(JSON.parse(JSON.stringify(servermessage));
This method is useful for nested objects.
servermessagelist: new Array() empties the array every time it's executed. Only execute that code once when you originally initialize the array.
I also had same issue. I had bit complex object that I was pushing in to the array. What I did; I Convert JSON object as String using JSON.stringify() and push in to the Array.
When it is returning from the array I just convert that String to JSON object using JSON.parse().
This is working fine for me though it is bit far more round solution.
Post here If you guys having alternative options
I do not know why a JSON way of doing this has not been suggested yet.
You can first stringify the object and then parse it again to get a copy of the object.
let uniqueArr = [];
let referencesArr = [];
let obj = {a: 1, b:2};
uniqueArr.push(JSON.parse(JSON.stringify(obj)));
referencesArr.push(obj);
obj.a = 3;
obj.c = 5;
uniqueArr.push(JSON.parse(JSON.stringify(obj)));
referencesArr.push(obj);
//You can see the differences in the console logs
console.log(uniqueArr);
console.log(referencesArr);
This solution also work on the object containing nested keys.
Before pushing, stringify the obj by
JSON.stringify(obj)
And when you are using, parse by
JSON.parse(obj);
As mentioned multiple times above, the easiest way of doing this would be making it a string and converting it back to JSON Object.
this.<JSONObjectArray>.push(JSON.parse(JSON.stringify(<JSONObject>)));
Works like a charm.

Convert a javascript associative array into json object using stringify and vice versa

I have a javascript associative array like one below
var my_cars= new Array()
my_cars["cool"]="Mustang";
my_cars["family"]="Station Wagon";
my_cars["big"]="SUV";
I want to convert it using Stringify to json object. I want to know after conversion how the json object will look like.
Also when i have this object How I can convert it back to associative array again.
First of all, by making my_cars an array and stringifying it, you don't get what you expect.
var my_cars= new Array()
my_cars["cool"]="Mustang";
my_cars["family"]="Station Wagon";
my_cars["big"]="SUV";
alert(JSON.stringify(my_cars));
This alerts [].
What you want is to start with {}:
var my_cars= {};
my_cars["cool"]="Mustang";
my_cars["family"]="Station Wagon";
my_cars["big"]="SUV";
alert(JSON.stringify(my_cars));
This alerts
{"cool":"Mustang","family":"Station Wagon","big":"SUV"}
To get your object back from the string, use JSON.parse().
var s = JSON.stringify(my_cars);
var c = JSON.parse(s);
alert(c.cool);
This alerts "Mustang".
See http://jsfiddle.net/Y2De9/
No,But the user want to use array not json.
Normal JavaScript arrays are designed to hold data with numeric indexes. You can stuff named keys on to them (and this can be useful when you want to store metadata about an array which holds normal, ordered, numerically indexed data), but that isn't what they are designed for. The JSON array data type cannot have named keys on an array.
If you want named keys, use an Object, not an Array.
*source
var test = []; // Object
test[0] = 'test'; //this will be stringified
Now if you want key value pair inside the array
test[1] = {}; // Array
test[1]['b']='item';
var json = JSON.stringify(test);
output
"["test",{"b":"item"}]"
so you can use an index with array,so alternatively
var my_cars= [];
my_cars[0]={};
my_cars[0]["cool"]="Mustang";
my_cars[1]={};
my_cars[1]["family"]="Station Wagon";
my_cars[2]={};
my_cars[2]["big"]="SUV";
console.log(JSON.stringify(my_cars));
Output
"[{"cool":"Mustang"},{"family":"Station Wagon"},{"big":"SUV"}]"
Moving my comment into an answer so I can show you a code example.
These types of array are no-no's in javascript. You should ONLY use an object for non-numeric keys like this. Array indexes should be numbers. Javascript objects can use arbitrary values for keys (like in your example). Arrays happen to "appear" to work because Arrays themselves are objects, but you will not find normal Array methods will work on them. For example, look at this code example.
var my_cars= new Array()
my_cars["cool"]="Mustang";
my_cars["family"]="Station Wagon";
my_cars["big"]="SUV";
alert(my_cars.length); // alerts 0
You have only added properties to the underlying object, not actually added elements to the Array. You should use an Object for this, not an Array. Javascript does not actually have an Associative Array. It has an Object who's properties can often be used like one would use an Associate Array in other languages. But, it's an Object, not an Array.
"JavaScript does not support arrays with named indexes"
The most close state to an associative array is an array with entries converted to properties (as in your case), so I provide a solution for this exact case.
The fun thing is that Chrome's console makes it feel like an associative array: ["cool":"Mustang", "family":"Station Wagon", "big":"SUV"] (Check with F12)
NOTE: open browser's console before running the snippet
var my_cars= new Array()
my_cars["cool"]="Mustang";
my_cars["family"]="Station Wagon";
my_cars["big"]="SUV";
let toAssociative=(keys, values)=>
values.reduce((acc, cv)=>{
acc[acc.shift()]=cv
return acc;
}, keys)
let fromAssociative = (assArr)=>({...assArr})
let serialized = JSON.stringify(fromAssociative(my_cars))
let o = JSON.parse(serialized)
let restored = toAssociative(Object.keys(o) , Object.values(o))
//NOTE: Look at the browser's console before executing (not SO console)
console.log("orig:",my_cars)
//[cool: "Mustang", family: "Station Wagon", big: "SUV"]
console.log("serialized:",serialized)
//{"cool":"Mustang","family":"Station Wagon","big":"SUV"}
console.log("restored:",restored) //NOTE: look at the browser's console (F12)
//[cool: "Mustang", family: "Station Wagon", big: "SUV"]
If for some reason you cannot convert your array into object, for instance you are working on a big framework or legacy code that you dont want to touch and your job is only to add som feature which requires JSON API use, you should consider using JSON.stringify(json,function(k,v){}) version of the API.
In the function you can now decide what to do with value of key is of a specific type.

Categories

Resources