What will happen if variable is not declared in Javascript? - javascript

For example, I have code like this:
var Player = function(param){
var self = {
x:0,
y:0,
spdX:0,
spdY:0,
id:"",
}
self.hp = 24;
}
Do I need to add hp inside var self = {}?

I believe others have misunderstood the question. If I understand correctly, you are asking about any potential issues with dynamically adding properties to an existing object (vs. when first declaring the object). The answer is that it is fine to do, is common JS practice and should have no negative performance impact.
This is a perfectly reasonable question if you are coming from a statically typed language background. For example, in TypeScript, you cannot add properties to an object after it has been defined (see this question). This is done for:
Type safety (far and away the main reason)
Performance (possibly).

No
It's completely alright. Relax. Your code isn't going to explode. Breathe. Breathe! Okay, now that you're settled down...
Performance wise, it's the same*: Performance test.
Syntax wise, they are both used in major documentation sites: developer.mozilla.org & W3Schools
*Well as close as it gets

Related

Creating a global variable from a function's return value

I'm looking at Addy Osmani's gist for a publication/subscription pattern here:
https://github.com/addyosmani/pubsubz/blob/master/pubsubz.js
He surfaces his object as a global like this:
;(function ( window, doc, undef ) {
var topics = {},
subUid = -1,
pubsubz ={};
....
getPubSubz = function(){
return pubsubz;
};
window.pubsubz = getPubSubz();
What is the value of creating that getPubSubz function? Wouldn't it be more straightforward to simply write:
window.pubsubz = pubsubz;
Yes, in this case, because getPubSubz is only called in one place, immediately after declaring it, it could safely be inlined.
It's hard to say exactly what the author had in mind, but in a growing code base there may be some value to having a "getter" function which could be modified if the act of getting the pubsubz object required more advanced logic.
It absolutely would be.
There are only two potential reasons why a getter would be used in this case:
There was previously some additional code inside the getter (logging, perhaps)
Addy Osmani's just following good practice*, and including a getter—even adding the opportunity to add additonal code in the future.
Through the power of GitHub, we can actually eliminate option one, as the getter was added in its current state—so I think we can conclusively say that it's just a matter of good practice here.
*as jantimon alludes to in the comments below, this isn't particularly advantageous in most cases (including this one) and this code does not necessarily need to followed as an example.

Is There a Way to Implement EventTarget with Plain JS?

I'm trying (perhaps in vain) to come up with a way to use the publish-subscribe pattern while a) using no libraries and b) minimizing boilerplate code in modules that use it. So far the best I've come up with is this:
var handle = document.createElement();
var unsubscribe = AwesomeModule.subscribe(handle);
handle.addEventListener('awesome', function() {
console.log('awesome');
});
This will work pretty well, except that people using AwesomeModule might be confused by having to provide a random DOM element that isn't used as an element.
I tried the following and it doesn't work too well:
var handle = Object.create(EventTarget);
var unsubscribe = AwesomeModule.subscribe(handle);
handle.addEventListener('awesome', function(){
console.log('awesome')
});
I get TypeError: Object [object Object] has no method 'addEventListener'. Interestingly enough, it doesn't seem to look in the prototype chain even though handle has EventTarget as its prototype.
Why doesn't this work? Is there a way implement EventTarget with pure JS? Can it be done in a single line of code that won't horrify users of AwesomeModule?
EDIT: I don't know why it didn't occur to me last night, but I suppose EventTarget being an interface means that it doesn't have implemented code. What's confusing is that in the Chrome debugger console Object.create(EventTarget) makes an object that appears to have addEventListener in is prototype chain. Maybe its lying. Can anyone explain this behavior? Can anyone explain why W3 chose not to make EventTarget a concrete "class"?
It looks like the answer to my original question is "yes." Since JavaScript doesn't have an inheritance model like Java which does compile-time checks for legal implementation, I suppose any Object can implement an interface merely by having methods with the same name. However, doing this would constitute making a library since the addEventListener code isn't implemented in EventTarget (I had previously assumed it was). Since there seems to be no cross-browser way to get a vanilla EventTarget, I will probably use window.addEventListener in conjunction with custom events.
The source is located here: https://code.google.com/p/chromium/codesearch#chromium/src/third_party/trace-viewer/src/base/event_target.js&sq=package:chromium&type=cs&l=18
If you can't modify it, you can always replicate it.
Here's a simple set of routines that works well.
with a small polyfill for IE9 and 10, support is decent.
you can incorporate these functions into your project as needed, i don't think it constitutes a library, or i wouldn't post this.
var on = addEventListener.bind(window),
off = removeEventListener.bind(window),
emit = function(name, val) {
dispatchEvent(new CustomEvent(name, {
detail: val
}));
};
// demo:
on("test", function(e){ alert(e.detail);});
emit("test", "Number is " + Math.random());
i don't think it can get much simpler (~180 chars) without sacrificing speed or library compatibility.

Can I replace s standard DOM functions like removeChild?

Can I replace s standard DOM functions like removeChild to show for example alert before some node removed from parent? Something like that but my example is with errors
var original = node.removeChild;
node.removeChild = function(node, original){
alert('message');
original(node);
}
If you want to apply this across the document do this
var original = Node.prototype.removeChild;
Node.prototype.removeChild = function(node) {
//custom logic
original.apply(this, arguments);
}
If you want to apply the change only to a selected node then
var original = node.removeChild;
node.removeChild = function(node){
//custom logic
original.apply(this, arguments);
}
First of all, the usage of the new keyword is completely incorrect. That will severely change the behaviour. function is an instance of Function, the "mothership" of all JavaScript functions.
When using the new keyword, the function will be immediately executed and the behaviour very different from what you expect. See Section 13 of the ECMA Language Specification for more details on how to create function objects. Read it here, at page 98.
Second, it is strongly discouraged to alter any native object prototype. It leads to the most tedious and painful bugs in human history. Anybody coming in after you to edit the code will spend a long time before figuring out where that alert originates from.
Keep those two actions separate, they are completely unrelated. Wrapping them up in a prototype function is very bad design, for the above reason any many more, such as:
Using for in loops. You will iterate through more properties that you should if you forget to use hasOwnProperty.
Yourself and other developers will have a hard time figuring out why random things are happing with a basic DOM Node remove operation occurs.(you will forget, happens to everybody).
I am going to be radical an just say no. While it may technically work on the browsers you care about and be the basis for prototype.js, you should never modify DOM objects, or their prototypes, like this.
There is a long post on the topic: http://perfectionkills.com/whats-wrong-with-extending-the-dom/ but the TL;DR is that these are "hosted objects" and modification to their behavior is not guaranteed. It may work today on browser x but there's no guarantee about browser y or even x tomorrow.
Your implementation looks fine, except that you don't need to pass original as an argument there.
var original = node.removeChild;
node.removeChild = function(node) {
alert('message');
original(node);
}

Is that a bad Javascript practice I'm doing here?

for some reason I do that every time because I find it clean. I declare variables on top to use them below. I do that even if I use them only once.
Here is an example (using jQuery framework) :
$("#tbListing").delegate("a.btnEdit", "click", function(e) {
var storeId = $(this).closest("tr").attr("id").replace("store-", ""),
storeName = $(this).closest("tr").find("td:eq(1)").html(),
$currentRow = $(this).closest("tr");
$currentRow.addClass("highlight");
$("#dialogStore")
.data("mode", "edit")
.data("storeId", storeId)
.data("storeName", storeName)
.dialog( "open" );
e.preventDefault();
});
I tend to do that in PHP too. Am I right if I believe it's not very memory efficient to do that ?
Edit: Thank you for all the answers. You have all given good answers. About that code optimisation now. Is that better now ?
$("#tbListing").delegate("a.btnEdit", "click", function(e) {
var $currentRow = $(this).closest("tr"),
storeId = this.rel, /*storing the storeId in the edit button's rel attribute now*/
storeName = $currentRow.find("td:eq(1)").html();
$currentRow.addClass("highlight");
$("#dialogStore")
.data("info", {
"mode" : "edit",
"storeId" : storeId,
"storeName" : storeName
}) /*can anyone confirm that overusing the data isn't very efficient*/
.dialog( "open" );
e.preventDefault();
});
Sorry, are you asking if it's OK to declare variables even if you're using them once?
Absolutely! It makes the code a million times more readable if you name things properly with a variable. Readability should be your primary concern. Memory efficiency should only be a concern if it proves problematic.
As Knuth said,
We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.
If you're asking more about declaring the variables at the beginning of the function, rather than where they are first used, then Emmett has it right - Crockford recommends doing this in JavaScript to avoid scope-related confusion. Whether it's worth it in PHP is a purely subjective question I'd say, but there's nothing wrong with keeping your PHP and JS coding styles similar.
One more CS quote (from Abelson and Sussman's SICP):
programs must be written for people to read, and only incidentally for machines to execute.
It's not bad practice.
The var statements should be the first statements in the function body.
JavaScript does not have block scope,
so defining variables in blocks can
confuse programmers who are
experienced with other C family
languages. Define all variables at the
top of the function.
http://javascript.crockford.com/code.html
Declaring variables at the top is a good thing to do. It makes the code more readable. In your particular example, you could replace $(this).closest('tr') witha variable, as suggested int eh comments, but in general I find code with descriptive variable names all in one place very readable.
nah, I'd say you're doing exactly the right thing.
As #Caspar says, you could simplify your code by setting $currentRow first and using that instead of $(this).closest("tr") in the other two lines. And there may be a few other things you could improve. But setting vars at the begining of a function the way you've done it is absolutely a good thing.
Particuarly good because you've done it inside the function, so they're local variables, which means they get thrown away at the end of the function, so no memory usage issues there.
If you'd set them as global vars, it might have been more of an issue, although to be honest even then, since you're just setting pointers to an existing object, it wouldn't be using a huge amount of memory even then (though it would be polluting the global namespace, which isn't good)

Is there a way to jail in Javascript, so that the DOM isn't visible

I would really like to provide the user some scripting capabilities, while not giving it access to the more powerful features, like altering the DOM. That is, all input/output is tunneled thru a given interface. Like a kind of restricted javacsript.
Example:
If the interface is checkanswer(func)
this are allowed:
checkanswer( function (x,y)={
return x+y;
}
but these are not allowed:
alert(1)
document.write("hello world")
eval("alert()")
EDIT: what I had in mind was a simple language that was implemented using javascript, something like http://stevehanov.ca/blog/index.php?id=92
(Edit This answer relates to your pre-edit question. Don't know of any script languages implemented using Javascript, although I expect there are some. For instance, at one point someone wrote BASIC for Javascript (used to have a link, but it rotted). The remainder of this answer is therefore pretty academic, but I've left it just for discussion, illustration, and even cautionary purposes. Also, I definitely agree with bobince's points — don't do this yourself, use the work of others, such as Caja.)
If you allow any scripting in user-generated content, be ready for the fact you'll be entering an arms race of people finding holes in your protection mechanisms and exploiting them, and you responding to those exploits. I think I'd probably shy away from it, but you know your community and your options for dealing with abuse. So if you're prepared for that:
Because of the way that Javascript does symbol resolution, it seems like it should be possible to evaluate a script in a context where window, document, ActiveXObject, XMLHttpRequest, and similar don't have their usual meanings:
// Define the scoper
var Scoper = (function() {
var rv = {};
rv.scope = function(codeString) {
var window,
document,
ActiveXObject,
XMLHttpRequest,
alert,
setTimeout,
setInterval,
clearTimeout,
clearInterval,
Function,
arguments;
// etc., etc., etc.
// Just declaring `arguments` doesn't work (which makes
// sense, actually), but overwriting it does
arguments = undefined;
// Execute the code; still probably pretty unsafe!
eval(codeString);
};
return rv;;
})();
// Usage:
Scoper.scope(codeString);
(Now that uses the evil eval, but I can't immediately think of a way to shadow the default objects cross-browser without using eval, and if you're receiving the code as text anyway...)
But it doesn't work, it's only a partial solution (more below). The logic there is that any attempt within the code in codeString to access window (for instance) will access the local variable window, not the global; and the same for the others. Unfortunately, because of the way symbols are resolved, any property of window can be accessed with or without the window. prefix (alert, for instance), so you have to list those too. This could be a long list, not least because as bobince points out, IE dumps any DOM element with a name or an ID onto window. So you'd probably have to put all of this in its own iframe so you can do an end-run around that problem and "only" have to deal with the standard stuff. Also note how I made the scope function a property of an object, and then you only call it through the property. That's so that this is set to the Scoper instance (otherwise, on a raw function call, this defaults to window!).
But, as bobince points out, there are just so many different ways to get at things. For instance, this code in codeString successfully breaks the jail above:
(new ('hello'.constructor.constructor)('alert("hello from global");'))()
Now, maybe you could update the jail to make that specific exploit not work (mucking about with the constructor properties on all — all — of the built-in objects), but I tend to doubt it. And if you could, someone (like Bob) would just come up with a new exploit, like this one:
(function(){return this;})().alert("hello again from global!");
Hence the "arms race."
The only really thorough way to do this would be to have a proper Javascript parser built into your site, parse their code and check for illegal accesses, and only then let the code run. It's a lot of work, but if your use-case justifies it...
T.J. Crowder makes an excellent point about the "arms race." It's going to be very tough to build a watertight sandbox.
it's possible to override certain functions, though, quite easily.
Simple functions:
JavaScript: Overriding alert()
And according to this question, even overriding things like document.write is as simple as
document.write = function(str) {}
if that works in the browsers you need to support (I assume it works in all of them), that may be the best solution.
Alternative options:
Sandboxing the script into an IFrame on a different subdomain. It would be possible to manipulate its own DOM and emit alert()s and such, but the surrounding site would remain untouched. You may have to do this anyway, no matter which method(s) you choose
Parsing the user's code using a white list of allowed functions. Awfully complex to do as well, because there are so many notations and variations to take care of.
There are several methods to monitor the DOM for changes, and I'm pretty sure it's possible to build a mechanism that reverts any changes immediately, quite similar to Windows's DLL management. But it's going to be awfully complex to build and very resource-intensive.
Not really. JavaScript is an extremely dynamic language with many hidden or browser-specific features that can be used to break out of any kind of jail you can devise.
Don't try to take this on yourself. Consider using an existing ‘mini-JS-like-language’ project such as Caja.
Sounds like you need to process the user entered data and replace invalid mark-up based on a white list or black-list of allowed content.
You can do it the same way as Facebook did. They're preprocessing all the javascript sources, adding a prefix to all the names other than their own wrapper APIs'.
I got another way: use google gears WorkerPool api
See this
http://code.google.com/apis/gears/api_workerpool.html
A created worker does not have access
to the DOM; objects like document and
window exist only on the main page.
This is a consequence of workers not
sharing any execution state. However,
workers do have access to all
JavaScript built-in functions. Most
Gears methods can also be used,
through a global variable that is
automatically defined:
google.gears.factory. (One exception
is the LocalServer file submitter,
which requires the DOM.) For other
functionality, created workers can ask
the main page to carry out requests.
What about this pattern in order to implement a sandbox?
function safe(code,args)
{
if (!args)
args=[];
return (function(){
for (i in window)
eval("var "+i+";");
return function(){return eval(code);}.apply(0,args);
})();
}
ff=function()
{
return 3.14;
}
console.log(safe("this;"));//Number
console.log(safe("window;"));//undefined
console.log(safe("console;"));//undefined
console.log(safe("Math;"));//MathConstructor
console.log(safe("JSON;"));//JSON
console.log(safe("Element;"));//undefined
console.log(safe("document;"));//undefined
console.log(safe("Math.cos(arguments[0]);",[3.14]));//-0.9999987317275395
console.log(safe("arguments[0]();",[ff]));//3.14
That returns:
Number
undefined
undefined
MathConstructor
JSON
undefined
undefined
-0.9999987317275395
3.14
Can you please provide an exploit suitable to attack this solution ? Just to understand and improve my knowledge, of course :)
THANKS!
This is now easily possible with sandboxed IFrames:
var codeFunction = function(x, y) {
alert("Malicious code!");
return x + y;
}
var iframe = document.createElement("iframe");
iframe.sandbox = "allow-scripts";
iframe.style.display = "none";
iframe.src = `data:text/html,
<script>
var customFunction = ${codeFunction.toString()};
window.onmessage = function(e) {
parent.postMessage(customFunction(e.data.x, e.data.y), '*'); // Get arguments from input object
}
</script>`;
document.body.appendChild(iframe);
iframe.onload = function() {
iframe.contentWindow.postMessage({ // Input object
x: 5,
y: 6
}, "*");
}
window.onmessage = function(e) {
console.log(e.data); // 11
document.body.removeChild(iframe);
}

Categories