Why is the second parameter to JSON.parse called “reviver”? - javascript

From the MDN documentation:
reviver (Optional)
If a function, prescribes how the value originally produced by parsing is transformed, before being returned.
Its name strikes me as odd. Maybe I’m missing a metaphor here — why would this be called “reviving” an object? Is there any history to such a transformer function being called a “reviver”? Googling reviver +javascript shows that JSON.parse is basically the only place where this term is used.

The idea is that native Javascript objects, like a Number(42), are your "live" objects. When you serialise those into a JSON representation, they're "dried up", or "dumbed down", or whatever you want to call it. To get your fresh live Javascript objects back, you need to "revive" them from their simple text representation.
This becomes more apparent if you use more complex objects:
function Foo(bar) {
this.bar = bar;
}
Foo.prototype.baz = function () {
alert(this.bar);
};
var f = Foo(42);
f.baz();
f = JSON.parse(JSON.stringify(f));
f.baz(); // Nope
To get the original object back which has a baz method, you need to do a little more than just parse it. That's the "reviving" part.

The parse function is used to create an object from data that has been serialized into a string. By default, all it can do is reconstitute the data into plain objects with a bunch of properties.
Sometimes, you may want to "bring these values back to life" (i.e. revive them) into full-fledged objects with methods, behaviors, etc., or even objects that have a particular type, instead of just the lifeless containers of values that JSON.parse() produces by default.
I would say that's why it's called a reviver.

Related

Is it possible to control how object property names get converted to strings in JavaScript?

I'm interested in creating an object that can handle keys of different types separately instead of casting them all to strings. I'm wondering if there's a way to do this with proxies or any other relatively new JavaScript features. If I do something like
const handler = {
get: function(target, name) {
return typeof(name);
}
};
const proxy = new Proxy({}, handler);
and then try to access proxy[1] it returns string as the type. I understand why this is happening, but I'm curious if there's any way to hook into this type conversion and control it. I know that I could override Number.prototype.toString, but I would like to only modify this behavior when the property name is being processed. Ideally I would want something analogous to this.
const handler = {
convertPropertyNameToString: function(target, name) {
return `${typeof(name)}--${name}`;
}
};
const proxy = new Proxy({}, handler);
I just want to control the conversion of the property names into strings for a specific object. If there's not a straightforward way to do it, then I'm also open to creative hacks.
With normal property access, e.g. foo.bar and foo[thing], the key is converted to a string before the object itself even knows there is an access coming. The get trap on a proxy only gets access to it after than point, so it is guaranteed that a string or Symbol.
If you're interested, you can see that in the spec for property access where on step (6) it is converted to a string. The logic to actually access the property does not happen until much later and has no knowledge about where the stringified key came from.
The best you could do is use your own function, e.g. proxy.readKey(name) where obviously name can be any value. As mentioned in the comments, this is similar to the interface used for ES6 Map instances.

Breakpoint on any string assignment if string contains a certain substring

Can I put a data breakpoint which triggers if any variable is assigned to a string containing a certain substring?
For example, I want to reverse-engineer how a URL containing &ctoken= is constructed. It's done with complicated JavaScript where the goal is to obfuscate it.
If I could tell the JS VM to monitor all string variables and break when a certain substring appears on any variable, this would help me a lot.
Is this possible?
Before I start - as of my knowledge this is not possible.
What you'd need (even before creating the debugging feature) is the raw string types already boxed to String the native built-in object and String then already proxied.
Some more explanation:
only having
const s = "hi"
is not yet an instance of String - the built-in native object, which is supplied by the ECMAScript implementation to your scope - but a raw type.
Such raw types are nothing more than pointers to a raw data memory reference. I even assume there are built in pools like in Java to optimize cases like
const s = "hi"
const x = new String("hi")
to be the same memory reference of the data object. but the later of course would be boxed by String.
http://bespin.cz/~ondras/html/classv8_1_1String.html
On raw types we couldn't - even if we wanted to - add a subscriber.
for example then:
s.charAt(i)
will autobox s to its wrapper String.
to observe every raw type would mean that we'd have to box all raw strings to String which wouldn't be a good thing for performance at all.
not only that but also the implementation of String itself would have to allow us to add a subscriber and therefore be proxied already.
in JS such proxy would look like this (to make it more understandable what I mean by proxied):
var proxiedString = new Proxy(String, {
defineProperty(target, propKey, propDesc) {
console.log('defined a new string')
},
set(obj, prop, value) {
console.log('set a new value to a string')
}
});
proxiedString.x = 'newPropValue'
and that again I guess - wouldn't be good for performance.
You can use condition breakpoints at browser devTools, by right
click with a menu.
If you can write a js somewhere in a page, you
can do this:
.
if(window.location.pathname.indexOf("&ctoken=") > -1){
debugger;// browser will put breakpoint automaticaly here, if condition is trully.
console.dir(window.location);
}

How to convert a complex javascript object to string and back

I have an object that contains arrays which is made up of other arrays it also contains methods. The problem that i am facing is that i can't use JSon because of the multidimensional arrays and the methods.
The reason i want to convert it to a string is to store into the Iphone's
localStorage.
you can only store text inside of there and i was hoping for a way to store a complex object about a user as a string and able to deserialize it again after. Is there even a way to do this. I don't know javascript well enough to write my own api. That was the option i started to try and look into at this point :(
Serialize it to JSON. You can serialize / deserialize complex objects and arrays.
There is no way you can serialize methods (code).
For local storage persistence I would recommend Lawnchair.
no need to store in localStorage you can use global array any where in your application try this once
It's normally possible to serialise a method using myfunc.toString()
So, you could use a replacer function in JSON.stringify() and JSON.parse() to recognise methods, and call .toString() on them, and them somehow recognise them on parsing and turn them back into first class functions.
However - note that a reconstructed function will not have access to the original object's scope, i.e. private variables, or methods, etc.
e.g.
function A() {
var foo = 'bar';
this.test = function test() { console.log(foo) };
};
var b = new A();
var f = b.test.toString(); // the text of the method
b.test2 = new Function(f);
b.test2();
> undefined
well,
there is a way to convert object with functions to string and vise verse. take a look at this plugin:
http://www.eslinstructor.net/jsonfn/
good luck,
-Vadim

Convert json object to json string and use it's functions?

I have a json object with a function:
var thread = {
title: "my title",
delete: function() {
alert("deleted");
}
};
thread.delete(); // alerted "deleted"
thread_json = JSON.encode(thread); // convert to json from object
thread_object = JSON.decode(thread_json); // convert to object from json
thread_object.delete(); // this didn't work
After I converted it back from json string to object, I could not use delete() function.
When you convert something to json, the functions are gone?
Are there ways to keep them in the json string?
I'm using Mootools.
You got it. Take a look at that JSON.encode output. Only simple data types are allowed in JSON representations, partly for ease of creation, and partly for security. (The reason we use something like JSON.decode instead of eval is the possibility of embedding functions.)
You'll have to modify the JSON library source code to accept functions, or write your own in order to preserve the literal definition of the object upon conversion to string.
Consider, though, the possibility that you don't really need to do this. There's probably a better solution, but I can't begin to address that without knowing your exact situation.

Javascript Array Key Retrieval

My JavaScript code stores a lot of data in arrays. I want to retrieve a key using something similar to what I wrote below. It key that should be retrieved is based on variables that are page-dependent . The following code doesn't work. Can anyone give me a solution to this problem?
This is part of a script that does automatic conjugation. (looks for SUBJECT in a div and then looks for VERB in another div and then conjugates the verb by retrieving the conjugated form from the array)
function getarray(Array,Key) {
return Array[Key];
}
Example of how it should work:
verb = innerhtmlfromdiv;
subject = innerhtmlfromotherdiv;
function getarray(Array,Key) {
return Array[Key]; }
conjugatedverb = getarray(verb,subject);
htmltextbox.value = conjugatedverb;
First off, what you want is an Object, not an Array. I'm guessing that you're new to javascript and your previous language was either PHP or PERL, and so you think what you're using is an "Associative Array".
The basics: There is no such thing as Associative arrays in Javascript. There is Objects, and a non-primitive subclass of Object called Array, which has some methods for dealing with Numericly named object properties, and a magic length property.
Since the keys you are dealing with are strings, not numbers, you have no use for Arrays.
Javascript Objects on the other hand are similar to an Associative array in php, or a hash in perl. (but they are not exactly the same thing).
As you have no doubt discovered, with an Object, you can use subscript notation to access certain properties, as in
verbs["go"] = "went";
this is equivilent to
verbs.go = "went";
a common mistake is to think that the dot notation is only used for objects, and the subscript notation for "associative arrays", because this is how it works in PHP. In javascript the two notations are interchangable. Since Arrays are a subclass of Object, the above examples work on them as well (but they don't use any special properties of Arrays).
As for your specific problem:
You need an object full of objects.
so for instance
var verbs = {
"do":{"Truck":"Drive","Blender":"Turn On","Bike":"Ride"},
"take":{"Money":"Steal","Julie":"Accompany","Lever":"Pull}
}
then your function would be:
function conjugate (verb, subject) {
return verbs[verb][subject];
}
and an example of its use would be
conjugate("do","Truck") // returns "Drive"
Try changing the parameter name Array to something else. Array is the name of a built-in function/object in javascript.
I don't quite get the point of the function. This is like writing:
function getValue(var) {return var}
Why not just get the value the normal way without wrapping it in a useless function:
conjugatedverb = verb[subject];
htmltextbox.value = conjugatedverb;
Also, your code doesn't make sense when you claim to do an innerHTML from an element and somehow get an object instead of a string. What is really going on? I think your problem starts even before this snippet of code.

Categories