Skip to content

begin arabic translation #370

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions doc/ar/array/constructor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
## The `Array` Constructor

Since the `Array` constructor is ambiguous in how it deals with its parameters,
it is highly recommended to use the array literal - `[]` notation -
when creating new arrays.

[1, 2, 3]; // Result: [1, 2, 3]
new Array(1, 2, 3); // Result: [1, 2, 3]

[3]; // Result: [3]
new Array(3); // Result: []
new Array('3') // Result: ['3']

In cases when there is only one argument passed to the `Array` constructor
and when that argument is a `Number`, the constructor will return a new *sparse*
array with the `length` property set to the value of the argument. It should be
noted that **only** the `length` property of the new array will be set this way;
the actual indexes of the array will not be initialized.

var arr = new Array(3);
arr[1]; // undefined
1 in arr; // false, the index was not set

Being able to set the length of the array in advance is only useful in a few
cases, like repeating a string, in which it avoids the use of a loop.

new Array(count + 1).join(stringToRepeat);

### In Conclusion

Literals are preferred to the Array constructor. They are shorter, have a clearer syntax, and increase code
readability.

58 changes: 58 additions & 0 deletions doc/ar/array/general.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
## Array Iteration and Properties

Although arrays in JavaScript are objects, there are no good reasons to use
the [`for in`](#object.forinloop) loop. In fact, there
are a number of good reasons **against** the use of `for in` on arrays.

> **Note:** JavaScript arrays are **not** *associative arrays*. JavaScript only
> has [objects](#object.general) for mapping keys to values. And while associative
> arrays **preserve** order, objects **do not**.

Because the `for in` loop enumerates all the properties that are on the prototype
chain and because the only way to exclude those properties is to use
[`hasOwnProperty`](#object.hasownproperty), it is already up to **twenty times**
slower than a normal `for` loop.

### Iteration

In order to achieve the best performance when iterating over arrays, it is best
to use the classic `for` loop.

var list = [1, 2, 3, 4, 5, ...... 100000000];
for(var i = 0, l = list.length; i < l; i++) {
console.log(list[i]);
}

There is one extra catch in the above example, which is the caching of the
length of the array via `l = list.length`.

Although the `length` property is defined on the array itself, there is still an
overhead for doing the lookup on each iteration of the loop. And while recent
JavaScript engines **may** apply optimization in this case, there is no way of
telling whether the code will run on one of these newer engines or not.

In fact, leaving out the caching may result in the loop being only **half as
fast** as with the cached length.

### The `length` Property

While the *getter* of the `length` property simply returns the number of
elements that are contained in the array, the *setter* can be used to
**truncate** the array.

var arr = [1, 2, 3, 4, 5, 6];
arr.length = 3;
arr; // [1, 2, 3]

arr.length = 6;
arr.push(4);
arr; // [1, 2, 3, undefined, undefined, undefined, 4]

Assigning a smaller length truncates the array. Increasing it creates a sparse array.

### In Conclusion

For the best performance, it is recommended to always use the plain `for` loop
and cache the `length` property. The use of `for in` on an array is a sign of
badly written code that is prone to bugs and bad performance.

85 changes: 85 additions & 0 deletions doc/ar/core/delete.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
## The `delete` Operator

In short, it's *impossible* to delete global variables, functions and some other
stuff in JavaScript which have a `DontDelete` attribute set.

### Global code and Function code

When a variable or a function is defined in a global or a [function
scope](#function.scopes) it is a property of either the Activation object or
the Global object. Such properties have a set of attributes, one of which is
`DontDelete`. Variable and function declarations in global and function code
always create properties with `DontDelete`, and therefore cannot be deleted.

// global variable:
var a = 1; // DontDelete is set
delete a; // false
a; // 1

// normal function:
function f() {} // DontDelete is set
delete f; // false
typeof f; // "function"

// reassigning doesn't help:
f = 1;
delete f; // false
f; // 1

### Explicit properties

Explicitly set properties can be deleted normally.

// explicitly set property:
var obj = {x: 1};
obj.y = 2;
delete obj.x; // true
delete obj.y; // true
obj.x; // undefined
obj.y; // undefined

In the example above, `obj.x` and `obj.y` can be deleted because they have no
`DontDelete` attribute. That's why the example below works too.

// this works fine, except for IE:
var GLOBAL_OBJECT = this;
GLOBAL_OBJECT.a = 1;
a === GLOBAL_OBJECT.a; // true - just a global var
delete GLOBAL_OBJECT.a; // true
GLOBAL_OBJECT.a; // undefined

Here we use a trick to delete `a`. [`this`](#function.this) here refers
to the Global object and we explicitly declare variable `a` as its property
which allows us to delete it.

IE (at least 6-8) has some bugs, so the code above doesn't work.

### Function arguments and built-ins

Functions' normal arguments, [`arguments` objects](#function.arguments)
and built-in properties also have `DontDelete` set.

// function arguments and properties:
(function (x) {

delete arguments; // false
typeof arguments; // "object"

delete x; // false
x; // 1

function f(){}
delete f.length; // false
typeof f.length; // "number"

})(1);

### Host objects

The behaviour of `delete` operator can be unpredictable for hosted objects. Due
to the specification, host objects are allowed to implement any kind of behavior.

### In conclusion

The `delete` operator often has unexpected behaviour and can only be safely
used to delete explicitly set properties on normal objects.
47 changes: 47 additions & 0 deletions doc/ar/core/eval.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
## Why Not to Use `eval`

The `eval` function will execute a string of JavaScript code in the local scope.

var number = 1;
function test() {
var number = 2;
eval('number = 3');
return number;
}
test(); // 3
number; // 1

However, `eval` only executes in the local scope when it is being called
directly *and* when the name of the called function is actually `eval`.

var number = 1;
function test() {
var number = 2;
var copyOfEval = eval;
copyOfEval('number = 3');
return number;
}
test(); // 2
number; // 3

The use of `eval` should be avoided. 99.9% of its "uses" can be achieved
**without** it.

### `eval` in Disguise

The [timeout functions](#other.timeouts) `setTimeout` and `setInterval` can both
take a string as their first argument. This string will **always** get executed
in the global scope since `eval` is not being called directly in that case.

### Security Issues

`eval` also is a security problem, because it executes **any** code given to it.
It should **never** be used with strings of unknown or untrusted origins.

### In Conclusion

`eval` should never be used. Any code that makes use of it should be questioned
in its workings, performance and security. If something requires `eval` in
order to work, it should **not** be used in the first place. A *better design*
should be used, that does not require the use of `eval`.

114 changes: 114 additions & 0 deletions doc/ar/core/semicolon.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
## Automatic Semicolon Insertion

Although JavaScript has C style syntax, it does **not** enforce the use of
semicolons in the source code, so it is possible to omit them.

JavaScript is not a semicolon-less language. In fact, it needs the
semicolons in order to understand the source code. Therefore, the JavaScript
parser **automatically** inserts them whenever it encounters a parse
error due to a missing semicolon.

var foo = function() {
} // parse error, semicolon expected
test()

Insertion happens, and the parser tries again.

var foo = function() {
}; // no error, parser continues
test()

The automatic insertion of semicolon is considered to be one of **biggest**
design flaws in the language because it *can* change the behavior of code.

### How it Works

The code below has no semicolons in it, so it is up to the parser to decide where
to insert them.

(function(window, undefined) {
function test(options) {
log('testing!')

(options.list || []).forEach(function(i) {

})

options.value.test(
'long string to pass here',
'and another long string to pass'
)

return
{
foo: function() {}
}
}
window.test = test

})(window)

(function(window) {
window.someLibrary = {}

})(window)

Below is the result of the parser's "guessing" game.

(function(window, undefined) {
function test(options) {

// Not inserted, lines got merged
log('testing!')(options.list || []).forEach(function(i) {

}); // <- inserted

options.value.test(
'long string to pass here',
'and another long string to pass'
); // <- inserted

return; // <- inserted, breaks the return statement
{ // treated as a block

// a label and a single expression statement
foo: function() {}
}; // <- inserted
}
window.test = test; // <- inserted

// The lines got merged again
})(window)(function(window) {
window.someLibrary = {}; // <- inserted

})(window); //<- inserted

> **Note:** The JavaScript parser does not "correctly" handle return statements
> that are followed by a new line. While this is not necessarily the fault of
> the automatic semicolon insertion, it can still be an unwanted side-effect.

The parser drastically changed the behavior of the code above. In certain cases,
it does the **wrong thing**.

### Leading Parenthesis

In case of a leading parenthesis, the parser will **not** insert a semicolon.

log('testing!')
(options.list || []).forEach(function(i) {})

This code gets transformed into one line.

log('testing!')(options.list || []).forEach(function(i) {})

Chances are **very** high that `log` does **not** return a function; therefore,
the above will yield a `TypeError` stating that `undefined is not a function`.

### In Conclusion

It is highly recommended to **never** omit semicolons. It is also recommended
that braces be kept on the same line as their corresponding statements and to
never omit them for single-line `if` / `else` statements. These measures will
not only improve the consistency of the code, but they will also prevent the
JavaScript parser from changing code behavior.

Loading