casting a string as a JavaScript object - javascript

In JavaScript, I can cast convert numbers to strings and vice versa, but there is no way to cast convert a string to an object
num = 1
str = '1'
num_as_str = String(num) // "1"
str_as_num = Number(str) // 1
str = '{ a: "foo", b: "bar", c: { a: "foo", b: "bar" }}'
str_as_obj = Object(str) // does not exist
Assuming my string (to be cast converted as an object) is predictable and relatively simply, what is the best way to achieve the above other than using a regexp to parse out the indiv key-val pairs? Suggestions welcome
background: I want to do the above because I want to be able to pass and receive complex values in a URL. For example, /index.html?q=within({r:20, u: "kms", lat: 35.32, lng: -22.0132}) (of course, I will URL encode/decode properly along the way). Fwiw, the node querystring module wipes out anything other strings, numbers, booleans and arrays by coercing them to empty strings.
background2: of course, I know about JSON.parse and JSON.stringify, but I have a user-submitted URL querystring param that is most easily transmitted as an object, except a querystring cannot deal with an object. That is what I am trying to find a way around.

I want to do the above because I want to be able to pass and receive complex values in a URL
Use JSON, not a JavaScript object initializer.
of course, I know about JSON.parse and JSON.stringify, but I have a user-submitted URL querystring param that is most easily transmitted as an object
The JSON version ({"a":"foo","b":"bar","c":{"a":"foo","b":"bar"}}) is just as easily transmitted. It URI-encodes to
%7B%22a%22%3A%22foo%22%2C%22b%22%3A%22bar%22%2C%22c%22%3A%7B%22a%22%3A%22foo%22%2C%22b%22%3A%22bar%22%7D%7D
vs. your original:
%7Ba%3A%22foo%22%2Cb%3A%22bar%22%2Cc%3A%7Ba%3A%22foo%22%2Cb%3A%22bar%22%7D%7D
Not much difference. (Yes, it's slightly longer.) And it has the advantage that JSON.parse is a built-in feature that doesn't allow arbitrary code execution.
If you must use the object literal string instead, you have to parse that string. There are two built-in ways to do it (eval and new Function), but unfortunately both of them execute the code, and don't limit what the code can be — you can't say, for instance, "only allow an object literal and no function calls."
It sounds like it's entirely possible that User A will be specifying the string and then you'll be evaluating it when showing a page to User B. If so, you can't use eval or new Function without exposing User B to risks from malicious code.
So you'll need to use a parser like Esprima or similar instead. You could probably also adapt Crockford's original JSON parser to allow unquoted property names.
So really, JSON is the way to go, but if you really don't want JSON, use a parser that doesn't allow arbitrary code execution.

Related

why are there 2 quotes around Session.keys in chrome console

look at
Session.keys.selected_player
Is it even a valid String? Just wondering.
Seems like the values in the Session are stored as EJSON strings, so the string you're storing has been passed to the EJSON.stringify function, which returns a string containing your string. It may make more sense to you if try passing the object {test: "test"} to EJSON.stringify and study the return value.
It is a valid string.
Session is an instance of IdMap - Meteor's dictionary class which allows you to use strings, numbers and other EJSONable data as a key. It is not easy to do with plain JS objects as some strings are special properties (like __proto__ or prototype), numbers are converted to strings, etc.

How does String.length work in JavaScript?

I want to know how is the string length of a string calculated in js.
Is is a function call or a class data member.
I want to know what happens when we execute the following code :
a = 'this is a string';
console.log(a.length); // what actually happens at this point?
Also if a do this :
a += ' added something';
console.log(a.length); // at what point is the new length calculated
//and/or updated for the object 'a';
And at last, do I need to store the string length in a temp variable while using a loop over the string or can I directly use the following (which one is faster/processor efficient) :
for(var i=0;i<a.length;i++){
// doing anything here
}
Summing up my question, I want to know the processing behind String.length and which practice is better while looping over strings?
A string is immutable in JavaScript.
a += "somestring" doesn't change the length of a string but makes a new string.
This means there is no "new length", but the length is just part of the definition of the string (more precisely it is stored in the same structure in implementations).
Regarding
for(i=0;i<a.length;i++){ // did you forget the 'var' keyword ?
a not so uncommon practice (if you don't change a) was to optimize it as
for (var i=0, l=a.length; i<l; i++)
in order to avoid the reading of the length but if you compare the performances with modern engines, you'll see this doesn't make the code any faster now.
What you must remember : querying the length of a string is fast because there is no computation. What's a little less fast is building strings (for example with concatenation).
Strings are a primitive type. At least that's what the documentation says. But we can access the length of the string as if we are accessing the property of an object(with the dot notation). Which indicates it's an object, Right?
Turns out, whenever we make a call from the string primitive to some property using the dot notation (for example, say length), the Js engine will take this primitive string and wrap it into an equivalent wrapper object, which is a String object. And then, the .length on that String object returns the length.
Interesting thing to note here is, that when we do something like this, our string still stays the same primitive string during all of this. And a temporary object is created to make our string operation work. Once the required property is fetched, this temporary object is deleted from the memory.
Hope this gives some high level understanding.
I'm answering your first question.
I'm also curious about this puzzle so I did some search myself, ended up finding -
Based on String documentation from Mozilla:
String literals (denoted by double or single quotes) and strings
returned from String calls in a non-constructor context (i.e., without
using the new keyword) are primitive strings. JavaScript automatically
converts primitives to String objects, so that it's possible to use
String object methods for primitive strings. In contexts where a
method is to be invoked on a primitive string or a property lookup
occurs, JavaScript will automatically wrap the string primitive and
call the method or perform the property lookup.
So as I understand, when you use somestring.length, the primitive string will first be wrapped as a String object, and then since the object has its property length, so it's just a internal method call to access and return.

How do I access or replicate string value of an object?

For example, I'm trying to isolate the first 5 characters of window.location.
var ltype, string = 'string';
console.log(window.location); // file:///C:/for example
console.log(typeof window.location); // [OBJECT]
lType=window.location.substr(0,5); // 'not a function' (quite so)
string=window.location;
lType=string.substr(0,5); // fails similarly
Q1: Can I somehow 'bind' substr() to window.location?
I can see that string=window.location replicates a reference and not
a value, so
Q2: How can a separate, discrete copy of a complex structure such as an object or an array be created [without using JSON.stringify() or JSON.parse() - which is what I am presently resorting to]?
try
string = window.location.href.toString();
instead of
string=window.location;
Because window.location will return object not a string.
window.location is an object, so you can't use string functions on it - as you've noticed. In order to get the actual location as a string (to perform string operations on it), you'll need to convert it to a string somehow.
window.location.href is a property provided by the object itself.
window.location.toString() is a method on all JavaScript objects, overridden here.
However, beware of the XY problem. It looks to me like you're trying to retrieve the protocol (the http: bit) of the URI. There's a property for that too - window.location.protocol.
lType = window.location.protocol;
You should use that - it's more robust (consider https:// or, worse, ftp://...).

Passing RegExp objects between content scripts and main add-on script

I am having an issue whereby I create a RegExp object in a content script and pass it as part of an object back to the main script using self.port.emit().
Somewhere along the way it seems to lose its identity as a RegExp and also its toString abilities. The following returns false in the main script, but true in the content script:
Object.prototype.toString.call(regexp) == '[object RegExp]';
regexp instanceof RegExp;
Interestingly for Arrays passed in the same way the following is true:
Object.prototype.toString.call(array) == '[object Array]';
Am I missing something?
The Add-on SDK doesn't pass objects around when you send messages, only strings - it essentially calls JSON.stringify() on one side and then JSON.parse() on the other. The result is easy to predict:
console.log(JSON.stringify(new RegExp()));
This gives you "{}". In other words, JSON.stringify() treats "custom" objects as normal objects without any properties, object prototypes and such are ignored. What you get in your main code is a plain object, same as if you call new Object().
If you need to pass a regular expression to your main code - send regexp.source, create an actual regular expression on the other side. Sending actual objects around isn't possible.
What about if you just sent the regex pattern instead of the whole rexexp object? e.g. encodeURIComponent(regexp.source);

Converting JSONobj to Obj not working?

I'm attempting to convert a JSON object to a "normal" object using the following...
var slaobj = eval('('+s+')');
s being the JSON. however, it doesnt seem to work (It's `.length' is coming back as undefined). What am I doing wrong?
It's `.length' is coming back as undefined
It won't necessarily have a length property, unless it's an array or some other object that has one. For example:
var json = '{"foo": "Value of foo"}';
var obj = eval('(' + json + ')');
alert(obj.foo); // alerts "value of foo"
alert(obj.length); // alerts "undefined", there's no `length` in `obj`
Live example
Off-topic: Using eval to deserialize JSON text can be a security problem, unless you can unambiguously trust the source of the JSON text (for instance, it's your own server and you're connecting via SSL), because eval doesn't parse JSON, it parses and runs JavaScript code. (Adding the parentheses doesn't really help.) You can get alternatives to using eval from Douglas Crockford's Github page (he's the inventor of JSON). Last I checked, there are three alternatives there, two of which don't use eval at all; see the README at the bottom of the page for details.
Objects don't all have ".length" properties. An object literal like:
{ 'foo': 100, 'bar': 'Abraham Lincoln' }
describes an object that has no ".length" property.
JavaScript Array objects have ".length" properties because of the way the language runtime works. But a plain object in JavaScript only has such a property if you put it there.
How are you retrieving the object?
I would say there has to be something else wrong - are you sure the 's' JSON object was returned correctly?
JSON.org
To convert a JSON text into an object, you can use the eval() function. eval() invokes the JavaScript compiler. Since JSON is a proper subset of JavaScript, the compiler will correctly parse the text and produce an object structure. The text must be wrapped in parens to avoid tripping on an ambiguity in JavaScript's syntax.
var myObject = eval('(' + myJSONtext + ')');
Update: Ah, I see, that's what the parentheses are for. Rats. Deleted the first part.
But this remains valid:
Don't use eval!
eval() is a dangerous function, which
executes the code it's passed with the
privileges of the caller. If you run
eval() with a string that could be
affected by a malicious party, you may
end up running malicious code on the
user's machine with the permissions of
your webpage / extension. More
importantly, third party code can see
the scope in which eval() was invoked,
which can lead to possible attacks in
ways of which the similar Function is
not susceptible.
Source: Mozilla JavaScript Reference: eval()
http://www.jsonlint.com/ this site has good JSON string validation which you should have at your disposal all the times. It's good to validate the JSON string when its really big.
Also do not user the eval() to get the JSON object. Visit http://www.json.org/ it has really nice guide lines check it.
There are many JavaScript libraries today which offers JSON API. I will suggest you to user one of it for safety.
http://api.jquery.com/jQuery.getJSON/
http://developer.yahoo.com/yui/json/
http://dojotoolkit.org/reference-guide/dojo/_base/json.html

Categories

Resources