Are there some benefits of using the methods defined on the localStorage object versus accessing the object properties directly? For example, instead of:
var x = localStorage.getItem(key);
localStorage.setItem(key, data);
I have been doing this:
var x = localStorage[key];
localStorage[key] = data;
Is there anything wrong with this?
Not really, they are, basically, exactly the same. One uses encapsulation (getter/setter) to better protect the data and for simple usage. You're supposed to use this style (for security).
The other allows for better usage when names(keys) are unknown and for arrays and loops. Use .key() and .length to iterate through your storage items without knowing their actual key names.
I found this to be a great resource : http://diveintohtml5.info/storage.html
This question might provide more insight as well to some: HTML5 localStorage key order
Addendum:
Clearly there has been some confusion about encapsulation. Check out this quick Wikipedia. But seriously, I would hope users of this site know how to google.
Moving on, encapsulation is the idea that you are making little in and out portals for communication with another system. Say you are making an API package for others to use. Say you have an array of information in that API system that gets updated by user input. You could make users of your API directly put that information in the array... using the array[key] method. OR you could use encapsulation. Take the code that adds it to the array and wrap it in a function (say, a setArray() or setWhateverMakesSense() function) that the user of your API calls to add this type of information. Then, in this set function you can check the data for issues, you can add it to the array in the correct way, in case you need it pushed or shifted onto the array in a certain way...etc. you control how the input from the user gets into the actual program. So, by itself it does not add security, but allows for security to be written by you, the author of the API. This also allows for better versioning/updating as users of your API will not have to rewrite code if you decide to make internal changes. But this is inherent to good OOP anyhow. Basically, in Javascript, any function you write is a part of your API. People are often the author of an API and it's sole user. In this case, the question of whether or not to use the encapsulation functions is moot. Just do what you like best. Because only you will be using it.
(Therefore, in response to Natix's comment below...)
In the case here of JavaScript and the localStorage object, they have already written this API, they are the author, and we are its users. If the JavaScript authors decide to change how localStorage works, then it will be much less likely for you to have to rewrite your code if you used the encapsulation methods. But we all know its highly unlikely that this level of change will ever happen, at least not any time soon. And since the authors didn't have any inherent different safety checks to make here, then, currently, both these ways of using localStorage are essentially the same. Except when you try to get data that doesn't exist. The encapsulated getItem function will return null (instead of undefined). That is one reason that encapsulation is suggested to be used; for more predictable/uniform/safer/easier code. And using null also matches other languages. They don't like us using undefined, in general. Not that it actually matters anyhow, assuming your code is good it's all essentially the same. People tend to ignore many of the "suggestions" in JavaScript, lol! Anyhow, encapsulation (in JavaScript) is basically just a shim. However, if we want to do our own custom security/safety checks then we can easily either: write a second encapsulation around the localStorage encapsulate, or just overwrite/replace the existing encapsulation (shim) itself around localStorage. Because JavaScript is just that awesome.
PT
I think they are exactly the same, the only thing the documenation states is:
Note: Although the values can be set and read using the standard
JavaScript property access method, using the getItem and setItem
methods is recommended.
If using the full shim, however, it states that:
The use of methods localStorage.yourKey = yourValue; and delete
localStorage.yourKey; to set or delete a key is not a secure way with
this code.
and the limited shim:
The use of method localStorage.yourKey in order to get, set or delete
a key is not permitted with this code.
One of the biggest benefits I see is that I don't have to check if a value is undefined or not before I JSON.parse() it, since getItem() returns NULL as opposed to undefined.
As long as you don't use the "dot notation" like window.localStorage.key you are probably OK, as it is not available in Windows Phone 7. I haven't tested with brackets (your second example). Personally I always use the set and get functions (your first example).
Well, there is actually a difference, when there is no local storage available for an item:
localStorage.item returns undefined
localStorage.getItem('item') returns null
One popular use case may be when using JSON.parse() of the return value: the parsing fails for undefined, while it works for null
Related
I want to let the user define certain variables without overriding existing ones. For example, an allowed new variable:
myJSON = 123
And an invalid one:
JSON = 123
Because it overrides the existing JSON object. Before adding I could simply check if the variable is different from undefined. But I would prefer to show the user which variables are already taken too.
How can I get a comprehensive list of the browser's built-in variables?
Note that Object.keys(window) and Object.keys(document) don't contain JSON. Which other places should I check to get a comprehensive list of taken variables?
So, originally, I thought that the limitation was that Object.keys enumerates only an object's own properties and not inherited ones. However, trying a simple for...in loop without a hasOwnProperty check failed to yield much more than Object.keys. I also tried looping over globalThis to no avail.
A bit of further research showed that JSON is part of the family of "Standard Built-In Objects". When researching that, I came upon a similar Stack Overflow question regarding how to list all standard built-in objects in Node, and the solution was to leverage getOwnPropertyNames. This proved to be the solution-- rather than getting ≈300 results, I instead got 1000+, among which were "JSON" and "Error".
const allWindowProperties = Object.getOwnPropertyNames(window);
console.log(allWindowProperties);
console.log(allWindowProperties.includes('JSON'));
console.log(allWindowProperties.includes('Error'));
So hopefully this solves your problem. My original comment, however, is still worth exploring: How has this use case manifested? Why is it a necessity to allow the user direct access to the runtime environment to declare variables at all, let alone in the global namespace? Perhaps you have a good reason, and I do think this is an interesting question, but I wonder if perhaps we have a classic X-Y problem here.
I recently got to know about ES6 proxies but I don't see a good reason to use it. I mean, everything that one could do with Proxy can be done without it, except if I'm missing something.
For example, most folks talk about validation when it comes to proxy but one could apply some JS goodness to validate and everyone is fine. I would appreciate if someone could open my eyes to some major use cases of Proxies. Thanks!
I mean, every thing that one could do with Proxy can be done without it...
That isn't remotely true.
Consider the common need to catch access to properties that don't exist:
const o = {foo: "bar"};
console.log(o.blarg);
It's common to want to handle that in a way other than the default, which is to log undefined. Proxy lets us do that, via the get trap. Example:
const o = {foo: "bar"};
const p = new Proxy(o, {
get(target, prop, receiver) {
return prop in target ? target[prop] : "nifty!";
}
});
console.log(p.foo);
console.log(p.blarg);
Another example is the ability to hook into the various operations that get the list of properties on an object. There is no way to hook into that without Proxy. With Proxy, it's easy: You use the has trap or the ownKeys trap depending on what you want to hook into.
In terms of other use cases: Proxy is the ultimate tool for implementing the Facade pattern. Look for the use cases of Facade, and you'll find use cases for Proxy.
There is actually lots you can do with it. Theres an awesome github repo where this guy put together a bunch of proxy resources which you can check out.
https://github.com/mikaelbr/proxy-fun
Also, check out my gists, I recently started playing around with proxies, and I have a couple examples that are pretty unique. You can essentially build your own DSL using proxy and program in a closer fashion to the way you think.
https://gist.github.com/jasuperior
Proxies represent a class of dynamic programming (as in dynamic languages, not the method of problem solving) called metaprogramming, and it is absolutely not the case that anything that can be done with proxies can be done without them. In fact that's really the reason proxies exist: to enable entirely new capabilities that weren't possible before.
Proxies enable you to intercept operations on your objects that would have otherwise been purely the responsibility of the JavaScript engine; property accessing and mutating being the two obvious examples.
T.J.'s answer is a good example of something you can't do without proxies. To give you another, I am using proxies to enable singleton instances of objective entities to allow their backing data stores to be swapped-out and replaced with entirely new objects, without affecting the references that are pointing to those objects.
To do this without proxies, we would have to iterate over each field of the object and swap them out for the new fields in the new object. While it's true JavaScript is dynamic enough to allow that to be possible, Proxies allow it to be solved in a much more elegant way: the hidden backing store of the proxy is simply replaced with the new object and all future property accesses are simply directed to the new backing store rather than the old one, while external references to the object (which is actually the proxy) need be none the wiser. To them, it appears as though it is the same object (because it is), but now it happens to have completely different data behind it.
This is only one example of what you can use Proxies for. They are really quite powerful because of how dynamic they are. I'm just getting to know them, but already I can say I'm quite in love. :)
In ES6 Proxy offers the flexibility of eating your cake and having it back. You do not need to know beforehand the properties going to be get/set like in ES5.
Now with ES6 Proxy you can add new property to an object like so: proxyObj.newProp = 9, Proxy will smile and set the new property without prejudice.
I recently got to know about ES6 proxies but I don't see a good reason to use it. I mean, everything that one could do with Proxy can be done without it, except if I'm missing something.
For example, most folks talk about validation when it comes to proxy but one could apply some JS goodness to validate and everyone is fine. I would appreciate if someone could open my eyes to some major use cases of Proxies. Thanks!
I mean, every thing that one could do with Proxy can be done without it...
That isn't remotely true.
Consider the common need to catch access to properties that don't exist:
const o = {foo: "bar"};
console.log(o.blarg);
It's common to want to handle that in a way other than the default, which is to log undefined. Proxy lets us do that, via the get trap. Example:
const o = {foo: "bar"};
const p = new Proxy(o, {
get(target, prop, receiver) {
return prop in target ? target[prop] : "nifty!";
}
});
console.log(p.foo);
console.log(p.blarg);
Another example is the ability to hook into the various operations that get the list of properties on an object. There is no way to hook into that without Proxy. With Proxy, it's easy: You use the has trap or the ownKeys trap depending on what you want to hook into.
In terms of other use cases: Proxy is the ultimate tool for implementing the Facade pattern. Look for the use cases of Facade, and you'll find use cases for Proxy.
There is actually lots you can do with it. Theres an awesome github repo where this guy put together a bunch of proxy resources which you can check out.
https://github.com/mikaelbr/proxy-fun
Also, check out my gists, I recently started playing around with proxies, and I have a couple examples that are pretty unique. You can essentially build your own DSL using proxy and program in a closer fashion to the way you think.
https://gist.github.com/jasuperior
Proxies represent a class of dynamic programming (as in dynamic languages, not the method of problem solving) called metaprogramming, and it is absolutely not the case that anything that can be done with proxies can be done without them. In fact that's really the reason proxies exist: to enable entirely new capabilities that weren't possible before.
Proxies enable you to intercept operations on your objects that would have otherwise been purely the responsibility of the JavaScript engine; property accessing and mutating being the two obvious examples.
T.J.'s answer is a good example of something you can't do without proxies. To give you another, I am using proxies to enable singleton instances of objective entities to allow their backing data stores to be swapped-out and replaced with entirely new objects, without affecting the references that are pointing to those objects.
To do this without proxies, we would have to iterate over each field of the object and swap them out for the new fields in the new object. While it's true JavaScript is dynamic enough to allow that to be possible, Proxies allow it to be solved in a much more elegant way: the hidden backing store of the proxy is simply replaced with the new object and all future property accesses are simply directed to the new backing store rather than the old one, while external references to the object (which is actually the proxy) need be none the wiser. To them, it appears as though it is the same object (because it is), but now it happens to have completely different data behind it.
This is only one example of what you can use Proxies for. They are really quite powerful because of how dynamic they are. I'm just getting to know them, but already I can say I'm quite in love. :)
In ES6 Proxy offers the flexibility of eating your cake and having it back. You do not need to know beforehand the properties going to be get/set like in ES5.
Now with ES6 Proxy you can add new property to an object like so: proxyObj.newProp = 9, Proxy will smile and set the new property without prejudice.
I have a ajax form that populates select lists with values based on the previous selected select list item. This form is used in 3 different views with each view adding an extra select list. I have written some basic validation code that keeps the form process in sync and doesn't confuse the user.
I have written one function that handles all 3 forms in an external script file.
My Question:
Is it acceptable or is there anything I need to worry about if some of my variables are undefined based on the form and view?
Here is some sample code that illustrates my question:
Note: These are not the actual names of my variables.
(function ($){
var objects = {sl1:$('#SelectList1'),sl2:$('#SelectList2'),sl3:$('#SelectList3'),lbl1:$('#Label1'),lbl2:$('#Label2'),lbl3:$('#Label3')};
objects.sl1.change(function(){
mapValues();
}
function mapValues(){
objects.lbl1.text(objects.sl1.val());
objects.lbl2.text(objects.sl2.val());
objects.lbl3.text(objects.sl3.val());//What if this select list is undefined for View1?
}
})(jQuery);
To summarize, View #1 has SelectList1 & SelectList2. View #2 has all 3. Is there a performance issue or is it bad practice to call a function where some of the variables are undefined?
Thanks.
This is more of a jQuery issue, not a JS one. jQuery simply does nothing (it does not even fail!) if you execute a method such as .text() or .val() on an empty result from a selector. For the performance issue, test it yourself. If the element is not found, I expect the performance to be a little better compared to when an element exists.
So, it's valid to use such code.
Note that you're mixing up "undefined variables" with "non-available elements" which are totally different matters. Using undefined variables is strongly discouraged and often lead to unexpected behavior.
I think it's more about readability and maintainability at this point. I mean would it be clear to another developer just by looking at your JS that View #1 has SelectList1 & SelectList2 ? Looking at the code you would think it has all three since all the forms use the same JS. Maybe making it more flexible to where individual forms can specify which selectLists are contained within the respective form, this way the global script is only using the selectLists specified in the forms and not assuming all at available.
Yes it is bad practice. And is source of bugs.
For good practice, define default value, and/or check for it in your function.
thats why you should use the || operator
e.g. :
( $('#SelectList1').length || '0')
The issue is that you will introduce a level of uncertainty, and hence hard to trace bugs, if you do so. Different JS parsers will respond differently - some are more forgiving and will do nothing, others will just crash. So right away you have potential cross-browser issues.
Further, as those variables get passed around inside your code, if you do not know their values, you'll have a difficult time predicting how the rest of your code will interact with them. So now you also have potential logic/program bugs.
So do yourself a favor and a) check that any required parameters are passed, and do some error handling if it is not and b) make sure optional parameters are handled as soon as you receive them (eg assign them a default value, make sure they don't get passed on to other functions if they are not defined, whatever is most appropriate for your application logic).
OK, so I have created an HTML5 canvas game that uses localStorage. I have localStorage working perfectly but I'm not sure that it follows the correct standards, or if it is completely fine the way that I have written it.
//check if storage is set already, if not set the variable
function checkLocalStorage(){
if (localStorage.timesPlayed){
timesPlayed = Number(localStorage.timesPlayed);
}
else{
timesPlayed = 0;
}
}
//code snippet to increase my variable
timesPlayed += 1;
//code snippet to set the localStorage
localStorage.timesPlayed = timesPlayed;
This works perfectly!? But from what I have read, i should be using localStorage.getItem and localStorage.setItem?
Should I change the way I write localStorage??
This is just the link to the website where I learned this way to access localStorage
http://hacks.mozilla.org/2009/06/localstorage/
It works, and it probably won't break, but I'd still try to cast things in the correct type when using localStorage. getItem and setItem are the preferred ways of doing things, but the thing that jumped out at me was that your methods of getting and setting the value won't work for any type but a number, which means you have to code cautiously if you're using a lot of localStorage.
You're sending a number to localStorage, where it's converted to a string. This can get you into a lot of trouble when dealing with booleans, for example:
var won = false;
localStorage.isWinner = won;
if (localStorage.isWinner) { // always true
alert("You won!");
}
Arrays and objects get ugly too:
localStorage.test = {foo: "bar", dog: "cat"};
// returns "[object Object]"
In other words, what you have works, but it's a good habit to do things correctly and consistently from the start, as it will simplify debugging later. The correct way -- which works with strings, numbers, arrays, objects -- is this:
localStorage.setItem("key", JSON.stringify(value));
JSON.parse(localStorage.getItem("key"));
// or as a de facto alternative
localStorage.key = JSON.stringify(value);
JSON.parse(localStorage.key);
I don't think the array access notation for localStorage is part of the standard, but most browsers that implement will probably allow for that possibility. If you want to be especially careful, then use getItem and setItem - but personally, I don't foresee this being a problem.
Mozilla says:
Although the values can be set and read via the standard JavaScript property access method usage of getItem and setItem methods is recommended.
http://dev.w3.org/html5/webstorage/#storage-0
Even the examples in that draft they use the property access notation, so I think you're OK.
For a small application, direct reading and writing to localStorage is probaby OK, however I think in a more complex application it would be a good idea to wrap localStorage and provide an API with get and set methods suitable for the particular application (e.g. get/setMySpecialObject and get/setMySpecialValue).
I don't think an application should care about where data is stored, it should just call an API to get or set it. The code behind the API works out how to store it and where to get it from. Genearlly it's most efficient to read and write data into an object and read/write to localStorage behind the scenes. Get data from localStorage the first time it is requested and cache it. If it's updated along the way, write back to localStorage as appropriate, it should not require commands from the application to do so.