Design, CG Graphics & Inspiration
JavaScript FAQ: Part 1

JavaScript FAQ: Part 1

I have created a topic where collected different questions about JavaScript that might be interesting to our readers (architecture, framework, problems). So, if you’re intrigued, let’s not waste our time and move straight to the questions.

1. What model of object creation is the most convenient?

If with new, then how should I protectmyself from making mistakes if I follow these rules:

• Constructor functions are always written with a capital letter;
• Check the validity of creating through this instanceofFunction_Name (avoid this instanceofarguments.callee for performance reasons);
• Similarly, the second one, but I check with the window, because I don’t want hardcore the name and I don’t write scripts for out-of-browser environments.

It’s better and more comfortable to create the objects via new. Constructors should be written with a capital letter.
I prefer to base on agreements and don’t check this inside a constructor -if you call the constructor without new it will flow into the globals.And in any case I don’t encourage an error with the new – some check if this is global than it means that the user has called constructor without new and creates an object inside the constructor and returns it – it is encouragement of mistakes and ideologically incorrect approach.

var Obj = function () {
    "use strict";
    this.pew = 100;
};

// Right
new Obj.pew++;

// the user will get a mistake
Obj(); // TypeError: this is undefined

new is not acceptable for factory methods, and short jQuery constructors.

I’m summing it up with the code:

// Good: less code, a mistake is not encouraged , use strict
var Obj = function () {
    "use strict";
    this.pew = 100;
};

// Not so good: superfluous and completely unnecessary code
var Obj = function () {
    if (!(this instanceof Obj)) {
        return new Obj();
    }
    this.pew = 100;
};

2. How to determine which mouse button is pressed on JS?

Mousedown and mouseup events can be called by each of the mouse buttons, and click – only with the left one. It’s necessary to check the code button event.button in the event listener, to see which of the buttons was pressed (0 – left, 1 – Average, 2 – right). In IE8 it’s different, see the code:

var button = document.getElementById('button'),
              //  0       1         2
    buttonMap = ['Left', 'Middle', 'Right'],
    handler = function (event) {
        event = event || window.event;
        alert(buttonMap[event.button] + ' id: ' + event.button);
    };

if (button.addEventListener) {
     button.addEventListener('mousedown',  handler, false);     
} else {
     // IE         0      1       2        3      4
     buttonMap = ['???', 'Left', 'Right', '???', 'Middle'];
     button.attachEvent('onmousedown',  handler);
}

jQuery fixes this IE defect, it is necessary to check event.which in it instead of magic with event.button

$('button').mousedown(function (event) {
    alert(['Left', 'Middle', 'Right'][event.which]);
});

Example: jsfiddle.net/azproduction/W2XgH/
More detailed: www.quirksmode.org/js/events_properties.html The paragraph «Which mouse button has been clicked?»
jQueryevent.which: api.jquery.com/event.which/

3. Is it possible to catch keystrokes events?

Is it possible to intercept keystrokes events (down, up arrow) in javascript, so that the browser then won’t do the windowscrolling? Are there any specific features of browsers in such behavior, if it’s possible? For example there is a table that does not go into the entire screen while moving along the lines implemented by means of arrow keys. It is necessary that the browser won’t be leafing through the page.

To do this you must cancel the so-called default action (Default Action): a down arrow and scrolling the mouse wheel window, right mouse button picks up the context menu by clicking on the sumbit performed form.submit (), when clicking on the input it will receive focus and when clicking on the anchor the browser will go to the link, etc.

Using jQuery you can do it this way:

// IE and Safari doesn't track the arrows on the keypress, and Opera is buggy on keyup
$(window).bind($.browser.opera ? 'keypress' : 'keyup', function (event) {
    event.preventDefault();
    // or
    return false;
});

There is an important point. You must perform preventDefault () before defaultAction fires off. For example, clicking on the input we do not want to give it focus, and then we have to hang on the event handler in the chain before the defaultAction – mousedown.

$('input').bind('mousedown', function (event) {
    event.preventDefault();
    // or
    return false;
});

The very chain of events is as follows:

1. mousedown
2. focus (blur will work at another site before the focus)
3. mouseup
4. click

If we hang the event on the focus and below, it will not work because defaultAction will run after the mousedown.

4. How to solve the problem of stopping gif-animation when you press ESC, if this key is bounded?

Some browsers stop gif animation by pressing the Esc, stop loading the page – this is their default action. You should cancel the default action event.preventDefault ():

$(document).bind($.browser.webkit ? 'keydown' : 'keypress', function (event) { 
    // pressed Esc
    if ((event.which || event.keyCode) === 27) {
        event.preventDefault();
        // or
        return false;
    }
});

5. What is operator (), by means of which shorting is being created?

Brackets allow the parser to understand, what brackets follow after a function: groupment or operator of call function.

If to make it so:

function () {
  // source
}()

In this case we get SyntaxError for lack of the function name (declaration function always must have a name).

If to add the name:

function foo() {
  // source
}()

In second case the name is set (foo), and obviously, declaration of function must pass normally. However, we have an error of syntax, but it relates to the groupment operator without expression inwardly. Pay attention, in this case it is exactly the operator of groupment, which follows by declaration of function, but not brackets of call function!

There is another way to prevent ParseError it is to put a function in the state of expression i.e. to show the parser, that it is exactly the Function Expression:

!function () {
  // source
}();

+function () {
  // source
}();

[function() {
  // source
}()];

var a = function () {
  // source
}();

It is also used in jQuery. It allows distinguishing all code in one block with a local visibility scope. It accelerates access to the internal variables, allows not cluttering up global space of the names and, mainly, is better compressed with minificators.

You can also read: kangax.github.com/nfe/

6. Sending the code in XHR

On the actions of user in ajax -system a server sends the answer of “alert;”. On a client the received answer is driven away through eval() and is being executed. How such communication data is called? It’s not JSON, not XML, and not HTML.

It has no name. Actually it is very bad approach, the same bad as how to keep the code of PHP in database and to eval it each time. Except conditional lack of security such architecture carries after itself a strong tie-up, and in the future it will be difficult to do something. A medley turns out : data + code + presentation, in such model to do something over we will have to unravel this tangle, make alteration, taking into account numerous connections, to tangle back. I say nothing of the trying to tear off the piece of functional from such medley. For simplification of code’s support it is necessary to separate maximally parts of the system and decrease the amount of connections (dependences). For the receipt of weak tie-up(when it is possible to tear off or replace the piece of application maximally painlessly) enter events and, for example, architecture of MVC application.

7. How to organize correctly the implementation turn of time-lagged commands without hangs of all script?

JavaScript has one stream in which a code is being executed, DOM tree is drawn, timers work. Each time when you execute the chain of operations (cycles, heavy functions) co-operating of user with the interface is blocked (if the chain is not heavy, than user does not notice any changes). To prevent blocking of UI Threed Web Workers were brought – the threads in JavaScript. If the use of workers is impossible, then it’s necessary to make the optimization of cycles and heavy functions. As Nicholas C. Zakas writes in the book OReilly High Performance JavaScript: user will not notice lags if UI Threed will be blocked on 100 milliseconds and less. It means that we can calculate 100 milliseconds, then unblock UI Threed, so that user won’t notice any lags.

Here is the original code from his book that was optimized for all processors:

function timedProcessArray(items, process, callback) {
    var todo = items.concat();   //create a clone of the original
    setTimeout(function () {
        var start = +new Date();
        do {
            process(todo.shift());
        } while (todo.length > 0 && (+new Date() - start < 50));
        if (todo.length > 0){
            setTimeout(arguments.callee, 25);
        } else {
            callback(items);
        }
    }, 25);
}

function saveDocument(id) {
    var tasks = [openDocument, writeText, closeDocument, updateUI];
    timedProcessArray(tasks, [id], function(){
        alert("Save completed!");
    });
}

timedProcessArray function blocks UI Threed on 25 milliseconds, executing the chain of actions, than frees UI Threed on 25 milliseconds, etc.

You can also read: Nicholas C. Zakas — OReilly High Performance JavaScript.

8. Is it possible to learn somehow whether the user stopped resizing the window?

There is no such event, but it is possible to learn how many times the user resized it, that approximately corresponds to onresizeend.

Sketch of the code:

var time = 0,
    timerId,
    TIME_ADMISSION = 100; // 0.1s

function onresizeend () {
    console.log('onresizeend');
};

function resizeWatcher () {
    if (+new Date - time >= TIME_ADMISSION) {
        onresizeend();
        if (timerId) {
            window.clearInterval(timerId);
            timerId = null;
        }
    }
};

$(window).resize(function () {
    if (!timerId) {
        timerId = window.setInterval(resizeWatcher, 25);
    }
    time = +new Date;
});

Live example

9. How to open through window.open() new window, but not tab?

This behavior depends on a concrete browser. Opera always opens a new tab (but it appears as a window), Safari always opens a window (behavior of Safari can be gone skipped). Chrome, Fire Fox and IE are controllable.

If to pass additional parameters – position of the window, then a new window will be opened:

window.open('http://www.google.com', '_blank', 'toolbar=0,location=0,menubar=0');

If to pass nothing, then the tab will be opened:

window.open('http://www.google.com');

It is more frequent required to open new tab, here can be a problem with Safari: by default (depends on settings) at any call of window.open function Safari opens a new window. But at a clique on a link (regardless of settings) by pressing Ctrl+Shift/Meta+Shiftalways a new tab is being opened. For opening of new tab we will emulate the event of “click” by pressing Ctrl+Shift/Meta+Shift:

function safariOpenWindowInNewTab(href) {
    var event = document.createEvent('MouseEvents'),
        mac = (navigator.userAgent.indexOf('Macintosh') >= 0);

    // do the Ctrl+Shift+LeftClick/Meta+Shift+LeftClick (trick)
    // create your own event
    event.initMouseEvent(
        /* type */          "click",
        /* canBubble */     true,
        /* cancelable */    true,
        /* view */          window,
        /* detail */        0,
        /* screenX, screenY, clientX, clientY */ 0, 0, 0, 0,
        /* ctrlKey */       !mac,
        /* altKey */        false,
        /* shiftKey */      true,
        /* metaKey */       mac,
        /* button */        0,
        /* relatedTarget */ null
    );

    // we create reference in memory and click by this event on a reference - new tab will be opened
    $('<a/>', {'href': href, 'target': '_blank'})[0].dispatchEvent(event);
}

10. How to do a deep copy effectively?

If oldObject will not change, then it’s more effective to clone through a prototype (it will be very quickly):

function object(o) {
    function F() {}
    F.prototype = o;
    return new F();
}

var newObject = object(oldObject);

If you need the honest cloning, then it will be quicker to walk on the tree object recursively + to do some optimizations (it is the most rapid algorithm of the honest cloning):

var cloner = {
    _clone: function _clone(obj) {
        if (obj instanceof Array) {
            var out = [];
            for (var i = 0, len = obj.length; i < len; i++) {
                var value = obj[i];
                out[i] = (value !== null && typeof value === "object") ? _clone(value) : value;
            }
        } else {
            var out = {};
            for (var key in obj) {
                if (obj.hasOwnProperty(key)) {
                    var value = obj[key];
                    out[key] = (value !== null && typeof value === "object") ? _clone(value) : value;
                }
            }
        }
        return out;
    },

    clone: function(it) {
        return this._clone({
        it: it
        }).it;
    }
};

var newObject = cloner.clone(oldObject);

For jQuery it is possible to use the following:

// shallow copy
var newObject = jQuery.extend({}, oldObject);

// deep copy
var newObject = jQuery.extend(true, {}, oldObject);

You can also read:
Benchmark methods of the honest cloning
What is the most efficient way to clone a JavaScript object?

11. How to make an analogue of destructor/finalizer? And how to manage objects time of life?

In JavaScript an object will be deleted when the last link to him will disappear:

var a = {z: 'z'};

var b = a;
var c = a;

delete a.z;
delete a; // we just delete the "а" link
console.log(b, c); // the object actually exists: Object {} Object {}, but it’s empty

I.e. using a “destructor”, it’s impossible to delete the object fully – it’s only possible to clear the content.

12. Is it possible to do the processing of the binary data? If yes, then how?

In JavaScript all numbers appear for the use in a string type and there are not built-in facilities for working with binary data. There is a library of JavaScript BinaryParser for working with binary numbers: encoding, decoding.

In ECMAScript 6+ (strawman) there is a rough copy of StructType (this struct is familiar to us from C++ and others). It’s is needed for simplification of work with binary files. That is how it could look in the future:

const Point2D = new StructType({ x: uint32, y: uint32 });
const Color = new StructType({ r: uint8, g: uint8, b: uint8 });
const Pixel = new StructType({ point: Point2D, color: Color });

const Triangle = new ArrayType(Pixel, 3);

let t = new Triangle([{ point: { x:  0, y: 0 }, color: { r: 255, g: 255, b: 255 } },
                      { point: { x:  5, y: 5 }, color: { r: 128, g: 0,   b: 0   } },
                      { point: { x: 10, y: 0 }, color: { r: 0,   g: 0,   b: 128 } }]);

For reading from buffers you can use JavaScript typed arrays, but it won’t turn out to get a number in a binary form.

XMLHttpRequest Level 2 allows to send and get binary files.

13. How from one function to change the context variables of the other function?

1. It is possible to pass ф link to the object’s context of primer in smth
2. To pass a function derived in the context of primer in the function of smth

var primer = function (){
    var a, b, c, d, e = {};

    smth(function () {
        a = 1;
        b = 2;
        c = 3;
        d = 4;
    }, e);

    alert([a, b, c, d, e.pewpew]);
},
smth = function (callback, e) {
    callback();
    e.pewpew = "pewpew";
};

primer();

3. Previously (FireFox 3.6 -) it was possible to get to the context through __parent__, but in 4 versions this possibility was removed.

14. How to pass scope implementations of one function to the other?

In no way. Previously (FireFox 3.6 -) it was possible to get to the context through __parent__, but in 4 versions this possibility was removed.

15. How to get a global object correctly without its direct specification, without eval and at ‘use strict’?

In no way, if to drop one of the terms, or to execute only in a global scope, then it is possible to:

// 1: eval - on
(function(){
    "use strict";
    var globalObject = (0, eval)("this"); // Магия :)
    return globalObject;
}());

// 2: specify the name - on
(function(global){
    // ...
}(window));

// 3: "use strict" - off
(function(){
    return this;
}());

// 4: If to execute this code is in globals, then we will get a link to the global variable, but in other cases it will not work.
// It is the most optimal variant
"use strict";
(function(global){
    // global
})(this);

16. Is it possible in JavaScript to restart the event after the intercept?

Event doesn’t carry any loadings it is simple the descriptor of event. But it is possible obviously to pass link on event handler, in this way:

$('#smth').click(function onSmthClick(event){
    if (smth) {
        // to write the handler
        event.handlerFunction = onSmthClick;
        event.handlerContext = this;
        // pass to the left object
        // now otherObjectSetSomeEvent can use event.handlerFunction and call the handler
        otherObjectSetSomeEvent(event);
    } else {
        // do something else
    }
});

But this is not the successful decision, as you’ll have to take some pains further. It is better to redo the logic and divide the general handler in 2 parts:

$('#smth').click(function handler1(event) {
    if (smth) {
        // pass to the left object
        leftObjectSetSomeEvent(event, function handler2(e) {
            // do something with event or e
        });
    } else {
        // do something else
    }
});

function leftObjectSetSomeEvent(event, callback) {
    callback(event);
    // do something with event
}

17. Could you give me a tip where can I study JavaScript deeply? Books, tutorials?

Initial Level

These books will give you fundamental concepts about JavaScript and will help to begin the study of this language:

1. JavaScript: The Good Parts
2. Professional JavaScript for Web Developers (Wrox Programmer to Programmer)
3. ppk on JavaScript, 1/e
4. Beginning JavaScript with DOM Scripting and Ajax: From Novice to Professional (Beginning: from Novice to Professional)
5. Eloquent JavaScript (Online)

Middle level

If you know the bases, then it’s the right time to find those sources of knowledge, which will help you to deepen into JavaScript. Here are some useful books:

1. Professional JavaScript for Web Developers (Wrox Programmer to Programmer)
2. JavaScript: The Definitive Guide
3. Eloquent JavaScript (Online)
4. DOM Scripting: Web Design with JavaScript and the Document Object Model (A good resource for studying DOM).

Advanced level

You know JavaScript well, but wish to improve the code. These books will help you to improve the architecture of your application and code in general:

1. High Performance JavaScript (Build Faster Web Application Interfaces)
2. Object-Oriented JavaScript: Create scalable, reusable high-quality JavaScript applications and libraries
3. JavaScript Patterns
4. Pragmatic Guide to JavaScript
5. Pro JavaScript Techniques
6. Secrets of the JavaScript Ninja

18. How to make a single clicks handler on JS?

It is necessary to hang the click event handler on a lowermost object in DOM tree, all clicks on elements will “emerge» to it.

/ jQuery
$(window).bind('click', function (e) {
    console.log('Clicked on ', e.target);
});

// It is also possible to limit to some area, using jQuery delegate
$('#pewpew').delegate('*', 'click', function (e) {
    console.log('Clicked on ', e.target);
});

// It is possible to limit the aims too
$('#pewpew').delegate('.pewpew', 'click', function (e) {
    console.log('Clicked on element with .pewpew class name');
});

19. How to execute XHR without jQuery?

Not cross-browser function:

function xhr(m,u,c,x){with(new XMLHttpRequest)onreadystatechange=function(x){readyState^4||c(x.target)},open(m,u),send(с)}

Cross-browser, a bit longer:

function xhr(m,u,c,x){with(new(this.XMLHttpRequest||ActiveXObject)("Microsoft.XMLHTTP"))onreadystatechange=function(x){readyState^4||c(x)},open(m,u),send(с)}

The usage:

xhr('get', '//ya.ru/favicon.ico', function(xhr){console.dir(xhr)});

20. Reflow, repaint and methods of their minimization.

1. If a browser supports the function of requestAnimationFrame, then it is needed to use it instead of setInterval/setTimeout
Browsers can optimize animations which are going simultaneously, decreasing the number of reflow and repaint to one, that in its turn will result in the increase of animation exactness. For example animations on JavaScript are synchronized with CSS transitions or SVG SMIL. Plus to everything if animation is executed in tab, which is unvisible, browsers will not continue drawing again, that will result to the less use of CPU, GPU, memory and as a result will bring down the expense of battery in mobile devices.
2. Avoid plenty of float elements (reflow will diminish)
3. Modify DOM tree as rare as possible – write in memory, and then 1 time insert into DOM (reflow will diminish)
4. Change properties of object by a pack (reflow, redraw will diminish)

/ Instead
element.style.left="150px;";
//...
element.style.color="green";

// change all at once
element.setAttribute('style', 'color:green;left:150px');

5. Make the animations only with the absolutely positioned objects (reflow will diminish)
Before you change groups of elements hide them style.display = “none” (reflow will diminish)
6. Use delegation of events for diminishing their amount
7. Cache the links on DOM elements (a call of selector is the most expensive operation)
8. Use the rapid selectors functions querySelectorAll() firstElementChild
9. Remember that document.getElementsByTagName returns “living” collection of elements (if element added to DOM tree, then collection will get it automatically)

In many modern browsers these methods will not give so visible advantage (developers of browsers optimize everything for us).

You can also read:
Nicholas C. Zakas — OReilly High Performance JavaScript

21. Is it necessary to use childProcesses in node.js for every query in the highly-loaded projects?

You mustn’t use childProcesses for every query, because we get too much charges (as PHP with apache): allocation of superfluous memory, time of fork, time of initialising (jid compiling), loading on CPU etc. Node.js very well distributes loading and loads one processor core in “evented processing loop” is a basic stream of application. Ideal loading for Node.js – one fork on processor core, best of all to fork using Cluster. A cluster will play role of equalizer (masters), and forks – slaves. The use of childProcesses is justified for heavy queries.

You can also read: stackoverflow.com/questions/3491811/node-js-and-cpu-intensive-requests

22. The use of runInNewContext is in node.js.

What is runInNewContext? — node-js.ru/12-control-context-using-runinnewcontext
I see the only application of this technology – it is for starting stranger, potentially dangerous code (so does hosting of Node.js – nodester). If there is no such necessity, then I categorically against it – it is the quite not necessary wrapping, which can be not used if to choose correct architecture of application and use agreements for development. What is bad here: creation/deleting of context – allocation of memory as a result frequent GC (which blocks all application). I think there might be some problems with support of such code.

  • TheShock,
  • October 20, 2011

SHARE THIS POST

Pavel is 21 year old web developer from Ukraine. In his spare time he writes articles about the basics of LibCanvas, AtomJS and JavaScript

Subscribe for the hottest posts

Subscribe to our email newsletter for useful tips and freebies.

  • marclarr

    Very nice! Keep ’em coming!

  • marclarr

    Very nice! Keep ’em coming!