I've seen lots of people using window. when calling some variable. But aren't all the variables of a same window actually in window?
Example:
window.onorientationchange = function() {
var orientation = window.orientation; // <-- WHY?
switch(orientation) {
/* ... */
}
}
But the same people use alert(), document, etc. So why?
At certain times you want to expose only certain functions/variables to be explicit properties of the window.
(function() {
var jQuery = function(selector) { alert( selector ) }
})();
jQuery // not defined
If we alter it to be:
(function() {
var jQuery = function(selector) { alert( selector ) }
window.jQuery = jQuery;
})();
then we "expose" it from a private namespace explicitly.
And yes, you do not have to explicitly declare window. to invoke methods such as alert, but everyone has their own style of coding and everyone has their own degree of how explicit their statements should be.
Some people explicitly prefix window. to global methods such as alert in order to avoid any confusion. Let's say you defined a function in a private namespace that was named alert, for example...
(function() {
function alert() {}
alert('lol'); // does nothing
window.alert('lol') // does something
})();
We cannot use alert inside of that private namespace to do our alerting, since we defined a function with exactly the same name. We have to explicitly reference the window.alert method to get around that.
But for general purposes, I would say it's perfectly fine to not prefix things with window. unless you are exposing things in a private namespace to the global namespace. So please use document and alert and such as is, in your code.
In many javascript tutorials alert(), document() and so on are used without fully qualified window object and I think they just repeat that code.
Related
I'm using ECMAScript Edition 6, not sure if that's even relevant. Anyway, I'm new to JavaScript and I'm trying to make a script that checks if a file(.pdf) exists and opens it if it does, but if not it opens a default page(.html) that shows where to get the desired file (.pdf). I want to avoid libraries such as jQuery, Bootstrap, AJAX... etc. I'm using "http://www.jslint.com" for validation.
The error is "Expected 'new' before 'UrlExists'.".
Thank you!
// These are declarations of global variables for use with http://www.jslint.com/
/*global window */
/*global document */
/*global alert */
/*global XMLHttpRequest */
"use strict"; // This is not necessary, but helps catch errors if they occur.
//get id
function $(id)
{
return document.getElementById(id);
}
// This function is called from the click events triggered by the onload or load function.
// It calls the appropriate function depending on what the UrlExists function returns.
function mylinkclicked(mylocalfile, myurl)
{
if (UrlExists(mylocalfile))
{
alert ("It exists!");
}
else
{
alert ("It does NOT exists!");
}
}
// This funtion will run when the page fully loads, and without causing any errors.
function after_all_loads_gogogo()
{
$("undergraduatecatalog").onclick = function() {var mylocalfile = "./local_files/catalog.pdf"; var myurl = "./resource_help/catalogdefault.html"; mylinkclicked(mylocalfile, myurl);};
$("classschedule").onclick = function() {var mylocalfile = "./local_files/schedule/schedule.html"; var myurl = "./resource_help/scheduledefault.html"; mylinkclicked(mylocalfile, myurl);};
$("degreerequirements").onclick = function() {var mylocalfile = "./local_files/degreerequirements.pdf"; var myurl = "./resource_help/degreereqdefault.html"; mylinkclicked(mylocalfile, myurl);};
}
if (window.attachEvent) {window.attachEvent('onload', after_all_loads_gogogo);}
else if (window.addEventListener) {window.addEventListener('load', after_all_loads_gogogo, false);}
else {document.addEventListener('load', after_all_loads_gogogo, false);}
It is convention to use title case for classes and constructors and use camel or snake case for general functions. The concept, so far as I understand it, is to address an object type properly and distinguish between loose functions and constructors.
Many JS tools have a rule to enforce this, often enabled by default (the ESLint equivalent is new-cap). You can disable them, if you would like, or follow their coding standard and use lowercase letters to start loose functions.
Using TitleCase for classes and camelCase for functions can help identify a class (or static method) reference at a glance. This can be confusing in JS -- even with a naming convention -- since you can make a constructor that doesn't really construct things, invoke constructors without parens, and a number of other interesting language features.
I try to submit a simple Firefox add-on and got a message from AMO editor about wrapping of variables and functions within a JavaScript object in order to prevent conflicts with other add-ons that may be installed by users. The working code is very simple and looks:
function analyze() {
var uri = document.getElementById('urlbar').value;
var requrl="http://www.myanalyzingsiteaddress.com/" + (uri);
gBrowser.selectedTab = gBrowser.addTab(requrl);
}
Is it enough to make other var names to avoid eventual conflicts or could you point me to other code change, which would fulfill the AMO editor's instruction?
Thank you in advance!
Evgenij
You should have been pointed to Javascript Object Management from the XUL School tutorial.
analyze is a generic name. In an overlay there is only one scope/namespace which is shared by the browser code itself and any additional extension code. It is therefore possible that either the browser or another add-on uses analyze as well and boom.
You need to avoid that by making names a specifc as possible. E.g.
function my_addon_id_analyze() ...
Use an an object with a (pseudo) unique name.
if (!("org" in this)) {
this.org = {};
}
if (!("example" in org)) {
org.example = {};
}
org.example.addonid = {
analyze: function() ...
};
// call
org.example.addonid.analyze();
Or even "hide" your code in an anonymous function. This is then hidden from the DOM as well, so no more <button id="example.org.addonid.mybutton" onclick="analyze()"> event handling. But you can always use addEventListener.
(function() {
"use strict";
function analyze() ...
// wire up an event handler instead of onlick
document.getElementById("example.org.addonid.mybutton").addEventListener("click", analyze);
})();
Mix some/all of the above, as long as you avoid short/generic names:
if (!("org" in this)) {
this.org = {};
}
if (!("example" in org)) {
org.example = {};
}
org.example.addonid = (function() {
function analyze() ...
function notvisibleoutside() ...
// return object of "exported"/"visible" functions.
return {
analyze: analyze
};
})();
// call
org.example.addonid.analyze()
Also, keep in mind that missing var (or let/const) declarations will implicitly declare the variable in the global scope.
E.g.:
function abc() {
for (i = 0; i < 10; ++i) doSomething();
}
Will implicitly declare a variable named i in the global scope (in a XUL window the global scope is window, therefore this will create window.i). Implicit declarations may therefore not only cause conflicts but also create quasi memory leaks, e.g.
function call_me_to_leak_1MB() {
hugeArray = new ArrayBuffer(1<<20);
}
will declare window.hugeArray that lives as long as the browser window is open instead of using a local variable that gets garbage collected as soon as the variables goes out of scope (and there are no more other references, of course).
Using strict mode makes implicit declaration an error, which is helpful to catch and avoid such mistakes early.
So much for the Javascript part. There is still other stuff that might clash.
DOM Ids: Use unique <button id="example.org.addonid.mybutton">, or more CSS friendly <button id="example-org-addonid-mybutton"> (or at the very least something like addonid-mybutton) instead of <button id="mybutton">
CSS: Never style random elements.
No: button { color: green; }
Yep: #example-org-addonid-mybutton { color: green; }
chrome.manifest:
No: content generic content/
Yep: content example-org-addonid content/.
i was exploring in the last few days how big frameworks works , how they assign their function name and it can't(?) be override , i pretty much know how framework work with anonymous function , for example they do it this way or similar version :
(function(){
var Sizzle = function (){
var x;
};
Sizzle.f = function(){
alert("!");
};
window.Sizzle = Sizzle;
})();
i still don't get few things about those huge frameworks and i hope i can find answer :
how do they assign function name and the name can't be override?
in the code above to call the function i need to write Sizzle.f() to get the function to work , but when i use jquery i don't write Jquery.show() , just show() , how do they vanish the "jquery" from "jquery.show()" function call?
by saying the name can't be override i mean , if i create function with one of the jquery functions names , the jquery function will work.
thanks in advance.
As has been shown for #2, it's really easy for BIG_NAMESPACE.Functions.doStuff to be added to anything you want.
var _ = BIG_NAMESPACE.Functions.doStuff;
_(); // runs BIG_NAMESPACE.Functions.doStuff;
As for #1:
Most libraries DO let their functions be overwritten.
It's the values that are inside of the framework's closure which are preserved, for safety reasons.
So you could do something like:
BIG_NAMESPACE.Functions.doStuff = function StealEverything() {};
(BIG_NAMESPACE.Functions.doStuff === StealEverything) // true;
But doStuff would have NO access to any of the variables hidden inside of the framework's closure.
It would also mean that until the page was reloaded, doStuff would also not work the way you want it to.
HOWEVER, in newer versions of JavaScript (ECMA5-compatible browsers), it WILL be possible to do something like what you're suggesting.
BIG_NAMESPACE = (function () {
var do_stuff = function () { console.log("doin' stuff"); },
functions = {
set doStuff (overwrite) { }
get doStuff () { return do_stuff; }
};
return { Functions : functions };
}());
Then, this will work:
BIG_NAMESPACE.Functions.doStuff(); // "doin' stuff"
BIG_NAMESPACE.Functions.doStuff = function () { console.log("ain't doin' jack"); };
BIG_NAMESPACE.Functions.doStuff(); // "doin' stuff"
However, Frameworks aren't going to use this for a LONG time.
This is not even remotely backwards compatible. Maybe in 2016...
There were defineGetter and defineSetter methods as well, but they aren't a formal part of the JavaScript language. Like innerHTML, they're things that the browser vendors put in, to make life better... ...as such, there's no real guarantee that they're going to be in any/all browsers your users have. Plus, they're deprecated, now that new browsers use the get and set constructs that other languages have.
(function(){
var jqueree = {};
jqueree.someval = 22;
jqueree.somefunc = function(){ alert(this.someval); };
window.jqueree = jqueree;
window.somefunc = function(){ jqueree.somefunc.call(jqueree); };
window.$$$ = jqueree;
})();
// all equivalent
window.somefunc();
window.jqueree.somefunc();
$$$.somefunc();
somefunc();
Answering your Questions
At the top of jQuery you'll see: var jQuery = (function() {, which creates the local function (its incomplete; the }); occurs elsewhere).
At the very end of jQuery you'll notice the following, which is how it attaches it to the global namespace:
// Expose jQuery to the global object
window.jQuery = window.$ = jQuery;
I have never seen a jQuery function called without referencing the jQuery object. I think you always need to use jQuery.show() or $.show(); however maybe you're saying you don't have to call window.jQuery.show(), which you are permitted to drop the window, since that is the default.
Using your example
(function(){
/* This is where Sizzle is defined locally, but not exposed globally */
var Sizzle = function (){
var x;
};
/* If you put "window.f = Sizzle.f = function(){" then you could *
* call f() w/o typing Sizzle.f() */
Sizzle.f = function(){
alert("!");
};
/* The following line is what makes it so you can use Sizzle elsewhere *
* on your page (it exposes it globally here) */
window.Sizzle = Sizzle;
})();
use function _name_() {} and the name is static
the simply use var $ = jQuery; to create an alias.
jQuery works this way:
Supposed you have this jQuery code:
$("#title").show();
You have three elements to that line.
$ is a javascript function
"#title" is an argument to that function
.show() is a method call
Here's how it works.
Javascript executes the function named $ and passed it an argument of "#title".
That function does it's business, finds the #title object in the DOM, creates a jQuery object, puts that DOM element into the array in the jQuery object and returns the jQuery object.
The Javascript execution engine then takes the return value from that function call (which is now a jQuery object) and looks for and executes the .show() method on that object.
The .show() method then looks at the array of DOM elements in the jQuery object and does the show operation for each DOM element.
In answer to your question, there is no .show() all by itself. It's a method on a jQuery object and, in this example, that jQuery object is returned from the $("#title") function call.
What's wrong with this—how come the variable foo isn't defined from within onModified() of a Document object?
function Document() {
var foo = "dfsadf";
this.onModified = function() {
alert(foo);
};
}
// Does not alert; "foo" doesn't resolve
new Document().onModified();
I'd like to have public methods on Document that reference variables that are somehow private to Document.
Your Document function is clashing with the Document constructor from the DOM.
document instanceof Document; // true
As with any host-object its behavior completely depends on the host environment, and they often can give you unexpected results.
As far I've tested, on Firefox you are not able to replace its value, therefore I would recommend you to either, rename your function, or, declare it on other scope.
I'm working on a proprietary site, and I'm having some issues. I'm using jQuery along with prototype, and I've got it namespaced properly, so in this question assume you can use $ or jQ as a namespaced reference to jQuery.
So I've got a bunch of functions, some mix jQuery and javascript, some plain javascript, some jQuery only. Now, currently some functions are defined within the document.ready jQuery function, and some are defined outside of it, kind of like this:
jQ(document.ready(function($) {
if ( ifConfig ) {
//page check, function calls here
fnc1();
fnc2();
fnc3();
fnc4();
}
function fnc1() {
//fnc code in here
}
function fnc2() {
//fnc code in here
}
}); //end document.ready
function fnc3() {
}
function fnc4() {
}
Now this is all pseudo code, you can assume the functions are valid and have valid code in them. Recently I was doing some debugging, and one of my functions that was declared and called inside the document.ready said it was undefined. I moved it outside of the document.ready, and everything worked again.
I'm basically trying to understand the order of how functions are initiated/called better, so my question is when do you declare functions inside the document.ready and when do you declare them outside? Do you only declare inside when they're called within that document.ready only? Or should I always just declare them outside of that document.ready?
Thanks.
Generally, you should declare & define your own namespace, where all of your application logic (including functions/methods) is located. That way you avoid collision with other scripts on your site + that way your code is much cleaner and easier to maintenaine.
var myapp = function(){
var foobar1 = null,
foobar2 = null,
foobar3 = null;
return {
getFoobar1: function(){
return foobar1;
},
getFoobar2: function(){
return foobar2;
},
setFoobar1: function(foo){
foobar1 = foo;
},
clickhandler: function(e){
alert('I am an event handler, and I am not anonymous');
}
// etc.
};
};
$(document).ready(function(){
var Application = myapp();
Application.getFoobar2();
$(document).bind('click', Application.clickhandler);
});
That pattern (some call it the "method pattern") creates a closured function/object which also guarantees private member variables within your namespace, only accessible through the getter functions from the outside.
This is really only a pretty basic example, you can push this idea & pattern to an extend, which is very nice & a good thing (IMO).
A great book about this stuff which was named and recommended pretty often is "Javascript: The Good Parts" by Douglas Crockford.
If a function is only used inside the document ready function, then declare it inside so you don't pollute the global scope. Otherwise, declare it outside so it the rest of your script has access to those functions.
(document).ready is more used for things that need to be executed at page load, and not function declarations. If you declare them inside of (document).ready, their scope will be local to that block - if they're only used locally, that's fine and they should be declared there. Otherwise, declare them outside.
So in your example, if the functions are only used in that block, they should be declared in there. If they're used other places additionally, they should be declared outside.