Quantcast
Channel: Splashnology.com » faq
Viewing all articles
Browse latest Browse all 6

JavaScript F.A.Q: Part 2

$
0
0

Previously I’ve posted the article JavaScript F.A.Q: Part 1, which contains very useful information on JavaScript, and now I would like to continue with some more new and interesting questions and answers to them.

In this part we are going to discuss such questions:

1. Why eval = evil?
2. What should I use instead eval?
3. How to play a sound using JS without flash? What formats are supported?
4. How much does the use of global variables slow the scripts?
5. How to forbid the selection of text on JS?
6. (function(){})(); What is this construction used for?
7. How to reset the events and renew the state of element?
8. How correctly to pass js -commands with parameters in ajax applications?
9. What for to pass the window in jQuery if it’s as it is global and why undefined?
10. How to know what side does the user scrolls the mouse wheel?
11. Does the element have a focus event, if not, than is it possible to realize it?
12. How to prevent the addition of new properties to an object (freez)?
13. Is it possible to do a custom realization of DomElement so that it was used at an analysis for the subset of tags?
14. What client MVC -framework can you advise?
15. Passing the limitations on Referer.
16. GOTO in Javascript.
17. What are the practices of data transfer from a server into the code, which is carried out from .js?
18. Is it possible to emulate the behavior of DOMInputElement by means of simple DOMElements(div)?
19. Problem of private and public methods.
20. How to define if the user tries to download a directory when loading files with the use of File and FormData?
21. Are there any analogues in JavaScript to declarations/to the lemmatas (terms from Python/Java accordingly)?

1. Why eval = evil?

1. Eval violates the usual logic of the program, generating a code.
2. It executes a code in a current context and can change it, it is a potential place for attacks. A context can be substituted, executing such trick:

(1,eval)(code);

Here happens the following: eval is the same function which depends on the call method. In this case we change a context on global.

3. It is difficult to debug the code descendant by the eval.
4. Eval is being executed very long.

Useful information for reading:
Global eval. What are the options?

A lot of information on Stackoverflow:
stackoverflow.com/questions/197769/when-is-javascripts-eval-not-evil
stackoverflow.com/questions/646597/eval-is-evil-so-what-should-i-use-instead
stackoverflow.com/questions/86513/why-is-using-javascript-eval-function-a-bad-idea

2. What should I use instead eval?

The best replacement of eval is a good code structure, which does not suppose the use of eval. However, it’s not always easy to give up the eval (JSON parsing, Resig’s Micro-Templating ).
Good replacement for eval is a Function constructor. But it the same eval, which is executed in a global context.

new Function('return ' + code)();
// It's practically the equivalent
(1,eval)(code);

3.How to play a sound using JS without flash? What formats are supported?

The simplest decision:

<audio src="http://developer.mozilla.org/@api/deki/files/2926/=AudioTest_(1).ogg" autoplay>
  Your browser does not support the <code>audio</code> element.
</audio>

But it’s not the limit of HTML5 audio. Formats: Ogg Vorbis, WAV PCM, MP3, AAC, Speex (depends on a concrete browser). About formats: Audio format support

Useful information for reading:
WHATWG — The audio element
MDN — HTML audio
Example: Creating a simple synth
Example: Displaying a graphic with audio samples
Example: Visualizing an audio spectrum
Example: Creating a Web based tone generator

4. How much does the use of global variables slow the scripts?

It depends on a concrete browser. In modern browsers this moment is optimized and there is no difference. In old ones the access to the global variable can be two times slower.

Here is the test: jsperf.com/global-vs-local-valiable-access
Please, take into account the circumstance that this is a test, every operation is processed to one million times in a second. Even if the increase for a test is 30%, then an actual increase for the first operation will be scanty (microseconds).

5. How to forbid the selection of text on JS?

There are few variants.

1. To execute preventDefault for the onselectstart and onmousedown events

var element = document.getElementById('content');
element.onselectstart = function () { return false; }
element.onmousedown = function () { return false; }

2. To add the attribute- unselectable

$(document.body).attr('unselectable', 'on')

3. To add user – select: none style

.g-unselectable {
  -moz-user-select: none;
  -khtml-user-select: none;
  -webkit-user-select: none;
  user-select: none;
}

There are also some reckless decisions of this problem:

4. To clean Range, TextRange, Selection on a timer
5. To render the text on canvas
6. To use disabled textarea

<textarea disabled="disabled" style="border:none;color:#000;background:#fff; font-family:Arial;">
    How to forbid the selection of text on JS?
</textarea>

Here is a micro plugin for jQuery using methods 1-3

$.fn.disableSelection = function() {
    function preventDefault () {
        return false;
    }
    $(this).attr('unselectable', 'on')
           .css('-moz-user-select', 'none')
           .css('-khtml-user-select', 'none')
           .css('-o-user-select', 'none')
           .css('-msie-user-select', 'none')
           .css('-webkit-user-select', 'none')
           .css('user-select', 'none')
           .mousedown(preventDefault);
           .each(function() { 
               this.onselectstart = preventDefault;
           });
};

This plugin will not save from Ctrl+A Ctrl+C in those browsers which do not support user – select or unselectable. Remember: to forbid a selection is evil.

6. (function(){})(); What is this construction used for?

It is called Immediately – Invoked Function Expression (IIFE)- a Function-expression, which was called at once after creation.

Here are a few methods to create IIFE

(function(){ /* code */ })(); // Simple IIFE
(function(){ /* code */ }()); // 

// To put a function in the state of "value"

true && function(){ /* code */ }();
0,function(){ /* code */ }();

// It is possible to create, using the operator as prefix

!function(){ /* code */ }(); // Facebook style
~function(){ /* code */ }();
-function(){ /* code */ }();
+function(){ /* code */ }();

// Using new

new function(){ /* code */ }
new function(){ /* code */ }() // If arguments are needed, then we put brackets

Where it is used:

1. If you need, that some variables didn’t get in external surroundings (similarity of let)

var APPLICATION_ID = function(){
    var keys = {
       'pew.ru': 15486,
       'pew.pew.ru': 15487,
       'pew.pew.pew.ru': 1548
    };
    
    return keys[window.location.host];
}();

2. Creation of the local closure is a basis for the modules, objects, memorizing the state

var Module = (function(){
    function privateMethod () {
    
    };
    
    return {
       publicMethod: function () {
           return privateMethod();
       }
    };
}());

Useful information for reading:
Immediately-Invoked Function Expression (IIFE)
ECMA-262-3 in detail. Chapter 5. Functions
Functions and function scope
Named function expressions
JavaScript Module Pattern: In-Depth
Closures explained with JavaScript

7. How to reset the events and renew the state of element?

We have some DOM -object with initially set “А” parameters with the help of HTML and CSS. In the process of work we dynamically change the parameters on “В”. Is there a simple method to “reset” the primary “А” state of an object ? Like with events. How to do a backup on the primary state?

It’s impossible to backup the state of an object. DOM doesn’t keep the state because elements can be received in different ways: directly from the html code and generated with JavaScript.
Everything is a lot simpler with the events. There is a good method in DOM it is called cloneNode. We simply clone an element with all its content (it will not have events) and substitute an old element with the new one.

// For the text
$('input').click(function(){alert('')});

function resetEvents(element) {
    var newElement = element.cloneNode(true);
    element.parentNode.insertBefore(newElement, element); // fixed by @spmbt
    element.parentNode.removeChild(element);

    return newElement;
}

resetEvents($('input')[0]);

// Nothing will happen with the click on input

8. How correctly to pass js -commands with parameters in ajax applications?

How correctly to pass js -commands with parameters in ajax applications without a fuss with quotation marks? It concerns the data transfer in ajax -system. At the transmission of difficult commands with a few nesting levels of parameters (for example, “setTimeout(‘alert(“Boom”!!!);’, 200);” ), there are problems with the use of quotation marks. How to settle them or are there some general rules of their registration?

To send a code from a server to the client is badly. It’s like a problem with eval. It is correctly, quickly and safely to pass the data which a browser will process, but not a code.
It is possible to use RPC. Very transparent RPC can be got, using NowJS. NowJS – framework allowing to execute functions on a server as if you execute them on a client.
Here is an example from a site:
On a server: Node.JS server

var nowjs = require("now");

// he we create http server

var everyone = nowjs.initialize(httpServer);

everyone.now.getServerInfo = function(callback){
  db.doQuery(callback);
}

On the client

now.getServerInfo(function(data){
  // Data of query
});

Simply, transparently and beautifully!

Useful information for reading:
Getting Started with NowJS

9. What for to pass the window in jQuery if it’s as it is global and why undefined?

jQuery creates closure and brings window and undefined to it.

1. undefined is passed for diminishing the code’s volume and bypassing the problem with rewriting of undefined. At the compression undefined turns into a single-letter variable.
2. window is passed for diminishing the code’s volume . jQuery applies a good policy, dissociating the methods of window from its own, using window.setInterval() and other. At the compression the window will turn into a single-letter variable, in code there will be c.setInterval()

10. How to know what side does the user scrolls the mouse wheel?

There are 2 events that react on the mouse scroll: ‘DOMMouseScroll’ (Firefox) and ‘mousewheel’ (other)
I think that it’s clear to all how to hang an event, let’s take a look on its handler

function wheel(event){
    var delta = 0;
    if (!event) event = window.event; // event IE.
    // We will set the cross browser delta
    if (event.wheelDelta) { 
        // IE, Opera, safari, chrome - multiplicity of delta equals to 120
        delta = event.wheelDelta/120;
    } else if (event.detail) { 
        // Mozilla, multiplicity of delta equals to 3
        delta = -event.detail/3;
    }
    if (delta) {
        // We will cancel the current event - an event by default (window scrolling).
        if (event.preventDefault) {
            event.preventDefault();
        }
        event.returnValue = false; // for IE
        
        // if delta is more than 0, then a wheel is scrolled upwards, otherwise downwards
        var dir = delta > 0 ? 'Up' : 'Down',
    }
}

For jQuery there are also Mouse Wheel Plugin jQuery Mouse Wheel Plugin Demos

Not all elements can generate a scroll-event. It depends on a concrete browser. More details: scroll and mousewheel

11. Does the element have a focus event, if not, then is it possible to realize it?

Focus is a logical event, showing that an object is being selected now.

If to read the standard there you’ll see that the focus and blur events are only in form elements: LABEL, INPUT, SELECT, TEXTAREA, and BUTTON. According to the standard, no other elements can generate this event. For all other elements there are other events: DOMFocusIn and DOMFocusOut. IE, as usual have its own events: focusin and focusout.

Firefox is not exactly submits to the standard, some of its elements, except a form can throw out focus and blur.
Look at the test of focus, blur, focusin, focusout, DOMFocusIn, DOMFocusOut events: www.quirksmode.org/dom/events/tests/blurfocus.html
If to listen all three events of an element, then we can define whether any of the elements got the focus or no.

Useful information for reading:
blur and focus

12. How to prevent the addition of new properties to an object (freez)?

There was no possibility to freeze an object in ECMAScript 3 (standard, which is supported by all JavaScript engines), but a few functions appeared in ECMAScript 5 at once, limiting the change of an object.
Object.preventExtensions- the weakest limitation. An object cannot get additional parameters.
Object.seal – preventExtensions + any parameters cannot be deleted
Object.freeze – preventExtensions + seal + parameters become only on reading
These new methods are supported far not in all browsers.

Useful information for reading:
New in JavaScript 1.8.5
Object.preventExtensions/seal/freeze Function (JavaScript)
ECMAScript 5 compatibility table

13. Is it possible to do a custom realization of DomElement so that it was used at an analysis for the subset of tags?

It’s impossible to do this straight. DOM is separated from JavaScript and that is why there are some limitations.

1. There are no constructors of concrete elements – there is only a factory of elements – document.createElement(”) and some methods of line for elements creation – String.prototype.anchor etc. HTMLElement and HTMLDivElement are not constructors.
2. Even if we emulate the constructor, then DOM will “clean” an object after an insertion in a tree.
Example

// We create our emulated constructor
var HTMLZzzElement = function () {
   var self = document.createElement('zzz');
   self.__proto__ = HTMLZzzElement.prototype;
   return self;
};

// We inherit from HTMLUnknownElement
function F(){}
F.prototype = HTMLUnknownElement.prototype;

HTMLZzzElement.prototype = new F();
HTMLZzzElement.prototype.constructor = HTMLZzzElement;
HTMLZzzElement.prototype.pewpewpew = function () {};

// create
var zzz = new HTMLZzzElement();

// Yes, it works
zzz.innerHTML = 'Yohoho!';

// Check
console.log(zzz instanceof HTMLZzzElement); // true
console.log(zzz instanceof HTMLUnknownElement); // true
console.log(zzz instanceof HTMLElement); // true
console.log(typeof zzz.pewpewpew); // function
//Everything is fine

// put into the DOM
document.body.appendChild(zzz);

// Get it back
zzz = document.querySelector('zzz')

// The object is cleaned
console.log(zzz instanceof HTMLZzzElement);  // false
console.log(zzz instanceof HTMLUnknownElement); // true
console.log(zzz instanceof HTMLElement); // true
console.log(typeof zzz.pewpewpew); // undefined

However, we can write in addition to the prototype “class” of HTML some element methods and properties and then to use them in the future :

HTMLUnknownElement.prototype.pewpewpew = function () {};

console.log(typeof zzz.pewpewpew); // function

The chain of “classes” inheritance is the following
Node -> Element -> HTMLElement -> HTMLDivElement/HTMLMetaElement …
You can finish writing a method to the prototype of element, however remember that to patch stranger objects is badly!

This method will work only in modern browsers. In IE88 and below, it seems that html elements are being taken from air, therefore their prototypes cannot be rewritten at a low level:

>>document.createElement('div').constructor
//undefined -- даже не null...


>>document.createElement('div') instanceof Object
//false -- amusing, isn't it? although magic with toString proves the contrary
>>Object.prototype.toString.call(document.createElement('div'));
//"[object Object]"

14. What client MVC -framework can you advise?

There are a lot of frameworks:

JavaScriptMVC
Backbone.js
SproutCore
TrimJunction

Check them all and choose the one that suits you better. I worked closely only with Backbone.js.

Useful information for reading:
MVC in JavaScript

15. Passing the limitations on Referer.

There is a picture on blabla.ru server, a server does not give it if Referer passed it from other server (pewpew.com). How to get the content of the picture and show it to the user?

There is now way to do it straight from the browser. It is possible to do server proxy, which will change the Referer.

16. GOTO in Javascript.

How to repeat goto behavior in JavaScript? The question is about the generated code and the renewal of blocks and cycles.

There are marks in JavaScript, but not goto (there is only a reserved word). A mark looks similarly as well as in all other languages, but they work differently. A mark distinguishes a block. A block can contain the other marked blocks. You can get the mark using break and continue, which are inside of this bloфФу

Example:

loop1: for (var a = 0; a < 10; a++) {
   if (a == 4) {
       break loop1; // Only 4 tries 
   }
   alert('a = ' + a);
   loop2: for (var b = 0; b < 10; ++b) {
      if (b == 3) {
         continue loop2; // skip 3
      }
      if (b == 6) {
         continue loop1; // We continue to execute loop1 'finished' will not be shown
      }
      alert('b = ' + b);
   }
   alert('finished')
}

block1: {
    alert('hello'); // displays 'hello'
    break block1;
    alert('world'); // will never be displayed
}
goto block1; // Parse error - goto no

17. What are the practices of data transfer from a server into the code, which is carried out from .js?

There are a lot of different ways of data transfer: XHR, SSE, WebSockets, JSONP.

It’s up to you what way and format to choose it depends greatly on the application requirements. For example, if it is a chat, then it’s better to use SSE or WebSockets (time of report delivery is critical). And if this chat must work cross-domain and in IE6, then it will be necessary to add some magic with iframe or flash.

18. Is it possible to emulate the behavior of DOMInputElement by means of simple DOMElements(div)?

It is impossible at the low level. I’ve already explained it in the 13th question. It is possible to do a wrapping which will emulate the Input, in basis of which there will be DOMDivElement.
I outlined the simple emulator jsfiddle.net/azproduction/Kz4d9/ – the very crooked input turned out (is not able to submit, and to lose the focus etc.). The same problem can be decided more elegantly, by adding only 1 attribute: contenteditable, which is supported only by desktop browsers – the same input turned out, but much simpler and better jsfiddle.net/azproduction/ZTqRe/

19. Problem of private and public methods.

If there is a desire to use private variables and methods of objects, in JavaScript there is a problem of access to the private methods from public one. And the privileged methods defined in a constructor, if I get it right, are duplicated for every copy, which is not that good from the point of view of the productivity. What do you think about such approach?
It’s a quite good approach. At least much better than to declare all methods in a constructor.

// our constructor
function Person(name, age){
    this.name = name;
    this.age  = age;
};

// prototype assignment
Person.prototype = new function(){

    // we have a scope for private stuff
    // created once and not for every instance
    function toString(){
        return this.name + " is " + this.age;
    };

    // create the prototype and return them
    this.constructor = Person;

    this._protectedMethod = function (){
        // act here
    };

    this.publicMethod = function() {
        this._protectedMethod();
    };

    // "magic" toString method
    this.toString = function(){
         // call private toString method
         return toString.call(this);
    }
};

Module approach:

var Module = (function (window) {
    function privateFunction() {
        console.log('pass');
    };

    var privateClass = function () {};

    var publicClass = function () {};
    publicClass.prototype.publicMethod = function () {
        privateFunction(); // ...
    };
    
    return { // Export
        publicClass: publicClass
    };
}(this));

// Use
(new Module.publicClass()).publicMethod();

20. How to define if the user tries to download a directory when loading files with the use of File and FormData?

How to define if the user tries to download a directory when loading files with the use of File and FormData? Unfortunately, the File.type property does not help (for some types, as well as for directories, it is null string), property of size – too (ff and safari show differently).

Regarding File.type is said, that it is a mime -type and if it is not defined, then it becomes a null string. mime -type comes from expansion of file/ folder. If we will shove the real file with the name of “pewpew”, then mime will be “”, and if the directory with the name of “pewpew.html”, then mime will be “text/html”. It does not suit us. Folder size is always 0, but there also can be files sized 0 byte. For 100% confidence it does not suit us.

In the standard of http://www.w3.org/TR/FileAPI/ is not said about the directories separately, but it is marked there, that browsers can output a SECURITY_ERR if an user tries to work with not correct files (protected, not accessible for reading etc.) We’ll take it into account.

In basis I followed an example of Drag and Drop

We will use FileReader for determination of resource type. If to read a folder as file in Firefox, then the method of reader.readAsDataURL throws out an exception. In Chrome this exception is not thrown out, but the event of onerror is caused at reader. We will cross it and will get a function for determination whether it is a file it or not.

function isReadableFile(file, callback) {
    var reader = new FileReader();
    reader.onload = function () {
        callback && callback(true);
        callback = null;
    }
            
    reader.onerror = function () {
        callback && callback(false);
        callback = null; 
    }
        
    try {
        reader.readAsDataURL(file); 
    } catch (e) {
        callback && callback(false);
        callback = null; 
    }
}

For securing, in a function I delete the callback, for it not to be recalled (behavior of FileReader can change in the future).
Example of the usage jsfiddle.net/azproduction/3sV23/8/

It was possible to do with measuring file. If 0, that to consider that it is not a file (because it is strange to load a file measuring 0 byte).

21. Are there any analogues in JavaScript to declarations/to the lemmatas (terms from Python/Java accordingly)?

There are no direct analogues.


Viewing all articles
Browse latest Browse all 6

Latest Images

Trending Articles





Latest Images