Let's say i want to create an object that is named using a variable? how would i do this? is it even possible?
var aName = "obusdiofu";
aName = {check: true, person: false};
console.log(obusdiofu); //gives me the newly created object?
Disclaimer first, per MDN:
Do not ever 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, a third-party code can see the
scope in which eval() was invoked, which can lead to possible attacks
in ways to which the similar Function is not susceptible.
That being said, you can achieve something along those lines like this:
let aName = 'obusdiofu';
eval(`var ${aName} = {check: true, person: false}`);
console.log(obusdiofu);
I can't see why that would ever be necessary, and due to the issues with eval() you would be better off doing something like one of the other posted answers.
You can't do that directly. You'd want to create an object first, then you can store things as custom properties of that object.
var names = {}
var aName = 'obusdiofu'
names[aName] = { check: true, person: false }
Unfortunately, there is no such thing in Javascript, however , you could do something like this :
var aName = "obusdiofu";
this[aName] = {check: true, person: false};
console.log(obusdiofu);
// Or if the code is outside the global scope, then
// you should access it like so :
console.log(this.obusdiofu);
Note: You should be careful though when assigning the aName variable, because not all characters are accepted .
Related
So I'm working on a sort of JavaScript framework, just some utility things for myself to use in future projects, and I want to make a data binding system.
The first method I used was objects, and the code would just loop through the specified html element and look for occurences of {{key}} in the markup and then look for that key in the object and replace it that way in the HTML.
For example, if you had <div>{{name}} is a cool guy</div> in the HTML and had {name:"joseph"} in the JS then the final product would be displayed on screen as 'joseph is a cool guy'.
However, I decided later to change my method and instead the framework would except a function. So instead of {name:"joseph"} you would give it function(){ var name = "joseph" }.
This obviously looks better and gives a lot better functionality.
I changed the processing function so instead of looking for the key/value pair to replace the {{key}}, it just uses eval on the variable to gets its value.
My problem lies here: How do I run my search/replace code INSIDE the scope of the function the user passes.
If the user defines variables within that function, their values will not be available anywhere else due to scope issues.
I've tried using Function.toString() to actually modify the source code of the function, but nothing's working and it's all very complicated.
(The issues are not due to the actual solution, I think that Function.toString() might work, but due to my implementation. I keep getting errors)
So... What is the best way to run arbitrary code in the scope of another function?
Critera:
Obviously, I can't modify the function because the user is passing it in. (you can't just tell me to add the search/replace code to the bottom of the function)
The variables must stay in the local scope of the function. (no cheating by using window.name = "joseph" or anything)
I am also aware of how terrible eval is so any suggestions as to get it to work are greatly appreciated. Thanks!
Code:
function process(html) {
var vars = html.match( /({{)[^{}]*(}})/g )
// vars = ['{{variable}}', '{{anotherVariable}}']
var names = vars.map( function(x){ return x.replace("{{", "").replace("}}", "") } )
// names = ['variable', 'anotherVariable]
obj = {}
for (var i = 0; i < names.length; i++) {
obj[names[i]] = eval(names[i])
}
for (var p in obj) {
html = html.replace(new RegExp('{{'+p+'}}','g'), obj[p]);
}
return html
}
You should go back to your first method with the object, it's much better. You can still pass a function, but the function should return an object:
function () {
return { name: 'joseph' }
}
I discovered some javascript in a site that didn't sanitize external data (siteName), but it's used in such a way that I think does not represent a problem. Certainly, the best thing to do would be to filter it so that only expected values could interact with code and there would be no worry about unexpected input. But, how much damage could be inflicted in the current setup?
var branding = {
'website1.com' : {
color: 'red'
},
'website2.com' : {
color: 'blue'
}
};
var siteName = document.referrer.split('/')[2];
var myElements = document.querySelectorAll(".some-class-name");
for (var i = 0; i < myElements.length; i++) {
myElements[i].style.color = branding[siteName]['color'];
}
This code is poorly conceived, but I don't think it's exploitable.
document.referrer.split('/')[2] extracts the hostname of the referrer. An attacker might have control over the hostname, but only to a limited degree; they can't put anything into that field that they can't register or set up as a domain name.
branding[siteName] could be made to do some interesting things if siteName is the name of an internal property on Object, like __proto__, or a method name, like hasOwnProperty. However, none of these properties would have been valid as Internet hostnames, as none of them have periods in them. __proto__ contains underscores, which aren't even valid in hostnames!
If siteName were not constrained, the following ['color'] still limits this code. Functions (like hasOwnProperty) wouldn't have a color property; nor would the Object prototype, so this looks like a dead end.
Even if we assume that a weird value like a function somehow got into the result, assigning a value like that to .style.color wouldn't do anything weird.
The potential for a vulnerability could easily be avoided, though:
var siteName = document.referrer.split('/')[2];
if (branding.hasOwnProperty(siteName)) {
... everything else ...
}
Object.hasOwnProperty is false for method names and "weird" properties like __proto__; it's only true for properties that have been explicitly declared on an object. This would limit the following code to only running for the intended site names.
I know that it's possible to create a read-only object in Javascript with code similar to this (sorry, "borrowed it" from another thread):
var obj = {};
Object.defineProperty( obj, "<yourPropertyNameHere>", {
value: "<yourPropertyValueHere>",
writable: false,
enumerable: true,
configurable: true
});
But as a Java developer, I know that I can use reflection to change a field that is declared as private. What I need to know is this: is it possible to prevent a malicious end-user from changing a read-only variable declared in the manner above?
Edit: Okay, I get it. This was a component of, not the entirety of, an entire security infrastructure. All inputs from the client-side to the server-side will be validated at the server side (I'm not a total idiot). But I want to explore the possibility of doing SOMETHING to make the client aware of the backend security infrastructure (roles assigned, etc).
This question has only one answer, never trust js. Even thought you can declare it, there is no way to be sure the user won't change the hole object.
The way to avoid the user tampering with your variables is using closure. Just define a function, declare all your variables, and run that function. There is a shorthand for that:
(function () {
//Your code, DECLARE ALL YOUR VARIABLES WITH "var variableName"
//i.e.
var myNumber = 3, myString = 'Hello World', myEmptyVar;
})();
Take a look at 'use strict' (strict mode) and use jshint for better coding
I've recently tested UglifyJS and YUI Compressor and noticed something odd.
Both minifiers don't seem to change the names of object properties, only the names of variables and functions.
for instance if I have the following code:
var objName = {first:2, second:4};
alert(objName.first + " " + objName.second);
the names first and second remain unchanged in the minified version.
Why is that?
Since in javascript a new scope is created in a function, you can scope your code in an immediately invoked function.
// scoped
(function() {
var objName = {first:2, second:4};
alert(objName.first + " " + objName.second);
})();
Then using Google's Closure Compiler, if you turn on the "Advanced" optimization it will see that the properties are only used locally, and will obfuscate them.
// result
var a={a:2,b:4};alert(a.a+" "+a.b);
It's because it doesn't know where the object is going to be used. It could be used externally by other code and you wouldn't want your other code to have to change whenever you obfuscate it.
Edit So basically, it's like that to prevent obfuscation from breaking external/internal references to properties that may not be possible to figure out while obfuscating.
Since there are no well defined scoping rules around objects in JavaScript it's impossible to obfuscate the names in a way that is guaranteed to be correct.
For example, if you had the following function:
function f() {
return { first: 'foo', second: 'bar' };
}
In order to obfuscate the property names you would have to nail down all the places that f is called from. Since functions are first-class in JavaScript they can be assigned and passed around in arbitrary ways making it impossible to pin down where f is referenced without actually running the program.
Additionally, JavaScript doesn't have any way for you to specify intent around what's public API and what isn't. Even if the minimizer could reliably determine where the function is called from in the code you give it, there would be no way for it to make the same changes to code that it hasn't seen.
I guess that's because the minifiers would break the object properties. Consider this:
function getProp(ob,name) {
return ob[name];
}
var objName = {first: 2, second: 4};
var prop = getProp(objName, "second");
There's no way for the minifier to know the string literal "second" being an object property. The minified code could look like this then:
function a(b,c){return b[c]}var d={p1:2,p2:4};var e=a(d,"second")
Broken now.
The latest release of uglify (today) has object property mangling, see v2.4.19. It also supports reserved files for excluding both object properties and variables that you don't want mangled. Check it out.
The only public tool so far to obfuscate property and function names (afaik) is the Closure Compiler's Advanced mode. There are a lot of limitations and restrictions, but the end result is generally worth it.
As a passing note: the Dojo Toolkit is compatible (with some minor modifications) with the Closure Compiler in Advanced mode -- arguably the only large-scale public JavaScript library that can be fully obfuscated. So if you are looking at obfuscation to protect your IP, you should look into using Dojo for the task.
http://dojo-toolkit.33424.n3.nabble.com/file/n2636749/Using_the_Dojo_Toolkit_with_the_Closure_Compiler.pdf?by-user=t
Stephen
What about doing something like:
// scoped
(function() {
var objName = {first:2, second:4};
var vA = 'first';
var vB = 'second';
alert(objName[vA] + " " + objName[vB]);
})();
Once objName.first and/or objName.second are referenced enough times, this technique will start to save characters. I can't think of any reason that wouldn't work, but I can't find any minifiers that do it.
Currently I am working on a legacy web page that uses a ton of JavaScript, jQuery, Microsoft client JavaScript, and other libraries. The bottom line - I cannot rewrite the entire page from scratch as the business cannot justify it. So... it is what it is. Anyway, I need to pollute (I really tried not too) the global namespace with a variable. There are the three options I was thinking about -
Just store/retrieve it using a normal JavaScript declaration - var x = 0;
Use jQuery to store/retrieve the value in a DOM tag - $("body").data("x", 0);
Use a hidden form field, and set/retrieve the value with jQuery - $("whatever").data("x", 0);
Is there a better way? I looked at the existing pile of code, and I do not believe the variable can be scoped in a function.
You can create a namespace inside the jQuery object, like so:
$.mynamespace = {
myVar : "something",
myVar2 : "somethingElse"
};
or:
$.mynamespace = {};
$.mynamespace.myVar = "something";
$.mynamespace.myVar2 = "somethingElse";
Bear in mind, any plugin method named 'mynamespace' will be overwritten so be sure to use a sensible name.
For me the best way to handle this situation is to define an object in the window object:
window.my_config =
{
my_var1 : 1,
my_var1 : 2,
my_var1 : 3
};
This would keep your scope neat and clean. And whenever you would access the global using window.my_config anyone looking at the code would know that a global is being accessed.
You can create a hash in the global scope and use it as a namespace:
MyNamepace={}
MyNamespace.newvar = 'value'
// MyNamespace.newvar => 'value'
Just sharing my practice with you, I would make a global object/var in the required JavaScript file with a sensible prefix, as in if I am working on a page where this object will be a text box then I would name it:
g_TxtMyValue = 'value'; // g_ specifies it to be a global variable, it is one
// of the many conventions used
If you have more than one global variable, you can also have a namespace such as:
my_txt = {}; // For a real site I would use a prefix relative to the project
// name instead of "my".
my_txt.testValueOne = 'Value one';
my_txt.testValueOne = 'Value two';
These variables will be available to you throughout the website, after they have been initialized.
I hope this helps.
Use underscore isEmpty().
_.isEmpty('') will return true.
Just a short notice:
Is the fancybox doing AJAX (meaning: if it loads within an iFrame, you should add "parent" to the close method), like this:
parent.$.fancybox.close();