From 5fc07deca390787fd398f2f99cfeeda165e8bfed Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Mon, 21 Mar 2011 14:56:02 +0200 Subject: [PATCH 01/41] modified gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index b918c19b..ea5e3ac2 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,6 @@ /html /site/de /site/ru +/site/en *.md~ *.src.md From 585324fee45c2687d25aa6aa808f43bc3a52739d Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Mon, 21 Mar 2011 15:21:38 +0200 Subject: [PATCH 02/41] fixed json notation error --- doc/ru/object/general.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/ru/object/general.md b/doc/ru/object/general.md index 804bf1e3..42ca0046 100644 --- a/doc/ru/object/general.md +++ b/doc/ru/object/general.md @@ -84,14 +84,14 @@ // валидный JavaScript и валидный JSON { - 'foo': 'oof', - 'bar': 'rab' + "foo": "oof", + "bar": "rab" } // валидный JavaScript и НЕ валидный JSON { - foo: 'oof', - bar: 'rab' + foo: "oof", + bar: "rab" } [1]: http://ru.wikipedia.org/wiki/%D0%A5%D0%B5%D1%88-%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D0%B0 From 151e9698ccd2e7c716722ce6bc869c542e29b2c8 Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Mon, 21 Mar 2011 16:49:12 +0200 Subject: [PATCH 03/41] small fix --- doc/ru/types/casting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ru/types/casting.md b/doc/ru/types/casting.md index bc350cfc..287a9701 100644 --- a/doc/ru/types/casting.md +++ b/doc/ru/types/casting.md @@ -10,7 +10,7 @@ JavaScript *слабо типизированный* язык, поэтому * 10 == '+10 '; // Ещё чуток строко-безумия 10 == '010'; // и ещё isNaN(null) == false; // null преобразуется в 0, - // который конечно же NaN + // который, конечно же, не NaN // Эти равенства — ложь 10 == 010; From eabb909e05f5d34a20f5ccb284e547cf2a03a355 Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Sun, 27 Mar 2011 12:02:23 +0300 Subject: [PATCH 04/41] injected new changes in russian translation --- doc/ru/index.json | 1 + doc/ru/intro/authors.md | 3 +- doc/ru/intro/hosting.md | 8 + site/en/index.html | 1859 --------------------------------------- 4 files changed, 11 insertions(+), 1860 deletions(-) create mode 100644 doc/ru/intro/hosting.md delete mode 100644 site/en/index.html diff --git a/doc/ru/index.json b/doc/ru/index.json index 9e27bf03..e1789747 100644 --- a/doc/ru/index.json +++ b/doc/ru/index.json @@ -9,6 +9,7 @@ "articles": [ "authors", "contributors", + "hosting", "translators", "license" ] diff --git a/doc/ru/intro/authors.md b/doc/ru/intro/authors.md index 3c11a24d..6c8a1b17 100644 --- a/doc/ru/intro/authors.md +++ b/doc/ru/intro/authors.md @@ -1,7 +1,8 @@ ## Авторы -Это руководство является результатом работы двух заядлых пользователей Stack Overflow: [Иво Ветцель /Ivo Wetzel/][1] (автора текста) и [Чжан И Цзян /Zhang Yi Jiang/][2] (дизайнера). +Это руководство является результатом работы двух заядлых пользователей [Stack Overflow][3]: [Иво Ветцель /Ivo Wetzel/][1] (автора текста) и [Чжан И Цзян /Zhang Yi Jiang/][2] (дизайнера). [1]: http://stackoverflow.com/users/170224/ivo-wetzel [2]: http://stackoverflow.com/users/313758/yi-jiang +[3]: http://stackoverflow.com/ diff --git a/doc/ru/intro/hosting.md b/doc/ru/intro/hosting.md new file mode 100644 index 00000000..7ae6e888 --- /dev/null +++ b/doc/ru/intro/hosting.md @@ -0,0 +1,8 @@ +## Хостинг + +JavaScript Garden хостится на [GitHub][3], однако [Cramer Development][1] поддерживают наше зеркало на [JavaScriptGarden.info][2]. + +[1]: http://cramerdev.com/ +[2]: http://javascriptgarden.info/ +[3]: https://github.com/BonsaiDen/JavaScript-Garden + diff --git a/site/en/index.html b/site/en/index.html deleted file mode 100644 index 8a91e498..00000000 --- a/site/en/index.html +++ /dev/null @@ -1,1859 +0,0 @@ -JavaScript Garden -

Intro

JavaScript Garden is a growing collection of documentation about the most -quirky parts of the JavaScript programming language. It gives advice to -avoid common mistakes, subtle bugs, as well as performance issues and bad -practices that non-expert JavaScript programmers may encounter on their -endeavours into the depths of the language.

- -

JavaScript Garden does not aim to teach you JavaScript. Former knowledge -of the language is strongly recommended in order to understand the topics covered -in this guide. In order to learn the basics of the language, please head over to -the excellent guide on the Mozilla Developer Network.

The Authors

This guide is the work of two lovely Stack Overflow users, Ivo Wetzel -(Writing) and Zhang Yi Jiang (Design).

License

JavaScript Garden is published under the MIT license and hosted on -GitHub. If you find errors or typos please file an issue or a pull -request on the repository. You can also find us in the JavaScript room on -Stack Overflow chat.

Objects

Object Usage and Properties

Everything in JavaScript acts like an object, with the only two exceptions being -null and undefined.

- -
false.toString() // 'false'
-[1, 2, 3].toString(); // '1,2,3'
-
-function Foo(){}
-Foo.bar = 1;
-Foo.bar; // 1
-
- -

A common misconception is that number literals cannot be used as -objects. That is because a flaw in JavaScript's parser tries to parse the dot -notation on a number as a floating point literal.

- -
2.toString(); // raises SyntaxError
-
- -

There are a couple of workarounds which can be used in order make number -literals act as objects too.

- -
2..toString(); // the second point is correctly recognized
-2 .toString(); // note the space left to the dot
-(2).toString(); // 2 is evaluated first
-
- -

Objects as a data type

- -

Objects in JavaScript can also be used as a Hashmap, they mainly consist -of named properties mapping to values.

- -

Using a object literal - {} notation - it is possible to create a -plain object. This new object inherits from Object.prototype and -has no own properties defined on it.

- -
var foo = {}; // a new empty object
-
-// a new object with a property called 'test' with value 12
-var bar = {test: 12}; 
-
- -

Accessing properties

- -

The properties of an object can be accessed in two ways, via either the dot -notation, or the square bracket notation.

- -
var foo = {name: 'Kitten'}
-foo.name; // kitten
-foo['name']; // kitten
-
-var get = 'name';
-foo[get]; // kitten
-
-foo.1234; // SyntaxError
-foo['1234']; // works
-
- -

Both notations are identical in their workings, with the only difference being that -the square bracket notation allows for dynamic setting of properties, as well as -the use of property names that would otherwise lead to a syntax error.

- -

Deleting properties

- -

The only way to actually remove a property from an object is to use the delete -operator; setting the property to undefined or null only remove the -value associated with the property, but not the key.

- -
var obj = {
-    bar: 1,
-    foo: 2,
-    baz: 3
-};
-obj.bar = undefined;
-obj.foo = null;
-delete obj.baz;
-
-for(var i in obj) {
-    if (obj.hasOwnProperty(i)) {
-        console.log(i, '' + obj[i]);
-    }
-}
-
- -

The above outputs both bar undefined and foo null - only baz was -removed and is therefore missing from the output.

- -

Notation of keys

- -
var test = {
-    'case': 'I am a keyword so I must be notated as a string',
-    delete: 'I am a keyword too so me' // raises SyntaxError
-};
-
- -

Object properties can be both notated as plain characters and as strings. Due to -another mis-design in JavaScript's parser, the above will throw -a SyntaxError prior to ECMAScript 5.

- -

This error arises from the fact that delete is a keyword; therefore, it must be -notated as a string literal to ensure that it will be correctly interpreted by -older JavaScript engines.

The Prototype

JavaScript does not feature a classical inheritance model, instead it uses a -prototypal one.

- -

While this is often considered to be one of JavaScript's weaknesses, the -prototypal inheritance model is in fact more powerful than the classic model. -It is for example fairly trivial to build a classic model on top of it, while the -other way around is a far more difficult task.

- -

Due to the fact that JavaScript is basically the only widely used language that -features prototypal inheritance, it takes some time to adjust to the -differences between the two models.

- -

The first major difference is that inheritance in JavaScript is done by using so -called prototype chains.

- - - -
function Foo() {
-    this.value = 42;
-}
-Foo.prototype = {
-    method: function() {}
-};
-
-function Bar() {}
-
-// Set Bar's prototype to a new instance of Foo
-Bar.prototype = new Foo();
-Bar.prototype.foo = 'Hello World';
-
-// Make sure to list Bar as the actual constructor
-Bar.prototype.constructor = Bar;
-
-var test = new Bar() // create a new bar instance
-
-// The resulting prototype chain
-test [instance of Bar]
-    Bar.prototype [instance of Foo] 
-        { foo: 'Hello World' }
-        Foo.prototype
-            { method: ... }
-            Object.prototype
-                { toString: ... /* etc. */ }
-
- -

In the above, the object test will inherit from both Bar.prototype and -Foo.prototype; hence, it will have access to the function method that was -defined on Foo. It will also have access to the property value of the -one Foo instance that is its prototype. It is important to note that new -Bar() does not create a new Foo instance, but reuses the one assigned to -its prototype; thus, all Bar instances will share the same value property.

- - - -

Property lookup

- -

When accessing the properties of an object, JavaScript will traverse the -prototype chain upwards until it finds a property with the requested name.

- -

When it reaches the top of the chain - namely Object.prototype - and still -hasn't found the specified property, it will return the value -undefined instead.

- -

The prototype property

- -

While the prototype property is used by the language to build the prototype -chains, it is still possible to assign any given value to it. Although -primitives will simply get ignored when assigned as a prototype.

- -
function Foo() {}
-Foo.prototype = 1; // no effect
-
- -

Assigning objects, as shown in the example above, will work, and allows for dynamic -creation of prototype chains.

- -

Performance

- -

The lookup time for properties that are high up on the prototype chain can have a -negative impact on performance critical sections of code. Additionally, trying to -access non-existent properties will always traverse the full prototype chain.

- -

Also, when iterating over the properties of an object -every property that is on the prototype chain will get enumerated.

- -

Extension of native prototypes

- -

One mis-feature that is often used is to extend Object.prototype or one of the -other built in prototypes.

- -

This technique is called monkey patching and breaks encapsulation. While -used by widely spread frameworks such as Prototype, there is still no good -reason for cluttering built-in types with additional non-standard functionality.

- -

The only good reason for extending a built-in prototype is to backport -the features of newer JavaScript engines; for example, -Array.forEach.

- -

In conclusion

- -

It is a must to understand the prototypal inheritance model completely -before writing complex code which makes use of it. Also, watch the length of -the prototype chains and break them up if necessary to avoid possible -performance issues. Further, the native prototypes should never be extended -unless it is for the sake of compatibility with newer JavaScript features.

hasOwnProperty

In order to check whether a object has a property defined on itself and not -somewhere on its prototype chain, it is necessary to use the -hasOwnProperty method which all objects inherit from Object.prototype.

- - - -

hasOwnProperty is the only thing in JavaScript which deals with properties and -does not traverse the prototype chain.

- -
// Poisoning Object.prototype
-Object.prototype.bar = 1; 
-var foo = {goo: undefined};
-
-foo.bar; // 1
-'bar' in foo; // true
-
-foo.hasOwnProperty('bar'); // false
-foo.hasOwnProperty('goo'); // true
-
- -

Only hasOwnProperty will give the correct and expected result, this is -essential when iterating over the properties of any object. There is no other -way to exclude properties that are not defined on the object itself, but -somewhere on its prototype chain.

- -

hasOwnProperty as a property

- -

JavaScript does not protect the property name hasOwnProperty; thus, if the -possibility exists that an object might have a property with this name, it is -necessary to use an external hasOwnProperty in order to get correct results.

- -
var foo = {
-    hasOwnProperty: function() {
-        return false;
-    },
-    bar: 'Here be dragons'
-};
-
-foo.hasOwnProperty('bar'); // always returns false
-
-// Use another hasOwnProperty and call it with 'this' set to foo
-{}.hasOwnProperty.call(foo, 'bar'); // true
-
- -

In conclusion

- -

When checking for the existence of a property on a object, hasOwnProperty is -the only method of doing so. It is also recommended to make hasOwnProperty -part of every for in loop, this will avoid errors from -extended native prototypes.

The for in Loop

Just like the in operator, the for in loop also traverses the prototype -chain when iterating over the properties of an object.

- - - -
// Poisoning Object.prototype
-Object.prototype.bar = 1;
-
-var foo = {moo: 2};
-for(var i in foo) {
-    console.log(i); // prints both bar and moo
-}
-
- -

Since it is not possible to change the behavior of the for in loop itself, it -is necessary to filter out the unwanted properties inside the loop body , -this is done by using the hasOwnProperty method of -Object.prototype.

- - - -

Using hasOwnProperty for filtering

- -
// still the foo from above
-for(var i in foo) {
-    if (foo.hasOwnProperty(i)) {
-        console.log(i);
-    }
-}
-
- -

This version is the only correct one to use. Due to the use of hasOwnProperty it -will only print out moo. When hasOwnProperty is left out, the code is -prone to errors in cases where the native prototypes - e.g. Object.prototype - -have been extended.

- -

One widely used framework which does this is Prototype. When this -framework is included, for in loops that do not use hasOwnProperty are -guaranteed to break.

- -

Best practices

- -

It is recommended to always use hasOwnProperty. Never should any -assumptions be made about the environment the code is running in, or whether the -native prototypes have been extended or not.

Functions

Function Declarations and Expressions

Functions in JavaScript are first class objects. That means they can be -passed around like any other value. One common use of this feature is to pass -an anonymous function as a callback to another, possibly asynchronous function.

- -

The function declaration

- -
function foo() {}
-
- -

The above function gets hoisted before the execution of the -program starts; thus, it is available everywhere in the scope it was defined -in, even if called before the actual definition in the source.

- -
foo(); // Works because foo was created before this code runs
-function foo() {}
-
- -

The function expression

- -
var foo = function() {};
-
- -

This example assigns the unnamed and anonymous function to the variable foo.

- -
foo; // 'undefined'
-foo(); // this raises a TypeError
-var foo = function() {};
-
- -

Due to the fact that var is a declaration, that hoists the variable name foo -before the actual execution of the code starts, foo is already defined when -the script gets executed.

- -

But since assignments only happen at runtime, the value of foo will default -to undefined before the corresponding code is executed.

- -

Named function expression

- -

Another special case is the assignment of named functions.

- -
var foo = function bar() {
-    bar(); // Works
-}
-bar(); // ReferenceError
-
- -

Here bar is not available in the outer scope, since the function only gets -assigned to foo; however, inside of bar it is available. This is due to -how name resolution in JavaScript works, the name of the -function is always made available in the local scope of the function itself.

How this Works

JavaScript has a different concept of what the special name this refers to -than most other programming languages do. There are exactly five different -ways in which the value of this can be bound in the language.

- -

The global scope

- -
this;
-
- -

When using this in global scope, it will simply refer to the global object.

- -

Calling a function

- -
foo();
-
- -

Here this will again refer to the global object.

- - - -

Calling a method

- -
test.foo(); 
-
- -

In this example this will refer to test.

- -

Calling a constructor

- -
new foo(); 
-
- -

A function call that is preceded by the new keyword acts as -a constructor. Inside the function this will refer -to a newly created Object.

- -

Explicit setting of this

- -
function foo(a, b, c) {}
-
-var bar = {};
-foo.apply(bar, [1, 2, 3]); // array will expand to the below
-foo.call(bar, 1, 2, 3); // results in a = 1, b = 2, c = 3
-
- -

When using the call or apply methods of Function.prototype, the value of -this inside the called function gets explicitly set to the first argument -of the corresponding function call.

- -

As a result, the above example the method case does not apply, and this -inside of foo will be set to bar.

- - - -

Common pitfalls

- -

While most of these cases make sense, the first one is to be considered another -mis-design of the language, as it never has any practical use.

- -
Foo.method = function() {
-    function test() {
-        // this is set to the global object
-    }
-    test();
-}
-
- -

A common misconception is that this inside of test refers to Foo, while in -fact it does not.

- -

In order to gain access to Foo from within test it is necessary to create a -local variable inside of method which refers to Foo.

- -
Foo.method = function() {
-    var that = this;
-    function test() {
-        // Use that instead of this here
-    }
-    test();
-}
-
- -

that is just a normal name, but it is commonly used for the reference to an -outer this. In combination with closures, it can also -be used to pass this values around.

- -

Assigning methods

- -

Another thing that does not work in JavaScript is function aliasing, that is, -assigning a method to a variable.

- -
var test = someObject.methodTest;
-test();
-
- -

Due to the first case test now acts like like a plain function call; therefore, -this inside it will no longer refer to someObject.

- -

While the late binding of this might seem like a bad idea at first, it is in -fact what makes prototypal inheritance work.

- -
function Foo() {}
-Foo.prototype.method = function() {};
-
-function Bar() {}
-Bar.prototype = Foo.prototype;
-
-new Bar().method();
-
- -

When method gets called on a instance of Bar, this will now refer to that -very instance.

Closures and References

One of JavaScript's most powerful features is the availability of closures, -this means that scopes always keep access to the outer scope they were -defined in. Since the only scoping that JavaScript has is -function scope, all functions, by default, act as closures.

- -

Emulating private variables

- -
function Counter(start) {
-    var count = start;
-    return {
-        increment: function() {
-            count++;
-        },
-
-        get: function() {
-            return count;
-        }
-    }
-}
-
-var foo = Counter(4);
-foo.increment();
-foo.get(); // 5
-
- -

Here, Counter returns two closures. The function increment as well as -the function get. Both of these functions keep a reference to the scope of -Counter and, therefore, always keep access to the count variable that was -defined in that very scope.

- -

Why private variables work

- -

Since it is not possible to reference or assign scopes in JavaScript, there is -no way of accessing the variable count from the outside. The only way to -interact with it is via the two closures.

- -
var foo = new Counter(4);
-foo.hack = function() {
-    count = 1337;
-};
-
- -

The above code will not change the variable count in the scope of Counter, -since foo.hack was not defined in that scope. It will instead create - or -override - the global variable count.

- -

Closures inside loops

- -

One often made mistake is to use closures inside of loops, as if they were -copying the value of the loops index variable.

- -
for(var i = 0; i < 10; i++) {
-    setTimeout(function() {
-        console.log(i);  
-    }, 1000);
-}
-
- -

The above will not output the numbers 0 through 9, but will simply print -the number 10 ten times.

- -

The anonymous function keeps a reference to i and at the time -console.log gets called, the for loop has already finished and the value of -i as been set to 10.

- -

In order to get the desired behavior, it is necessary to create a copy of -the value of i.

- -

Avoiding the reference problem

- -

In order to copy the value of the loop's index variable, it is best to use an -anonymous wrapper.

- -
for(var i = 0; i < 10; i++) {
-    (function(e) {
-        setTimeout(function() {
-            console.log(e);  
-        }, 1000);
-    })(i);
-}
-
- -

The anonymous outer function gets called immediately with i as its first -argument and will receive a copy of the value of i as its parameter e.

- -

The anonymous function that gets passed to setTimeout now has a reference to -e, whose value does not get changed by the loop.

- -

There is another possible way of achieving this; that is to return a function -from the anonymous wrapper, that will then have the same behavior as the code -above.

- -
for(var i = 0; i < 10; i++) {
-    setTimeout((function(e) {
-        return function() {
-            console.log(e);
-        }
-    })(i), 1000)
-}
-

The arguments Object

Every function scope in JavaScript can access the special variable arguments. -This variable holds a list of all the arguments that were passed to the function.

- - - -

The arguments object is not an Array. While it has some of the -semantics of an array - namely the length property - it does not inherit from -Array.prototype and is in fact an Object.

- -

Due to this, it is not possible to use standard array methods like push, -pop or slice on arguments. While iteration with a plain for loop works -just fine, it is necessary to convert it to a real Array in order to use the -standard Array methods on it.

- -

Converting to an array

- -

The code below will return a new Array containing all the elements of the -arguments object.

- -
Array.prototype.slice.call(arguments);
-
- -

This conversion is slow, it is not recommended to use it in performance -critical sections of code.

- -

Passing arguments

- -

The following is the recommended way of passing arguments from one function to -another.

- -
function foo() {
-    bar.apply(null, arguments);
-}
-function bar(a, b, c) {
-    // do stuff here
-}
-
- -

Another trick is to use both call and apply together to create fast, unbound -wrappers.

- -
function Foo() {}
-
-Foo.prototype.method = function(a, b, c) {
-    console.log(this, a, b, c);
-};
-
-// Create an unbound version of "method" 
-// It takes the parameters: this, arg1, arg2...argN
-Foo.method = function() {
-
-    // Result: Foo.prototype.method.call(this, arg1, arg2... argN)
-    Function.call.apply(Foo.prototype.method, arguments);
-};
-
- -

Formal parameters and arguments indexes

- -

The arguments object creates getter and setter functions for both its -properties as well as the function's formal parameters.

- -

As a result, changing the value of a formal parameter will also change the value -of the corresponding property on the arguments object, and the other way around.

- -
function foo(a, b, c) {
-    arguments[0] = 2;
-    a; // 2                                                           
-
-    b = 4;
-    arguments[1]; // 4
-
-    var d = c;
-    d = 9;
-    c; // 3
-}
-foo(1, 2, 3);
-
- -

Performance myths and truths

- -

The arguments object is always created with the only two exceptions being the -cases where it is declared as a name inside of a function or one of its formal -parameters. It does not matter whether it is used or not.

- -

Both getters and setters are always created; thus, using it has nearly -no performance impact at all, especially not in real world code where there is -more than a simple access to the arguments object's properties.

- - - -

However, there is one case which will drastically reduce the performance in -modern JavaScript engines. That case is the use of arguments.callee.

- -
function foo() {
-    arguments.callee; // do something with this function object
-    arguments.callee.caller; // and the calling function object
-}
-
-function bigLoop() {
-    for(var i = 0; i < 100000; i++) {
-        foo(); // Would normally be inlined...
-    }
-}
-
- -

In the above code, foo can no longer be a subject to inlining since it -needs to know about both itself and its caller. This not only defeats possible -performance gains that would arise from inlining, it also breaks encapsulation -since the function may now be dependent on a specific calling context.

- -

It is highly recommended to never make use of arguments.callee or any of -its properties.

- -

Constructors

Constructors in JavaScript are yet again different from many other languages. Any -function call that is preceded by the new keyword acts as a constructor.

- -

Inside the constructor - the called function - the value of this refers to a -newly created Object. The prototype of this new -object is set to the prototype of the function object that was invoked as the -constructor.

- -

If the function that was called has no explicit return statement, then it -implicitly returns the value of this - the new object.

- -
function Foo() {
-    this.bla = 1;
-}
-
-Foo.prototype.test = function() {
-    console.log(this.bla);
-};
-
-var test = new Foo();
-
- -

The above calls Foo as constructor and sets the prototype of the newly -created object to Foo.prototype.

- -

In case of an explicit return statement the function returns the value -specified that statement, but only if the return value is an Object.

- -
function Bar() {
-    return 2;
-}
-new Bar(); // a new object
-
-function Test() {
-    this.value = 2;
-
-    return {
-        foo: 1
-    };
-}
-new Test(); // the returned object
-
- -

When the new keyword is omitted, the function will not return a new object.

- -
function Foo() {
-    this.bla = 1; // gets set on the global object
-}
-Foo(); // undefined
-
- -

While the above example might still appear to work in some cases, due to the -workings of this in JavaScript, it will use the -global object as the value of this.

- -

Factories

- -

In order to be able to omit the new keyword, the constructor function has to -explicitly return a value.

- -
function Bar() {
-    var value = 1;
-    return {
-        method: function() {
-            return value;
-        }
-    }
-}
-Bar.prototype = {
-    foo: function() {}
-};
-
-new Bar();
-Bar();
-
- -

Both calls to Bar return the exact same thing, a newly create object which -has a property called method on it, that is a -Closure.

- -

It is also to note that the call new Bar() does not affect the prototype -of the returned object. While the prototype will be set on the newly created -object, Bar never returns that new object.

- -

In the above example, there is no functional difference between using and -not using the new keyword.

- -

Creating new objects via factories

- -

An often made recommendation is to not use new since forgetting its use -may lead to bugs.

- -

In order to create new object, one should rather use a factory and construct a -new object inside of that factory.

- -
function Foo() {
-    var obj = {};
-    obj.value = 'blub';
-
-    var private = 2;
-    obj.someMethod = function(value) {
-        this.value = value;
-    }
-
-    obj.getPrivate = function() {
-        return private;
-    }
-    return obj;
-}
-
- -

While the above is robust against a missing new keyword and certainly makes -the use of private variables easier, it comes with some -downsides.

- -
    -
  1. It uses more memory since the created objects do not share the methods -on a prototype.
  2. -
  3. In order to inherit the factory needs to copy all the methods from another -object or put that object on the prototype of the new object.
  4. -
  5. Dropping the prototype chain just because of a left out new keyword -somehow goes against the spirit of the language.
  6. -
- -

In conclusion

- -

While omitting the new keyword might lead to bugs, it is certainly not a -reason to drop the use of prototypes altogether. In the end it comes down to -which solution is better suited for the needs of the application, it is -especially important to choose a specific style of object creation and stick -with it.

Scopes and Namespaces

Although JavaScript deals fine with the syntax of two matching curly -braces for blocks, it does not support block scope; hence, all that is left -is in the language is function scope.

- -
function test() { // a scope
-    for(var i = 0; i < 10; i++) { // not a scope
-        // count
-    }
-    console.log(i); // 10
-}
-
- - - -

There are also no distinct namespaces in JavaScript, that means that everything -gets defined in one globally shared namespace.

- -

Each time a variable is referenced, JavaScript will traverse upwards through all -the scopes until it finds it. In the case that it reaches the global scope and -still has not found the requested name, it will raise a ReferenceError.

- -

The bane of global variables

- -
// script A
-foo = '42';
-
-// script B
-var foo = '42'
-
- -

The above two scripts do not have the same effect. Script A defines a -variable called foo in the global scope and script B defines a foo in the -current scope.

- -

Again, that is not at all the same effect, not using var can have major -implications.

- -
// global scope
-var foo = 42;
-function test() {
-    // local scope
-    foo = 21;
-}
-test();
-foo; // 21
-
- -

Leaving out the var statement inside the function test will override the -value of foo. While this might not seem like a big deal at first, having -thousands of lines of JavaScript and not using var will introduce horrible and -hard to track down bugs.

- -
// global scope
-var items = [/* some list */];
-for(var i = 0; i < 10; i++) {
-    subLoop();
-}
-
-function subLoop() {
-    // scope of subLoop
-    for(i = 0; i < 10; i++) { // missing var statement
-        // do amazing stuff!
-    }
-}
-
- -

The outer loop will terminate after the first call to subLoop, since subLoop -overwrites the global value of i. Using a var for the second for loop would -have easily avoided this error. The var statement should never be left out -unless the desired effect is to affect the outer scope.

- -

Local variables

- -

The only source for local variables in JavaScript are -function parameters and variables that were declared via the -var statement.

- -
// global scope
-var foo = 1;
-var bar = 2;
-var i = 2;
-
-function test(i) {
-    // local scope of the function test
-    i = 5;
-
-    var foo = 3;
-    bar = 4;
-}
-test(10);
-
- -

While foo and i are local variables inside the scope of the function test, -the assignment of bar will override the global variable with the same name.

- -

Hoisting

- -

JavaScript hoists declarations. This means that both var statements and -function declarations will be moved to the top of their enclosing scope.

- -
bar();
-var bar = function() {};
-var someValue = 42;
-
-test();
-function test(data) {
-    if (false) {
-        goo = 1;
-
-    } else {
-        var goo = 2;
-    }
-    for(var i = 0; i < 100; i++) {
-        var e = data[i];
-    }
-}
-
- -

The above code gets transformed before any execution is started. JavaScript moves -the var statements as well as the function declarations to the top of the -nearest surrounding scope.

- -
// var statements got moved here
-var bar, someValue; // default to 'undefined'
-
-// the function declartion got moved up too
-function test(data) {
-    var goo, i, e; // missing block scope moves these here
-    if (false) {
-        goo = 1;
-
-    } else {
-        goo = 2;
-    }
-    for(i = 0; i < 100; i++) {
-        e = data[i];
-    }
-}
-
-bar(); // fails with a TypeError since bar is still 'undefined'
-someValue = 42; // assignments are not affected by hoisting
-bar = function() {};
-
-test();
-
- -

Missing block scoping will not only move var statements out of loops and -their bodies, it will also make the results of certain if constructs -non-intuitive.

- -

In the original code the if statement seemed to modify the global -variable goo, while actually it modifies the local variable - after hoisting -has been applied.

- -

Without the knowledge about hoisting, below code might seem to raise a -ReferenceError.

- -
// check whether SomeImportantThing has been initiliazed
-if (!SomeImportantThing) {
-    var SomeImportantThing = {};
-}
-
- -

But of course, the above works due to the fact that the var statement is being -moved to the top of the global scope.

- -
var SomeImportantThing;
-
-// other code might initiliaze SomeImportantThing here, or not
-
-// make sure it's there
-if (!SomeImportantThing) {
-    SomeImportantThing = {};
-}
-
- -

Name resolution order

- -

All scopes in JavaScript, including the global scope, have the special name -this defined in them, which refers to the current object.

- -

Function scopes also have the name arguments defined in -them which contains the arguments that were passed to a function.

- -

For example, when trying to access a variable named foo inside the scope of a -function, JavaScript will lookup the name in the following order:

- -
    -
  1. In case there is a var foo statement in the current scope use that.
  2. -
  3. If one of the function parameters is named foo use that.
  4. -
  5. If the function itself is called foo use that.
  6. -
  7. Go to the next outer scope and start with #1 again.
  8. -
- - - -

Namespaces

- -

A common problem of having only one global namespace is the likeliness of running -into problems where variable names clash. In JavaScript, this problem can -easily be avoided with the help of anonymous wrappers.

- -
(function() {
-    // a self contained "namespace"
-
-    window.foo = function() {
-        // an exposed closure
-    };
-
-})(); // execute the function immediately
-
- -

Unnamed functions are considered expressions; so in order to -being callable, they must first be evaluated.

- -
( // evaluate the function inside the paranthesis
-function() {}
-) // and return the function object
-() // call the result of the evaluation
-
- -

There are other ways for evaluating and calling the function expression; which, -while different in syntax, do behave the exact same way.

- -
// Two other ways
-+function(){}();
-(function(){}());
-
- -

In conclusion

- -

It is recommended to always use an anonymous wrapper for encapsulating code in -its own namespace. This does not only protect code against name clashes, it -also allows for better modularization of programs.

- -

Additionally, the use of global variables is considered bad practice. Any -use of them indicates badly written code that is prone to errors and hard to maintain.

Arrays

Array Iteration and Properties

Although arrays in JavaScript are objects, there are no good reasons to use -the for in loop in for iteration on them. In fact there -are a number of good reasons against the use of for in on arrays.

- - - -

Since the for in loop enumerates all the properties that are on the prototype -chain and the only way to exclude those properties is to use -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, that 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 foo = [1, 2, 3, 4, 5, 6];
-foo.length = 3;
-foo; // [1, 2, 3]
-
-foo.length = 6;
-foo; // [1, 2, 3]
-
- -

Assigning a smaller length does truncate the array, but increasing the length -does not have any effect on the 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.

The Array Constructor

Since the Array constructor is ambiguous in how it deals with its parameters, -it is highly recommended to always use the array literals - [] 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 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
-
- -

The behavior of being able to set the length of the array upfront only comes in -handy in a few cases, like repeating a string, in which it avoids the use of a -for loop code.

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

In conclusion

- -

The use of the Array constructor should be avoided as much as possible. -Literals are definitely preferred. They are shorter and have a clearer syntax; -therefore, they also increase the readability of the code.

Types

Equality and comparisons

JavaScript has two different ways of comparing the values of objects for equality.

- -

The equals operator

- -

The equals operator consists of two equal signs: ==

- -

JavaScript features weak typing, that means, that the equals operator -coerces types in order to compare them.

- -
""           ==   "0"           // false
-0            ==   ""            // true
-0            ==   "0"           // true
-false        ==   "false"       // false
-false        ==   "0"           // true
-false        ==   undefined     // false
-false        ==   null          // false
-null         ==   undefined     // true
-" \t\r\n"    ==   0             // true
-
- -

The above table shows the results of the type coercion and it is the main reason -why the use of == is widely regarded as bad practice, it introduces hard to -track down bugs due to its complicated conversion rules.

- -

Additionally there is also a performance impact when type coercion is in play; -for example, a string has to be converted to a number before it can be compared -to another number.

- -

The strict equals operator

- -

The strict equals operator consists of three equal signs: ===

- -

Other than the normal equals operator, the strict equals operator does not -perform type coercion between its operands.

- -
""           ===   "0"           // false
-0            ===   ""            // false
-0            ===   "0"           // false
-false        ===   "false"       // false
-false        ===   "0"           // false
-false        ===   undefined     // false
-false        ===   null          // false
-null         ===   undefined     // false
-" \t\r\n"    ===   0             // false
-
- -

The above results are a lot clearer and allow for early breakage of code. This -hardens code to a certain degree and also gives performance improvements in case -the operands are of different types.

- -

Comparing objects

- -

While both == and === are stated as equality operators, they behave -different when at least one of their operands happens to be an Object.

- -
{} === {};                   // false
-new String('foo') === 'foo'; // false
-new Number(10) === 10;       // false
-var foo = {};
-foo === foo;                 // true
-
- -

Here both operators compare for identity and not equality; that is, they -will compare for the same instance of the object, much like is in Python -and a pointer comparison in C do.

- -

In conclusion

- -

It is highly recommended to only use the strict equals operator. In cases -where types need to be coerced, it should be done explicitly -and not left to the language's complicated coercion rules.

The typeof operator

The typeof operator (together with -instanceof) is probably the biggest -design flaw of JavaScript, as it is near of being completely broken.

- -

Although instanceof still has its limited uses, typeof really has only one -practical use case, which does not happen to be checking the type of an -object.

- - - -

The JavaScript type table

- -
Value               Class      Type
--------------------------------------
-"foo"               String     string
-new String("foo")   String     object
-1.2                 Number     number
-new Number(1.2)     Number     object
-true                Boolean    boolean
-new Boolean(true)   Boolean    object
-new Date()          Date       object
-new Error()         Error      object
-[1,2,3]             Array      object
-new Array(1, 2, 3)  Array      object
-new Function("")    Function   function
-/abc/g              RegExp     object (function in Nitro/V8)
-new RegExp("meow")  RegExp     object (function in Nitro/V8)
-{}                  Object     object
-new Object()        Object     object
-
- -

In the above table Type refers to the value, that the typeof operator returns. -As can be clearly seen, this value is anything but consistent.

- -

The Class refers to the value of the internal [[Class]] property of an object.

- - - -

In order to retrieve the value of [[Class]] one has to make use of the -toString method of Object.prototype.

- -

The Class of an object

- -

The specification gives exactly one way of accessing the [[Class]] value, -with the use of Object.prototype.toString.

- -
function is(type, obj) {
-    var clas = Object.prototype.toString.call(obj).slice(8, -1);
-    return obj !== undefined && obj !== null && clas === type;
-}
-
-is('String', 'test'); // true
-is('String', new String('test')); // true
-
- -

In the above example, Object.prototype.toString gets called with the value of -this being set to the object whose [[Class]] value should be -retrieved.

- - - -

Testing for undefined variables

- -
typeof foo !== 'undefined'
-
- -

The above will check whether foo was actually declared or not; just -referencing it would result in a ReferenceError. This is the only thing -typeof is actually useful for.

- -

In conclusion

- -

In order to check the type of an object, it is highly recommended to use -Object.prototype.toString; as this is the only reliable way of doing so. -As shown in the above type table, some return values of typeof are not defined -in the specification; thus, they can differ across various implementations.

- -

Unless checking whether a variable is defined, typeof should be avoided at -all costs.

The instanceof operator

The instanceof operator compares the constructors of its two operands. It is -only useful when comparing custom made objects. Used on built-in types, it is -nearly as useless as the typeof operator.

- -

Comparing custom objects

- -
function Foo() {}
-function Bar() {}
-Bar.prototype = new Foo();
-
-new Bar() instanceof Bar; // true
-new Bar() instanceof Foo; // true
-
-// This just sets Bar.prototype to the function object Foo
-// But not to an actual instance of Foo
-Bar.prototype = Foo;
-new Bar() instanceof Foo; // false
-
- -

Using instanceof with native types

- -
new String('foo') instanceof String; // true
-new String('foo') instanceof Object; // true
-
-'foo' instanceof String; // false
-'foo' instanceof Object; // false
-
- -

One important thing to note here is, that instanceof does not work on objects -that origin from different JavaScript contexts (e.g. different documents -in a web browser), since their constructors will not be the exact same object.

- -

In conclusion

- -

The instanceof operator should only be used when dealing with custom made -objects that origin from the same JavaScript context. Just like the -typeof operator, every other use of it should be avoided.

Type casting

JavaScript is a weakly typed language, so it will apply type coercion -wherever possible.

- -
// These are true
-new Number(10) == 10; // Number.toString() is converted
-                      // back to a number
-
-10 == '10';           // Strings gets converted to Number
-10 == '+10 ';         // More string madness
-10 == '010';          // And more 
-isNaN(null) == false; // null converts to 0
-                      // which of course is not NaN
-
-// These are false
-10 == 010;
-10 == '-10';
-
- - - -

In order to avoid the above, use of the strict equal operator -is highly recommended. Although this avoids a lot of common pitfalls, there -are still many further issues that arise from JavaScript's weak typing system.

- -

Constructors of built-in types

- -

The constructors of the built in types like Number and String behave -differently when being used with the new keyword and without it.

- -
new Number(10) === 10;     // False, Object and Number
-Number(10) === 10;         // True, Number and Number
-new Number(10) + 0 === 10; // True, due to implicit conversion
-
- -

Using a built-in type like Number as a constructor will create a new Number -object, but leaving out the new keyword will make the Number function behave -like a converter.

- -

In addition, having literals or non-object values in there will result in even -more type coercion.

- -

The best option is to cast to one of the three possible types explicitly.

- -

Casting to a string

- -
'' + 10 === '10'; // true
-
- -

By prepending a empty string a value can easily be casted to a string.

- -

Casting to a number

- -
+'10' === 10; // true
-
- -

Using the unary plus operator it is possible to cast to a number.

- -

Casting to a boolean

- -

By using the not operator twice, a value can be converted a boolean.

- -
!!'foo';   // true
-!!'';      // false
-!!'0';     // true
-!!'1';     // true
-!!'-1'     // true
-!!{};      // true
-!!true;    // true
-

Core

Why not to use eval

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

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

But eval only executes in local scope when it is being called directly and -the name of the called function is actually eval.

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

The use of eval should be avoided at all costs. 99.9% of its "uses" can be -achieved without it.

- -

eval in disguise

- -

The timeout functions 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 as 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 is to be questioned in -its workings, performance and security. In case something requires eval in -order to work, its design is to be questioned and should not be used in the -first place, a better design should be used, that does not require the use of -eval.

undefined and null

JavaScript has two distinct values for nothing, the more useful of these two -being undefined.

- -

The value undefined

- -

undefined is a type with exactly one value: undefined.

- -

The language also defines a global variable that has the value of undefined, -this variable is also called undefined. But this variable is not a constant, -nor is it a keyword of the language. This means that its value can be easily -overwritten.

- - - -

Some examples for when the value undefined is returned:

- -
    -
  • Accessing the (unmodified) global variable undefined.
  • -
  • Implicit returns of functions due to missing return statements.
  • -
  • return statements which do not explicitly return anything.
  • -
  • Lookups of non-existent properties.
  • -
  • Function parameters which do not had any explicit value passed.
  • -
  • Anything that has been set to the value of undefined.
  • -
- -

Handling changes to the value of undefined

- -

Since the global variable undefined only holds a copy of the actual value of -undefined, assigning a new value to it does not change the value of the -type undefined.

- -

Still, in order to compare something against the value of undefined it is -necessary to retrieve the value of undefined first.

- -

In order to protect code against a possible overwritten undefined variable, a -common technique used is to add an additional parameter to an -anonymous wrapper, that gets no argument passed to it.

- -
var undefined = 123;
-(function(something, foo, undefined) {
-    // undefined in the local scope does 
-    // now again refer to the value
-
-})('Hello World', 42);
-
- -

Another way to achieve the same effect would be to use a declaration inside the -wrapper.

- -
var undefined = 123;
-(function(something, foo) {
-    var undefined;
-    ...
-
-})('Hello World', 42);
-
- -

The only difference being here, that this version results in 4 more bytes being -used in case it is minified and there is no other var statement inside the -anonymous wrapper.

- -

Uses of null

- -

While undefined in the context of the JavaScript language is mostly used in -the sense of a traditional null, the actual null (both a literal and a type) -is more or less just another data type.

- -

It is used in some JavaScript internals (like declaring the end of the -prototype chain by setting Foo.prototype = null), but in almost all cases it -can be replaced by undefined.

Automatic semicolon insertion

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

- -

But JavaScript is not a semicolon-less language, it in fact 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, as 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
-
- - - -

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 advocated to -keep braces on the same line with their corresponding statements and to never omit -them for one single-line if / else statements. Both of these measures will -not only improve the consistency of the code, they will also prevent the -JavaScript parser from changing its behavior.

Other

setTimeout and setInterval

Since JavaScript is asynchronous, it is possible to schedule the execution of a -function by using the setTimeout and setInterval functions.

- - - -
function foo() {}
-var id = setTimeout(foo, 1000); // returns a Number > 0
-
- -

When setTimeout gets called, it will return the ID of the timeout and schedule -foo to run in approximately one thousand milliseconds in the future. -foo will then get executed exactly once.

- -

Depending on the timer resolution of the JavaScript engine that is running the -code, as well as the fact that JavaScript is single threaded and other code that -gets executed might block the thread, it is by no means a safe bet that one -will get the exact delay that was specified in the setTimeout call.

- -

The function that was passed as the first parameter will get called by the -global object, that means, that this inside the called function -refers to that very object.

- -
function Foo() {
-    this.value = 42;
-    this.method = function() {
-        // this refers to the global object
-        console.log(this.value); // will log undefined
-    };
-    setTimeout(this.method, 500);
-}
-new Foo();
-
- - - -

Stacking calls with setInterval

- -

While setTimeout only runs the function once, setInterval - as the name -suggests - will execute the function every X milliseconds. But its use is -discouraged.

- -

When code that is being executed blocks the timeout call, setInterval will -still issue more calls to the specified function. This can, especially with small -intervals, result in function calls stacking up.

- -
function foo(){
-    // something that blocks for 1 second
-}
-setInterval(foo, 100);
-
- -

In the above code foo will get called once and will then block for one second.

- -

While foo blocks the code setInterval will still schedule further calls to -it. Now, when foo has finished, there will already be ten further calls to -it waiting for execution.

- -

Dealing with possible blocking code

- -

The easiest as well as most controllable solution, is to use setTimeout within -the function itself.

- -
function foo(){
-    // something that blocks for 1 second
-    setTimeout(foo, 100);
-}
-foo();
-
- -

Not only does this encapsulate the setTimeout call, but it also prevents the -stacking of calls and it gives additional control.foo itself can now decide -whether it wants to run again or not.

- -

Manually clearing timeouts

- -

Clearing timeouts and intervals works by passing the respective ID to -clearTimeout or clearInterval, depending which set function was used in -the first place.

- -
var id = setTimeout(foo, 1000);
-clearTimeout(id);
-
- -

Clearing all timeouts

- -

As there is no built-in method for clearing all timeouts and/or intervals, -it is necessary to use brute force in order to achieve this functionality.

- -
// clear "all" timeouts
-for(var i = 1; i < 1000; i++) {
-    clearTimeout(i);
-}
-
- -

There might still be timeouts that are unaffected by this arbitrary number; -therefore, is is instead recommended to keep track of all the timeout IDs, so -they can be cleared specifically.

- -

Hidden use of eval

- -

setTimeout and setInterval can also take a string as their first parameter. -This feature should never be used, since it internally makes use of eval.

- - - -
function foo() {
-    // will get called
-}
-
-function bar() {
-    function foo() {
-        // never gets called
-    }
-    setTimeout('foo()', 1000);
-}
-bar();
-
- -

Since eval is not getting called directly in this case, the string -passed to setTimeout will get executed in the global scope; thus, it will -not use the local variable foo from the scope of bar.

- -

It is further recommended to not use a string for passing arguments to the -function that will get called by either of the timeout functions.

- -
function foo(a, b, c) {}
-
-// NEVER use this
-setTimeout('foo(1,2, 3)', 1000)
-
-// Instead use an anonymous function
-setTimeout(function() {
-    foo(a, b, c);
-}, 1000)
-
- - - -

In conclusion

- -

Never should a string be used as the parameter of setTimeout or -setInterval. It is a clear sign of really bad code, when arguments need -to be supplied to the function that gets called. An anonymous function should -be passed that then takes care of the actual call.

- -

Further, the use of setInterval should be avoided since its scheduler is not -blocked by executing JavaScript.

Copyright © 2011. Built with -Node.jsusing a -jadetemplate. -

\ No newline at end of file From 95bcf38ab5e97ef27f9fdf15b343129ca162425e Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Mon, 15 Aug 2011 12:02:59 +0300 Subject: [PATCH 05/41] fix typos between master and current branch --- doc/ru/function/general.md | 4 ++-- doc/ru/object/forinloop.md | 2 +- doc/ru/other/timeouts.md | 4 ++-- doc/ru/types/equality.md | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/ru/function/general.md b/doc/ru/function/general.md index f8012d1a..73fb7100 100644 --- a/doc/ru/function/general.md +++ b/doc/ru/function/general.md @@ -1,6 +1,6 @@ -## Выражения и объявление функций +## Объявление функций и выражения с ними -Функции в JavaScript тоже являются объектами (шок, сенсация) — следовательно, их можно передавать и присваивать точно так же, как и любой другой объект. Одним из вариантов использования такой возможности является передача *анонимной функции* как функции обратного вызова в другую функцию — к примеру, для ассинхронных вызовов. +Функции в JavaScript тоже являются объектами (шок, сенсация). Следовательно, их можно передавать и присваивать точно так же, как и любой другой объект. Одним из вариантов использования такой возможности является передача *анонимной функции* как функции обратного вызова в другую функцию — к примеру, для ассинхронных вызовов. ### Объявление `function` diff --git a/doc/ru/object/forinloop.md b/doc/ru/object/forinloop.md index 22470a2f..9b2b06d4 100644 --- a/doc/ru/object/forinloop.md +++ b/doc/ru/object/forinloop.md @@ -25,7 +25,7 @@ } } -Это единственная версия правильного использования цикла. Благодаря использованию `hasOwnPropery` будет выведено **только** свойство `moo`. Если же убрать `hasOwnProperty`, код становится нестабилен и могут возникнуть ошибки, особенно если кто-то изменил встроенные прототипы, такие как `Object.prototype`. +Это единственная версия правильного использования цикла. Благодаря использованию `hasOwnProperty` будет выведено **только** свойство `moo`. Если же убрать `hasOwnProperty`, код становится нестабилен и могут возникнуть ошибки, особенно если кто-то изменил встроенные прототипы, такие как `Object.prototype`. Один из самых популярных фреймворков [Prototype][1] как раз этим и славится, и если вы его подключаете, то не забудьте использовать `hasOwnProperty` внутри цикла `for in`, иначе у вас гарантированно возникнут проблемы. diff --git a/doc/ru/other/timeouts.md b/doc/ru/other/timeouts.md index 4453493d..2c8661a8 100644 --- a/doc/ru/other/timeouts.md +++ b/doc/ru/other/timeouts.md @@ -75,7 +75,7 @@ `setTimeout` и `setInterval` могут принимать строку в качестве первого параметра. Эту возможность не следует использовать **никогда**, поскольку изнутри при этом производится скрытый вызов `eval`. -> **Замечание**: Поскольку функции работы с таймаутами **не** определены в стандарте ECMAScript, точная внутренняя механика их работы может различаться от движка к движку. Известен факт, то Microsoft JScript использует конструктор `Function` вместо `eval`. +> **Замечание**: Поскольку функции работы с таймаутами **не** определены в стандарте ECMAScript, точная внутренняя механика их работы может различаться от движка к движку. Например, то Microsoft JScript использует конструктор `Function` вместо `eval`. function foo() { // будет вызвана @@ -111,5 +111,5 @@ Кроме того, избегайте использования `setInterval` в случаях, когда его планировщик может блокировать выполнение JavaScript. -[1]: http://ru.wikipedia.org/wiki/Document_Object_Model +[1]: http://ru.wikipedia.org/wiki/Document_Object_Model "Document Object Model" diff --git a/doc/ru/types/equality.md b/doc/ru/types/equality.md index 25cbae31..332bb993 100644 --- a/doc/ru/types/equality.md +++ b/doc/ru/types/equality.md @@ -26,7 +26,7 @@ JavaScript имеет 2 различных способа сравнения з Оператор строгого равенства состоит из **трёх** символов равенства: `===` -В отличие от обычного оператора равенства, оператор строгого равенства **не** выполняет приведение типов между операндами. +Он работает также как и обычный оператор сравнения, но оператор строгого равенства **не** выполняет приведение типов между операндами. "" === "0" // false 0 === "" // false From 391df077f2abd3738c3f9b1e954947925f3821db Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Mon, 15 Aug 2011 12:46:36 +0300 Subject: [PATCH 06/41] just a dash --- doc/ru/function/this.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/ru/function/this.md b/doc/ru/function/this.md index b01f76b0..a49981a5 100644 --- a/doc/ru/function/this.md +++ b/doc/ru/function/this.md @@ -55,7 +55,7 @@ Распространенным заблуждением будет то, что `this` внутри `test` ссылается на `Foo`, но это **не так**. -Для того, чтобы получить доступ к `Foo` внутри функции `test`, необходимо создать локальную перменную внутри `method`, которая и будет ссылаться на `Foo`. +Для того, чтобы получить доступ к `Foo` внутри функции `test`, необходимо создать локальную переменную внутри `method`, которая и будет ссылаться на `Foo`. Foo.method = function() { var that = this; @@ -65,7 +65,7 @@ test(); } -Подходящее имя для переменной - `that`, его часто используют для ссылки на внешний `this`. В комбинации с [замыканиями](#function.closures) `this` можно пробрасывать в глобальную область, или в любой другой объект. +Подходящее имя для переменной — `that`, его часто используют для ссылки на внешний `this`. В комбинации с [замыканиями](#function.closures) `this` можно пробрасывать в глобальную область, или в любой другой объект. > **Замечание** от перев. Кроме `that` так же часто встречаются `this_`, `self_` и другие варианты, но лучше принять для себя `that` как стандарт и тогда, возможно, все вокруг тоже будут им пользоваться. From bf0255a0460376c6dee517435307996bf3522627 Mon Sep 17 00:00:00 2001 From: sentharren Date: Fri, 15 Mar 2013 15:59:56 +0400 Subject: [PATCH 07/41] (ru) function/scopes.md - minor grammar fix --- doc/ru/function/scopes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ru/function/scopes.md b/doc/ru/function/scopes.md index 48c6e846..980d32bc 100644 --- a/doc/ru/function/scopes.md +++ b/doc/ru/function/scopes.md @@ -188,7 +188,7 @@ JavaScript **высасывает** определения. Это значит, ### Заключение -Рекомендуется всегда использовать *анонимную обёртку* для заключения кода в его собственное пространство имён. Это не только защищает код от совпадений имён, но и позваоляет создавать более модульные программы. +Рекомендуется всегда использовать *анонимную обёртку* для заключения кода в его собственное пространство имён. Это не только защищает код от совпадений имён, но и позволяет создавать более модульные программы. Важно добавить, что использование глобальных переменных считается **плохой практикой**. **Любое** их использование демонстрирует плохое качество кода и может привести к трудноуловимым ошибкам. From 12e34fc6106ec6bb8eecaca0bad3c0b68c1f030c Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Thu, 25 Apr 2013 15:04:07 +0200 Subject: [PATCH 08/41] fix major rule translation --- doc/ru/object/general.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/ru/object/general.md b/doc/ru/object/general.md index ceb2466a..29699aa6 100644 --- a/doc/ru/object/general.md +++ b/doc/ru/object/general.md @@ -1,6 +1,6 @@ ## Объекты и их свойства -В JavaScript всё является объектом, лишь за двумя исключениями — [`null`](#core.undefined) и [`undefined`](#core.undefined). +В JavaScript все значения ведут себя как объекты, лишь за двумя исключениями — [`null`](#core.undefined) и [`undefined`](#core.undefined). false.toString() // 'false' [1, 2, 3].toString(); // '1,2,3' @@ -9,7 +9,7 @@ Foo.bar = 1; Foo.bar; // 1 -Неверно считать, что числовые литералы нельзя использовать в качестве объектов — это распространённое заблуждение. Его причиной является упущение в парсере JavaScript, благодаря которому применение *точечной нотации* к числу воспринимается им как литерал числа с плавающей точкой. +Неверно считать, что числовые литералы нельзя использовать в роли объектов — это распространённое заблуждение. Его причиной является упущение в парсере JavaScript, благодаря которому применение *точечной нотации* к числу воспринимается им как литерал числа с плавающей точкой. 2.toString(); // вызывает SyntaxError From e0dce220fa529b864e029ca816eef8f365b29d48 Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Thu, 25 Apr 2013 15:56:34 +0200 Subject: [PATCH 09/41] some stylistic fixes --- doc/ru/array/constructor.md | 4 ++-- doc/ru/array/general.md | 2 +- doc/ru/function/scopes.md | 2 +- doc/ru/object/prototype.md | 2 +- doc/ru/types/equality.md | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/ru/array/constructor.md b/doc/ru/array/constructor.md index 34f15976..f9e56352 100644 --- a/doc/ru/array/constructor.md +++ b/doc/ru/array/constructor.md @@ -9,13 +9,13 @@ new Array(3); // Результат: [] new Array('3') // Результат: ['3'] -В случае, когда в конструктор `Array` передаётся один аргумент и этот аргумент имеет тип `Number`, конструктор возвращает новый, *заполненный случайными значениями*, массив, имеющий длину равную значению переданного аргумента. Стоит заметить, что в этом случае будет установлено только свойство `length` нового массива, индексы массива фактически не будут проинициализированы. +В случае, когда в конструктор `Array` передаётся один аргумент и этот аргумент имеет тип `Number`, конструктор возвращает новый, *заполненный случайными значениями* (в зале подсказывают, _разреженный_), массив, имеющий длину равную значению переданного аргумента. Стоит заметить, что в этом случае будет установлено только свойство `length` нового массива, индексы массива фактически не будут проинициализированы. var arr = new Array(3); arr[1]; // не определён, undefined 1 in arr; // false, индекс не был установлен -Поведение, которое позволяет изначально установить только размер массива может пригодиться лишь в нескольких случаях, таких как повторение строк, за счёт чего избегается использование цикла `for loop`. +Поведение, которое позволяет изначально установить только размер массива может пригодиться лишь в нескольких случаях, таких как повторение строки, за счёт чего избегается использование цикла `for loop`. new Array(count + 1).join(stringToRepeat); diff --git a/doc/ru/array/general.md b/doc/ru/array/general.md index 8350eefa..22c58b0c 100644 --- a/doc/ru/array/general.md +++ b/doc/ru/array/general.md @@ -4,7 +4,7 @@ > **Замечание:** Массивы в JavaScript **не** являются *ассоциативными массивами*. Для связывания ключей и значений в JavaScript есть только [объекты](#object.general). И при том, что ассоциативные массивы **сохраняют** заданный порядок, объекты **не** делают этого. -Во время выполнения `for in` циклически перебираются все свойства объекта, находящиеся в цепочке прототипов. Единственный способ исключить ненужные свойства — использовать [`hasOwnProperty`](#object.hasownproperty), а это **в 20 раз** медленнее обычного цикла `for`. +Во время выполнения `for in` циклически перебираются все свойства объекта, находящиеся в цепочке прототипов. Единственный способ исключить ненужные свойства — использовать [`hasOwnProperty`](#object.hasownproperty), а это **до 20 раз** медленнее обычного цикла `for`. ### Итерирование diff --git a/doc/ru/function/scopes.md b/doc/ru/function/scopes.md index 980d32bc..5e9aac0d 100644 --- a/doc/ru/function/scopes.md +++ b/doc/ru/function/scopes.md @@ -25,7 +25,7 @@ Вышеприведённые два скрипта **не** приводят к одному результату. Скрипт A определяет переменную по имени `foo` в *глобальной* области видимости, а скрипт B определяет `foo` в текущей области видимости. -Повторимся, это вообще **не** *тот же самый эффект*. Если вы не используете `var` — то вы в большой опасности. +Повторимся, это **совсем не** *тот же самый эффект*. Если вы не используете `var` — то вы в большой опасности. // глобальная область видимости var foo = 42; diff --git a/doc/ru/object/prototype.md b/doc/ru/object/prototype.md index 15f90ba6..94f44e7f 100644 --- a/doc/ru/object/prototype.md +++ b/doc/ru/object/prototype.md @@ -37,7 +37,7 @@ Object.prototype { toString: ... /* и т.д. */ } -В приведённом коде объект `test` наследует оба прототипа: `Bar.prototype` и `Foo.prototype`; следовательно, он имеет доступ к функции `method` которую мы определили в прототипе `Foo`. Также у него есть доступ к свойству `value` **одного уникального** экземпляра `Foo`, который является его протипом. Важно заметить, что код `new Bar()` **не** создаёт новый экземпляр `Foo`, а повторно вызывает функцию, которая была назначен его прототипом: таким образом все новые экземпляры `Bar` будут иметь **одинаковое** свойство `value`. +В приведённом коде объект `test` наследует оба прототипа: `Bar.prototype` и `Foo.prototype`; следовательно, он имеет доступ к функции `method` которую мы определили в прототипе `Foo`. Также у него есть доступ к свойству `value` **одного уникального** экземпляра `Foo`, который является его протипом. Важно заметить, что код `new Bar()` **не** создаёт новый экземпляр `Foo`, а повторно использует тот объект, который назначен прототипу `Bar`: таким образом все новые экземпляры `Bar` будут иметь **одинаковое** свойство `value`. > **Замечание:** Никогда **не** используйте конструкцию `Bar.prototype = Foo`, поскольку ссылка будет указывать не на прототип `Foo`, а на объект функции `Foo`. Из-за этого цепочка прототипов будет проходить через `Function.prototype`, а не через `Foo.prototype` и в результате функция `method` не будет содержаться в цепочке прототипов. diff --git a/doc/ru/types/equality.md b/doc/ru/types/equality.md index 98985ec9..0efb49c4 100644 --- a/doc/ru/types/equality.md +++ b/doc/ru/types/equality.md @@ -1,12 +1,12 @@ ##  Равенство и сравнение -JavaScript имеет 2 различных способа сравнения значений объектов на равенство. +JavaScript умеет сравнивать значения объектов на равенство двумя различными способами. ### Оператор сравнения Оператор сравнения состоит из **двух** символов равенства: `==` -*Слабая типизированность* языка JavaScript подразумевает **приведение** обеих переменных к **одному типу** для того, чтобы произвести сравнение. +*Слабая типизация* языка JavaScript подразумевает **приведение** обеих переменных к **одному типу** для того, чтобы сравнить два объекта. "" == "0" // false 0 == "" // true From 9bc24e520d7e82765e4fcdb3589641f155972cec Mon Sep 17 00:00:00 2001 From: saatchiCEO Date: Fri, 26 Apr 2013 16:30:15 +0400 Subject: [PATCH 10/41] Fixed a misprint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ...который является его протипом... протипом -> прототипом --- doc/ru/object/prototype.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ru/object/prototype.md b/doc/ru/object/prototype.md index 94f44e7f..37c32804 100644 --- a/doc/ru/object/prototype.md +++ b/doc/ru/object/prototype.md @@ -37,7 +37,7 @@ Object.prototype { toString: ... /* и т.д. */ } -В приведённом коде объект `test` наследует оба прототипа: `Bar.prototype` и `Foo.prototype`; следовательно, он имеет доступ к функции `method` которую мы определили в прототипе `Foo`. Также у него есть доступ к свойству `value` **одного уникального** экземпляра `Foo`, который является его протипом. Важно заметить, что код `new Bar()` **не** создаёт новый экземпляр `Foo`, а повторно использует тот объект, который назначен прототипу `Bar`: таким образом все новые экземпляры `Bar` будут иметь **одинаковое** свойство `value`. +В приведённом коде объект `test` наследует оба прототипа: `Bar.prototype` и `Foo.prototype`; следовательно, он имеет доступ к функции `method` которую мы определили в прототипе `Foo`. Также у него есть доступ к свойству `value` **одного уникального** экземпляра `Foo`, который является его прототипом. Важно заметить, что код `new Bar()` **не** создаёт новый экземпляр `Foo`, а повторно использует тот объект, который назначен прототипу `Bar`: таким образом все новые экземпляры `Bar` будут иметь **одинаковое** свойство `value`. > **Замечание:** Никогда **не** используйте конструкцию `Bar.prototype = Foo`, поскольку ссылка будет указывать не на прототип `Foo`, а на объект функции `Foo`. Из-за этого цепочка прототипов будет проходить через `Function.prototype`, а не через `Foo.prototype` и в результате функция `method` не будет содержаться в цепочке прототипов. From fca3cb6eb650c619586f6eadbb8ce0bf8e88a5ab Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Fri, 10 May 2013 00:21:21 +0200 Subject: [PATCH 11/41] fixes in introduction and objects --- doc/ru/intro/index.md | 2 +- doc/ru/object/forinloop.md | 16 ++++++++-------- doc/ru/object/general.md | 20 ++++++++++---------- doc/ru/object/hasownproperty.md | 17 +++++++++++------ doc/ru/object/prototype.md | 26 +++++++++++++------------- 5 files changed, 43 insertions(+), 38 deletions(-) diff --git a/doc/ru/intro/index.md b/doc/ru/intro/index.md index 9debe341..2401cce1 100644 --- a/doc/ru/intro/index.md +++ b/doc/ru/intro/index.md @@ -2,7 +2,7 @@ **JavaScript Гарден** — это постоянно обновляющаяся и растущая документация по самым заковыристым темам языка JavaScript. В ней вы найдёте советы о том, как избежать распространённых ошибок и предсказать появление тех или иных багов. В документации подробно освещены проблемы оптимизации и нерекомендуемые практики с которыми, продираясь к глубинам языка, могут столкнуться даже просвещённые JavaScript-программисты. -JavaScript Гарден **не** имеет цели научить вас языку JavaScript. Вам понадобится реальный опыт работы с языком чтобы понимать темы, рассматриваемые в этом руководстве. Если вам требуется изучить основы языка, пожалуйста внимательно ознакомьтесь с замечательным [руководством][1] на сайте Mozilla Developer Network. +JavaScript Гарден **не cтавит** себе целью научить вас языку JavaScript. Вам понадобится реальный опыт работы с языком чтобы понимать темы, рассматриваемые в этом руководстве. Если вам требуется изучить основы языка, пожалуйста обратитесь к замечательному [руководством][1] на сайте Mozilla Developer Network. [1]: https://developer.mozilla.org/en/JavaScript/Guide diff --git a/doc/ru/object/forinloop.md b/doc/ru/object/forinloop.md index 9b2b06d4..a6eb3655 100644 --- a/doc/ru/object/forinloop.md +++ b/doc/ru/object/forinloop.md @@ -1,10 +1,10 @@ ## Цикл `for in` -Как и оператор `in`, цикл `for in` проходит по всей цепочке прототипов обходя свойства объекта. +Как и оператор `in`, цикл `for in` проходит по всей цепочке прототипов, обходя свойства объекта. -> **Примечание:** Цикл `for in` **не** обходит те свойства объекта, у которых атрибут `enumerable` установлен в `false`; как пример - свойство `length` у массивов +> **Примечание:** Цикл `for in` **не** обходит те свойства объекта, у которых внутренний атрибут `enumerable` установлен в `false`; как пример - свойство `length` у массивов - // Испортим Object.prototype + // Подпортим Object.prototype Object.prototype.bar = 1; var foo = {moo: 2}; @@ -12,26 +12,26 @@ console.log(i); // печатает и bar и moo } -Так как изменить поведение цикла `for in` как такового не представляется возможным, то для фильтрации нежелательных свойств объекта внутри этого цикла используют метод [`hasOwnProperty`](#object.hasownproperty) из `Object.prototype`. +Так как изменить поведение цикла `for in` как такового не представляется возможным, то для фильтрации нежелательных свойств объекта внутри этого цикла используется метод [`hasOwnProperty`](#object.hasownproperty) из `Object.prototype`. > **Примечание:** Цикл `for in` всегда обходит всю цепочку прототипов полностью: таким образом, чем больше прототипов (слоёв наследования) в цепочке, тем медленнее работает цикл. ### Использование `hasOwnProperty` в качестве фильтра - // возьмём foo из примера выше + // всё то же foo из примера выше for(var i in foo) { if (foo.hasOwnProperty(i)) { console.log(i); } } -Это единственная версия правильного использования цикла. Благодаря использованию `hasOwnProperty` будет выведено **только** свойство `moo`. Если же убрать `hasOwnProperty`, код становится нестабилен и могут возникнуть ошибки, особенно если кто-то изменил встроенные прототипы, такие как `Object.prototype`. +Это единственно правильная версия использования такого цикла. За счёт использования `hasOwnProperty` будет выведено одно **только** свойство `moo`. Если же вы уберёте проверку `hasOwnProperty`, код станет нестабилен и, если кто-то позволил себе изменить прототипы встроенных типов, такие как `Object.prototype`, у вас возникнут непредвиденные ошибки. -Один из самых популярных фреймворков [Prototype][1] как раз этим и славится, и если вы его подключаете, то не забудьте использовать `hasOwnProperty` внутри цикла `for in`, иначе у вас гарантированно возникнут проблемы. +Один из самых популярных фреймворков [Prototype][1] использует упомянутое расширение `Object.prototype` — и если вы его подключаете — ни в коем случае не забывайте использовать `hasOwnProperty` внутри всех циклов `for in` — иначе у вас гарантированно возникнут проблемы. ### Рекомендации -Рекомендация одна — **всегда** используйте `hasOwnProperty`. Пишите код, который будет в наименьшей мере зависеть от окружения, в котором он будет запущен — не стоит гадать, расширял кто-то прототипы или нет и используется ли в ней та или иная библиотека. +Рекомендация одна — **всегда** используйте `hasOwnProperty`. Пишите код, который будет в наименьшей мере зависеть от окружения, в котором он будет запущен — не стоит гадать, расширял кто-то прототипы или нет и используется ли в нём та или иная библиотека. [1]: http://www.prototypejs.org/ diff --git a/doc/ru/object/general.md b/doc/ru/object/general.md index 96d59f95..90856e25 100644 --- a/doc/ru/object/general.md +++ b/doc/ru/object/general.md @@ -9,19 +9,19 @@ Foo.bar = 1; Foo.bar; // 1 -Неверно считать, что числовые литералы нельзя использовать в роли объектов — это распространённое заблуждение. Его причиной является упущение в парсере JavaScript, благодаря которому применение *точечной нотации* к числу воспринимается им как литерал числа с плавающей точкой. +Распростанено заблуждение, что числовые литералы нельзя использовать в роли объектов — оно неверно и зародилось из-за упущения в парсере JavaScript, благодаря которому применение *точечной нотации* к числу воспринимается им как литерал числа с плавающей точкой. 2.toString(); // вызывает SyntaxError -Есть несколько способов обойти этот недостаток и любой из них можно использовать для того, чтобы работать с числами, как с объектами: +Есть несколько способов обойти этот недостаток и любой из них подойдёт, если нужно добиться от числа поведения объекта: 2..toString(); // вторая точка распознаётся корректно 2 .toString(); // обратите внимание на пробел перед точкой (2).toString(); // двойка вычисляется заранее -### Объекты как тип данных +### Объекты как хранилища данных -Объекты в JavaScript могут использоваться как [*хеш-таблицы*][1]: подавляющей частью состоят из именованных свойств (ключей), привязанных к значениям. +Объекты в JavaScript могут использоваться и как [*хеш-таблицы*][1]: подавляющей частью они состоят из именованных свойств (ключей), привязанных к значениям. Используя объектный литерал — нотацию `{}` — можно создать простой объект. Новый объект [наследуется](#object.prototype) от `Object.prototype` и не имеет [собственных свойств](#object.hasownproperty). @@ -34,7 +34,7 @@ Получить доступ к свойствам объекта можно двумя способами: используя либо точечную нотацию, либо запись квадратными скобками. - var foo = {name: 'Kitten'} + var foo = {name: 'kitten'} foo.name; // kitten foo['name']; // kitten @@ -44,11 +44,11 @@ foo.1234; // SyntaxError foo['1234']; // работает -Обе нотации идентичны по принципу работы — одна лишь разница в том, что использование квадратных скобок позволяет устанавливать свойства динамически и использовать такие имена свойств, какие в других случаях могли бы привести к синтаксической ошибке. +Обе нотации идентичны по принципу работы, одна лишь разница в том, что использование квадратных скобок позволяет устанавливать свойства динамически и использовать такие имена свойств, какие в других случаях могли бы привести к синтаксической ошибке. ### Удаление свойств -Единственный способ удалить свойство у объекта — использовать оператор `delete`; устанавливая свойство в `undefined` или `null`, вы только заменяете связанное с ним *значение*, но не удаляете *ключ*. +Единственный способ полностью удалить свойство у объекта — использовать оператор `delete`; устанавливая свойство в `undefined` или `null`, вы только заменяете связанное с ним *значение*, но не удаляете *ключ*. > **Замечание** от перев.: Если ссылок на значение больше нет, то сборщиком мусора удаляется и само значение, но ключ объекта при этом всё так же имеет новое значение. @@ -73,12 +73,12 @@ var test = { 'case': 'Я — ключевое слово, поэтому меня надо записывать строкой', - delete: 'Я тоже ключевое слово, так что я' // бросаю SyntaxError + delete: 'Я тоже ключевое слово, и меня' // порождает SyntaxError }; -Свойства объектов могут записываться как явно символами, так и в виде закавыченных строк. В связи с другим упущением в парсере JavaScript, этот код выбросит `SyntaxError` во всех версиях ранее ECMAScript 5. +Ключи свойств объектов могут записываться как явно символами без кавычек, так и в виде закавыченных строк. В связи с другим упущением в парсере JavaScript, вышеприведённый код выбросит `SyntaxError` во всех версиях ранее ECMAScript 5. -Источником ошибки является факт, что `delete` — это *ключевое слово* и поэтому его необходимо записывать как *строчный литерал*: ради уверенности в том, что оно будет корректно опознано более старыми движками JavaScript. +Источником ошибки является факт, что `delete` — это *ключевое слово* и поэтому его *необходимо* записывать как *строчный литерал*, ради уверенности в том, что оно будет корректно опознано более старыми движками JavaScript. *От перев.:* И еще один пример в пользу строковой нотации, это относится к [JSON][2]: diff --git a/doc/ru/object/hasownproperty.md b/doc/ru/object/hasownproperty.md index 1c8a617c..55043b65 100644 --- a/doc/ru/object/hasownproperty.md +++ b/doc/ru/object/hasownproperty.md @@ -1,12 +1,12 @@ ## Функция `hasOwnProperty` -Если вам необходимо проверить, определено ли свойство у *самого объекта*, а **не** в его [цепочке прототипов](#object.prototype), вы можете использовать метод `hasOwnProperty`, который все объекты наследуют от `Object.prototype`. +Если вам необходимо проверить, определено ли свойство у *самого объекта*, а **не** где-то в его [цепочке прототипов](#object.prototype), вы можете использовать метод `hasOwnProperty`, который все объекты наследуют от `Object.prototype`. -> **Примечание:** Для проверки наличия свойства **недостаточно** проверять, эквивалентно ли оно `undefined`. Свойство может вполне себе существовать, но при этом ему может быть присвоено значение `undefined`. +> **Примечание:** Для проверки существования свойства **недостаточно** проверять, эквивалентно ли оно `undefined`. Свойство может вполне себе существовать, но при этом ему может быть присвоено значение `undefined`. `hasOwnProperty` — единственная функция в JavaScript, которая позволяет получить свойства объекта **без обращения** к цепочке его прототипов. - // испортим Object.prototype + // Подпортим Object.prototype Object.prototype.bar = 1; var foo = {goo: undefined}; @@ -16,11 +16,11 @@ foo.hasOwnProperty('bar'); // false foo.hasOwnProperty('goo'); // true -Только используя `hasOwnProperty` можно гарантировать правильный результат при переборе свойств объекта. И **нет** иного способа для определения свойств, которые определены в *самом* объекте, а не где-то в цепочке его прототипов. +Только используя `hasOwnProperty` можно гарантировать правильный результат при переборе свойств объекта в циклах. И **нет** иного способа для отделения свойств, которые определены в *самом* объекте, а не где-либо в цепочке его прототипов. ### `hasOwnProperty` как свойство -JavaScript **не** резервирует свойство с именем `hasOwnProperty`. Так что, если есть потенциальная возможность, что объект может содержать свойство с таким именем, требуется использовать *внешний* вариант функции `hasOwnProperty` чтобы получить корректные результаты. +JavaScript **не** резервирует свойство с именем `hasOwnProperty`. Так что, если есть потенциальная возможность, что объект может содержать свойство с таким именем, чтобы получить ожидаемый результат, требуется использовать *внешний* вариант функции `hasOwnProperty`. var foo = { hasOwnProperty: function() { @@ -35,7 +35,12 @@ JavaScript **не** резервирует свойство с именем `has // и передаём foo в качестве this ({}).hasOwnProperty.call(foo, 'bar'); // true + // Для этих целей также можно использовать функцию hasOwnProperty из прототипа Object + Object.prototype.hasOwnProperty.call(foo, 'bar'); // true + +*От перев.:* Обратите внимание, что последний способ в примере не создаёт новых объектов + ### Заключение -**Единственным** способом проверить существование свойства у объекта является использование метода `hasOwnProperty`. При этом, рекомендуется использовать этот метод в **каждом** [цикле `for in`](#object.forinloop) вашего проекта, чтобы избежать возможных ошибок с ошибочным заимствованием свойств из [прототипов](#object.prototype) родительских объектов. Также вы можете использовать конструкцию `{}.hasOwnProperty.call(...)` на случай, если кто-то вздумает расширить [прототипы](#object.prototype) встроенных объектов. +**Единственным** надёжным способом проверить существование свойства у объекта является использование метода `hasOwnProperty`. Рекомендуется использовать этот метод в **любом** [цикле `for in`](#object.forinloop) вашего проекта, дабы избежать потенциальных ошибок с неверным заимствованием свойств из [прототипов](#object.prototype) встроенных объектов. diff --git a/doc/ru/object/prototype.md b/doc/ru/object/prototype.md index 94f44e7f..d0976c2d 100644 --- a/doc/ru/object/prototype.md +++ b/doc/ru/object/prototype.md @@ -2,13 +2,13 @@ В JavaScript отсутствует классическая модель наследования — вместо неё используется [*прототипная модель*][1]. -Хотя её часто расценивают как один из недостатков JavaScript, на самом деле прототипная модель наследования намного мощнее классической. К примеру, поверх неё можно предельно легко реализовать классическое наследование, а попытки совершить обратное вынудят вас попотеть. +Хоть её и часто причисляют к недостаткам JavaScript, на самом деле прототипная модель наследования *мощнее* классической. К примеру, поверх неё можно предельно легко реализовать классическое наследование, а попытки совершить обратное вынудят вас попотеть. Из-за того, что JavaScript — практически единственный широко используемый язык с прототипным наследованием, придётся потратить некоторое время на осознание различий между этими двумя моделями. Первое важное отличие заключается в том, что наследование в JavaScript выполняется с использованием так называемых *цепочек прототипов*. -> **Замечание:** В результате выполнения конструкции `Bar.prototype = Foo.prototype` оба объекта будут делить друг с другом **один и тот же** прототип. Так что изменение прототипа одного из объектов повлечёт за собой изменение прототипа другого и наоборот — вряд ли это окажется тем, чего вы ожидали. +> **Замечание:** При использовании конструкции `Bar.prototype = Foo.prototype` оба объекта будут делить друг с другом **один и тот же** прототип. Так что изменение прототипа одного из объектов повлечёт за собой изменение прототипа другого и наоборот — вряд ли это то, чего вы ожидали. function Foo() { this.value = 42; @@ -23,7 +23,7 @@ Bar.prototype = new Foo(); Bar.prototype.foo = 'Hello World'; - // Убедимся, что Bar является действующим конструктором + // Убедимся, что Bar является настоящим конструктором Bar.prototype.constructor = Bar; var test = new Bar() // создадим новый экземпляр bar @@ -37,31 +37,31 @@ Object.prototype { toString: ... /* и т.д. */ } -В приведённом коде объект `test` наследует оба прототипа: `Bar.prototype` и `Foo.prototype`; следовательно, он имеет доступ к функции `method` которую мы определили в прототипе `Foo`. Также у него есть доступ к свойству `value` **одного уникального** экземпляра `Foo`, который является его протипом. Важно заметить, что код `new Bar()` **не** создаёт новый экземпляр `Foo`, а повторно использует тот объект, который назначен прототипу `Bar`: таким образом все новые экземпляры `Bar` будут иметь **одинаковое** свойство `value`. +В приведённом коде объект `test` будет наследовать оба прототипа: `Bar.prototype` и `Foo.prototype`; следовательно, он будет иметь и доступ к функции `method`, которую мы определили в прототипе `Foo`. Также у него есть доступ к свойству `value` **одного уникального** экземпляра `Foo`, который является его протипом. Важно заметить, что `new Bar()` **не создаёт** новый экземпляр `Foo`, а повторно использует тот объект, который был установлен ему (`Bar`) в прототипе: таким образом, все новые экземпляры `Bar` будут иметь **одно и то же** свойство `value`. -> **Замечание:** Никогда **не** используйте конструкцию `Bar.prototype = Foo`, поскольку ссылка будет указывать не на прототип `Foo`, а на объект функции `Foo`. Из-за этого цепочка прототипов будет проходить через `Function.prototype`, а не через `Foo.prototype` и в результате функция `method` не будет содержаться в цепочке прототипов. +> **Замечание:** Никогда **не используйте** конструкцию `Bar.prototype = Foo`, поскольку ссылка будет указывать не на прототип `Foo`, а на объект-функцию `Foo`. Из-за этого цепочка прототипов будет проходить через `Function.prototype`, а не через `Foo.prototype` и в результате чего функция `method` вообще не будет содержаться в цепочке прототипов. ### Поиск свойств При обращении к какому-либо свойству объекта, JavaScript проходит **вверх** по цепочке прототипов этого объекта, пока не найдет свойство c запрашиваемым именем. -Если он достигнет верхушки этой цепочки (`Object.prototype`) и при этом так и не найдёт указанное свойство, вместо него вернётся значение [undefined](#core.undefined). +Если он достигнет верхушки этой цепочки (а именно `Object.prototype`), и при этом так и не найдёт указанное свойство, вместо него вернётся значение [undefined](#core.undefined). ### Свойство `prototype` -То, что свойство `prototype` используется языком для построения цепочек прототипов, даёт нам возможность присвоить **любое** значение этому свойству. Однако обычные примитивы, если назначать их в качестве прототипа, будут просто-напросто игнорироваться. +Тот факт, что свойство `prototype` используется языком для построения цепочек прототипов, даёт нам возможность присвоить **любое** значение этому свойству. Однако обычные примитивы, если назначать их в качестве прототипа, будут просто-напросто игнорироваться. function Foo() {} - Foo.prototype = 1; // ничего не произойдёт + Foo.prototype = 1; // никакого эффекта Foo.prototype = { "foo":"bar" - }; + }; // это сработает -При этом присвоение объектов, как в примере выше, позволит вам динамически создавать цепочки прототипов. +Но присвоение объектов, как в примерах здесь и выше, сработает, и позволит вам динамически создавать цепочки прототипов. ### Производительность -Поиск свойств, располагающихся относительно высоко по цепочке прототипов, может негативно сказаться на производительности, особенно в критических местах кода. Если же мы попытаемся найти несуществующее свойство, то поиск будет осуществлён вообще по всей цепочке, со всеми вытекающими последствиями. +Поиск свойств, располагающихся относительно высоко по цепочке прототипов, может негативно сказаться на производительности, особенно в критических к ней местах кода. Если же мы попытаемся найти несуществующее свойство, то поиск будет осуществлён вообще по всей цепочке, со всеми вытекающими последствиями. Вдобавок, при [циклическом переборе](#object.forinloop) свойств объекта, будет обработано **каждое** свойство, существующее в цепочке прототипов. @@ -69,13 +69,13 @@ Часто встречается неверное применение прототипов — расширение прототипа `Object.prototype` или прототипов одного из встроенных объектов JavaScript. -Подобная практика нарушает принцип *инкапсуляции*, и имеет соответствующее название — [monkey patching][2]. К сожалению, в основу многих широко распространенных фреймворков, например Prototype, положен принцип изменения базовых прототипов. Вам же стоит запомнить — от хорошей жизни прототипы встроенных объектов не меняют. +Подобная практика нарушает принцип *инкапсуляции*, и имеет соответствующее название — [monkey patching][2]. К сожалению, в основу многих широко распространенных фреймворков, например Prototype, положен принцип изменения базовых прототипов. На самом деле — до сих пор не известно разумных причин примешивать во встроенные типы *нестандартную функциональность*. **Единственным** оправданием для расширения встроенных прототипов может быть только воссоздание возможностей более новых движков JavaScript, например функции [`Array.forEach`][4], которая появилась в версии 1.6. ### Заключение -Перед тем, как вы приступите к разработке сложных приложений на JavaScript, вы **должны** полностью осознать как работают прототипы, и как организовывать наследование на их основе. Также, помните о зависимости между длиной цепочек прототипов и производительностью — разрывайте их при необходимости. Кроме того — **никогда** не расширяйте прототипы встроенных объектов (ну, если только для совместимости с новыми возможностями Javascript). +Перед тем, как вы приступите к разработке сложных приложений на JavaScript с использованием прототипов, вы **должны** полностью осознать как работают прототипные цепочки, и как организовывать наследование на их основе. Также, помните о зависимости между длиной цепочек прототипов и производительностью — разрывайте их при необходимости. Кроме того — **никогда** не расширяйте прототипы встроенных объектов, если вы не делаете это для совместимости с новыми возможностями Javascript. [1]: http://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%BE%D1%82%D0%BE%D1%82%D0%B8%D0%BF%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5 [2]: http://en.wikipedia.org/wiki/Monkey_patch From 6a06c153c24c08001a93e2abf4f2678d0490c88d Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Sun, 12 May 2013 13:04:32 +0200 Subject: [PATCH 12/41] funtions.intro fixes --- doc/ru/function/general.md | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/doc/ru/function/general.md b/doc/ru/function/general.md index 73fb7100..acbca972 100644 --- a/doc/ru/function/general.md +++ b/doc/ru/function/general.md @@ -1,13 +1,13 @@ -## Объявление функций и выражения с ними +## Про объявление функций и выражения с ними -Функции в JavaScript тоже являются объектами (шок, сенсация). Следовательно, их можно передавать и присваивать точно так же, как и любой другой объект. Одним из вариантов использования такой возможности является передача *анонимной функции* как функции обратного вызова в другую функцию — к примеру, для ассинхронных вызовов. +Функции в JavaScript являются объектами. Следовательно, их можно передавать и присваивать точно так же, как и любой другой объект. Популярным сбособом использования этого свойства является передача *анонимной функции* в качестве функции обратного вызова в некую другую функцию — к примеру, при описании асинхронных вызовов. ### Объявление `function` // всё просто и привычно function foo() {} -В следующем примере описанная функция [резервируется](#function.scopes) перед запуском всего скрипта; за счёт этого она доступна *в любом месте* кода, вне зависимости от того где она *определена* — даже если функция вызывается до её фактического объявления в коде. +В следующем примереб ещё перед запуском всего скрипта, для описанной функции [резервируется](#function.scopes) переменная; за счёт этого она доступна *в любом месте* кода, вне зависимости от того, где она *определена* — даже если она вызывается заранее, перед её фактическим объявлением в коде (и сколь угодно задолго до такого определения). foo(); // сработает, т.к. функция будет создана до выполнения кода @@ -17,29 +17,24 @@ var foo = function() {}; -В этом примере безымянная и *анонимная* функция присваивается переменной `foo`. +В конце этого примера переменной `foo` присваивается безымянная *анонимная* функция. foo; // 'undefined' foo(); // вызовет TypeError var foo = function() {}; -Так как в данном примере выражение `var` — это определение функции, переменная с именем `foo` будет заранее зарезервирована перед запуском скрипта (таким образом, `foo` уже будет определена во время его работы). +Поскольку выражение с `var` *резервирует* имя переменной `foo` ещё до запуска кода, `foo` уже имеет некое значение во время его исполнения (отсутствует ошибка «`foo` is not defined»). -Но поскольку присвоения исполняются непосредственно во время работы кода, `foo` по умолчанию будет присвоено значение [`undefined`](#core.undefined) (до обработки строки с определением функции): - - var foo; // переменная неявно резервируется - foo; // 'undefined' - foo(); // вызовет TypeError - foo = function() {}; +Но поскольку сами *присвоения* исполняются только непосредственно во время работы кода, `foo` по умолчанию будет иметь лишь значение [`undefined`](#core.undefined) (до обработки строки с определением функции). ### Выражения с именованными фунциями -Существует еще ньюанс, касающийся именованных функций создающихся через присваивание: +Существует еще один ньюанс, касающийся присваивания именованных функций: var foo = function bar() { bar(); // работает } bar(); // получим ReferenceError -Здесь объект `bar` не доступен во внешней области, так как имя `bar` используется только для присвоения переменной `foo`; однако `bar` можно вызвать внутри функции. Такое поведение связано с особенностью работы JavaScript с [пространствами имен](#function.scopes) - имя функции *всегда* доступно в локальной области видимости самой функции. +Здесь фукнция `bar` не доступна во внешней области видимости, так как она используется только для присвоения переменной `foo`; однако, внутри `bar` она неожиданно оказывается доступна. Такое поведение связано с особенностью работы JavaScript с [разыменованием](#function.scopes) - имя функции *всегда* доступно в локальной области видимости самой функции. From 99e233eb4f53d9e7e7f4af559bcac0ac7cfddd2c Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Mon, 13 May 2013 03:43:30 +0200 Subject: [PATCH 13/41] funtions.closures and functions.this fixes --- doc/ru/function/closures.md | 32 +++++++++++++++++--------------- doc/ru/function/this.md | 36 +++++++++++++++++------------------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/doc/ru/function/closures.md b/doc/ru/function/closures.md index a6e62997..4851b50e 100644 --- a/doc/ru/function/closures.md +++ b/doc/ru/function/closures.md @@ -1,8 +1,8 @@ ## Замыкания и ссылки -Одним из самых мощных инструментов JavaScript'а считаются возможность создавать *замыкания* — это такой приём, когда наша область видимости **всегда** имеет доступ к внешней области, в которой она была объявлена. Собственно, единственный механизм работы с областями видимости в JavaScript — это [функции](#function.scopes): т.о. объявляя функцию, вы автоматически реализуете замыкания. +Одним из самых мощных инструментов язка JavaScript считают возможность создавать *замыкания*. Это такой приём, когда новые области видимости (например, функций) **всегда** имеют доступ к внешней области, в которых они были объявлены. Собственно, единственный механизм создания областей видимости в JavaScript — это и есть [функции](#function.scopes): таким образом, объявляя функцию, вы автоматически реализуете замыкания. Или, другими словами: любая объявленная функция по умолчанию ведёт себя как замыкание. -### Эмуляция приватных свойств +### Эмуляция приватных переменных function Counter(start) { var count = start; @@ -21,22 +21,22 @@ foo.increment(); foo.get(); // 5 -В данном примере `Counter` возвращает **два** замыкания: функции `increment` и `get`. Обе эти функции сохраняют **ссылку** на область видимости `Counter` и, соответственно, имеют доступ к переменной `count` из этой самой области. +В данном примере `Counter` возвращает **два** замыкания: функции `increment` и `get`. Обе эти функции сохраняют внутри себя **ссылку** на область видимости `Counter` и, соответственно, имеют свободный доступ к переменной `count` из этой самой области. -### Как это работает +### Как работают приватные переменные -Поскольку в JavaScript нельзя присваивать или ссылаться на области видимости, заполучить `count` извне **не** представляется возможным. Единственным способом взаимодействовать с ним остается использование двух замыканий. +Поскольку в JavaScript нельзя присваивать или ссылаться на области видимости, заполучить `count` извне — **не** представляется возможным. Единственный способ взаимодействовать с этой переменной — изменять её внутри двух описанных замыканий. var foo = new Counter(4); foo.hack = function() { count = 1337; }; -В приведенном примере мы **не** изменяем переменную `count` в области видимости `Counter`, т.к. `foo.hack` не объявлен в **данной** области. Вместо этого будет создана или перезаписана *глобальная* переменная `count`; +В приведенном примере мы **не** изменяем переменную `count` из области видимости `Counter`, т.к. `foo.hack` не объявлен в **той** области. Вместо этого будет создана или перезаписана *глобальная* переменная `count` (''прим. перев.'' — замена кода внутри `foo.hack` на `this.count = 1337`, не поможет, конечно же, тоже, поскольку `count` и не был свойством объекта `Counter`, а был лишь внутренней переменной); ### Замыкания внутри циклов -Часто встречается ошибка, когда замыкания используют внутри циклов, передавая переменную индекса внутрь. +Существует одна, довольно часто встречающаяся, ловушка — когда замыкания используют внутри циклов, передавая переменную индекса внутрь. for(var i = 0; i < 10; i++) { setTimeout(function() { @@ -44,15 +44,15 @@ }, 1000); } -Данный код **не** будет выводить числа с `0` до `9`, вместо этого число `10` будет выведено десять раз. +Данный код **не** будет выводить числа с `0` до `9` — вместо этого число `10` будет выведено десять раз. -*Анонимная* функция сохраняет **ссылку** на `i` и когда будет вызвана функция `console.log`, цикл `for` уже закончит свою работу, а в `i` будет содержаться `10`. +*Анонимная* функция сохраняет лишь **ссылку** на `i`, и когда будет вызвана функция `console.log`, цикл `for` уже *закончит* свою работу — и поэтому в переменной `i` будет покоиться значение `10`. Для получения желаемого результата необходимо создать **копию** переменной `i`. -### Во избежание ошибок +### Обход проблемы с ссылкой -Для того, чтобы скопировать значение индекса из цикла, лучше всего использовать [анонимную функцию](#function.scopes) как обёртку. +Для того, чтобы скопировать значение индекса из цикла, лучше всего использовать другую [анонимную функцию](#function.scopes) как обёртку. for(var i = 0; i < 10; i++) { (function(e) { @@ -62,11 +62,11 @@ })(i); } -Анонимная функция-обертка будет вызвана сразу же, и в качестве первого аргумента получит `i`, **значение** которой будет скопировано в параметр `e`. +Анонимная функция-обертка вызвается сразу же, и в качестве первого аргумента получает индекс `i`, **значение** которого будет скопировано в параметр `e`. -Анонимная функция, которая передается в `setTimeout`, теперь содержит ссылку на `e`, значение которой **не** изменяется циклом. +Анонимная функция, которая передается в `setTimeout`, теперь содержит ссылку на переменную `e`, значение которой **не** изменяется циклом. -Еще одним способом реализации является возврат функции из анонимной функции-обертки, поведение этого кода будет таким же, как и в коде из предыдущего примера. +Этот приём можно реализовать и другим способом — возвратив нужную функции из анонимной функции-обертки — поведение такого кода будет идентично поведению кода из предыдущего примера. for(var i = 0; i < 10; i++) { setTimeout((function(e) { @@ -76,5 +76,7 @@ })(i), 1000) } -> **Замечание** от перев. Переменную `e` можно тоже назвать `i`, если вы хотите: это не поменяет поведения кода — внутренняя переменная `i` всё так же будет *копией* внешней переменной +''Прим, перев.'' В качестве упражнения на замыкания и анонимные функции, попробуйте заменить оборачивающие вызовы анонимных функций на варианты с `.call` и `.apply`. + +> **Замечание** от перев. Переменную `e` можно тоже назвать `i`, если вы хотите: это не поменяет поведения кода — внутренняя переменная `i` всё так же будет *копией* внешней переменной. diff --git a/doc/ru/function/this.md b/doc/ru/function/this.md index c939ef1c..1ec66a95 100644 --- a/doc/ru/function/this.md +++ b/doc/ru/function/this.md @@ -1,50 +1,50 @@ ## Как работает `this` -В JavaScript область ответственности специальной переменной `this` концептуально отличается от того, за что отвечает `this` в других языках программирования. Различают ровно **пять** вариантов того, к чему привязывается `this` в языке. +В JavaScript зона ответственности специальной переменной `this` концептуально отличается от тех, за которые отвечает `this` в других языках программирования. Различают ровно **пять** сущностей, к которым в этом языке может быть привязана переменная `this`. ### 1. Глобальная область видимости this; -Когда мы используем `this` в глобальной области, она будет просто ссылаться на *глобальный* объект. +Когда мы используем `this` в глобальной области видимости, она просто ссылается на *глобальный* объект. ### 2. Вызов функции foo(); -Тут `this` также ссылается на *глобальный* объект. +Внутри функции `this` ссылается на *глобальный* объект. -> **ES5 Замечание:** В strict-режиме **теряется** понятие глобальности, поэтому в этом случае `this` будет иметь значение `undefined`. +> **Замечание касательно ES5:** В strict-режиме **отсутствует** понятие глобальной видимости, поэтому `this` в этом случае будет иметь значение `undefined`. ### 3. Вызов метода test.foo(); -В данном примере `this` ссылается на `test`. +Внутри метода `this` ссылается на `test`. ### 4. Вызов конструктора new foo(); -Если перед вызовом функции присутствует ключевое слово `new` то данная функция будет действовать как [конструктор](#function.constructors). Внутри такой функции `this` будет указывать на *новосозданный* `Object`. +Если перед вызовом функции присутствует ключевое слово `new` то данная функция будет действовать как [конструктор](#function.constructors). Внутри такой функции `this` будет указывать на *новый созданный* `Object`. ### 5. Переопределение `this` function foo(a, b, c) {} var bar = {}; - foo.apply(bar, [1, 2, 3]); // массив развернётся в a = 1, b = 2, c = 3 - foo.call(bar, 1, 2, 3); // аналогично + foo.apply(bar, [1, 2, 3]); // внутри foo массив развернётся в аргументы + foo.call(bar, 1, 2, 3); // аналогично: a = 1, b = 2, c = 3 Когда мы используем методы `call` или `apply` из `Function.prototype`, то внутри вызваемой функции `this` **явным образом** будет присвоено значение первого передаваемого параметра. -Исходя из этого, в предыдущем примере (строка с `apply`) правило #3 *вызов метода* **не** будет применёно, и `this` внутри `foo` будет присвоено `bar`. +Исходя из этого, в предыдущем примере (строка с `apply`), правило №3 *«вызов метода»* **не** будет применёно, и `this` внутри `foo` будет присвоено `bar`. > **Замечание:** `this` **нельзя** использовать внутри литералов `{}` (`Object`) для ссылки на сам объект. Т.е. если мы напишем `var obj = {me: this}`, то `me` не будет ссылаться на `obj`, поскольку `this` присваивается только по одному из пяти описанных правил. -### Наиболее распространенные ошибки +### Наиболее распространенные ловушки -Хотя большинство из примеров ниже наполнены глубоким смыслом, первый из них можно считать ещё одним упущением в самом языке, поскольку он **вообще** не имеет практического применения. +Хотя большинство из примеров ниже имеют смысл, первый из них можно причислить к упущениям в самом языке, поскольку он **вообще** не имеет практических применений. Foo.method = function() { function test() { @@ -53,7 +53,7 @@ test(); } -Распространенным заблуждением будет то, что `this` внутри `test` ссылается на `Foo`, но это **не так**. +Распространено заблуждение о том, что `this` внутри `test` ссылается на `Foo`, но это совсем **не так**. Для того, чтобы получить доступ к `Foo` внутри функции `test`, необходимо создать локальную переменную внутри `method`, которая и будет ссылаться на `Foo`. @@ -65,20 +65,18 @@ test(); } -Подходящее имя для переменной — `that`, его часто используют для ссылки на внешний `this`. В комбинации с [замыканиями](#function.closures) `this` можно пробрасывать в глобальную область, или в любой другой объект. +Подходящее имя для такой переменной — `that`, и его часто используют для ссылки на внешний `this`. В комбинациях с [замыканиями](#function.closures) такая переменная может использоваться, чтобы «пробрасывать» `this` в глобальную область, или в любой другой объект. -> **Замечание** от перев. Кроме `that` также часто встречаются `this_`, `self_` и другие варианты, но лучше принять для себя `that` как стандарт и тогда, возможно, все вокруг тоже будут им пользоваться. +### Присвоение методов -### Назначение методов - -Еще одной фичей, которая **не** работает в `JavaScript`, является создание псевдонимов для методов, т.е. **присвоение** метода объекта переменной. +Еще одной возможностью, которая могла бы работать, но **не** работает в `JavaScript`, является создание псевдонимов (алиасов) для методов, т.е. **присвоение** метода объекта переменной. var test = someObject.methodTest; test(); -Следуя первому правилу `test` вызывается как обычная функция; следовательно `this` внутри него больше не ссылается на `someObject`. +Следуя первому правилу, `test` вызывается как обычная функция; следовательно `this` внутри него больше не ссылается на `someObject`. -Хотя позднее связывание `this` на первый взгляд может показаться плохой идеей, но на самом деле именно благодаря этому работает [наследование прототипов](#object.prototype). +Хотя позднее связывание `this` на первый взгляд может показаться не очень хорошей идеей, но на самом деле это именно то, благодаря чему работает [наследование прототипов](#object.prototype). function Foo() {} Foo.prototype.method = function() {}; From d57e7816ba4651ed2b5099a51787161d408e32ed Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Sun, 19 May 2013 21:29:48 +0200 Subject: [PATCH 14/41] functions.arguments + minor fixes in functions.* --- doc/ru/function/arguments.md | 26 +++++++++++++------------- doc/ru/function/closures.md | 2 +- doc/ru/function/general.md | 4 ++-- doc/ru/function/scopes.md | 6 ++++++ 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/doc/ru/function/arguments.md b/doc/ru/function/arguments.md index 64085e8d..5269ad2f 100644 --- a/doc/ru/function/arguments.md +++ b/doc/ru/function/arguments.md @@ -4,17 +4,17 @@ > **Замечание:** В случае, если переменная `arguments` уже была объявлена в области видимости функции либо путём присвоения через выражение `var`, либо являясь формальным параметром, объект `arguments` не будет создан. -Объект `arguments` **не** является наследником `Array`. Он, конечно же, очень похож на массив, и даже содержит свойство `length` — но он не наследует `Array.prototype`, а представляет собой `Object`. +Объект `arguments` **не** является ни экземпляром, ни наследником `Array`. Он, конечно же, очень похож на массив, и даже содержит свойство `length` — но он не наследует `Array.prototype`, и если внимательно присмотреться, он окажется обычным `Object`. -По этой причине, у объекта `arguments` **отсутствуют** стандартные методы массивов, такие как `push`, `pop` или `slice`. Хотя итерация с использованием обычного цикла `for` по агрументам работает вполне корректно, вам придётся конвертировать этот объект в настоящий массив типа `Array`, чтобы применять к нему стандартные методы массивов. +По этой причине, у объекта `arguments` **отсутствуют** стандартные методы массивов, такие как `push`, `pop` или `slice`. Пусть перебор с использованием обычного цикла `for` по аргументам работает вполне корректно, но вам придётся конвертировать этот объект в настоящий массив типа `Array`, чтобы применять к нему стандартные методы массивов. ### Конвертация в массив -Указанный код вернёт новый массив типа `Array`, содержащий все элементы объекта `arguments`. +Этот код вернёт новый массив типа `Array`, содержащий все элементы объекта `arguments`. Array.prototype.slice.call(arguments); -Эта конвертация занимает **много времени** и использовать её в критических частях кода **не рекомендуется**. +Будьте внимательны — это преобразование занимает **много времени** и использовать его в чувствительных к производительности частях кода **не рекомендуется**. ### Передача аргументов @@ -27,7 +27,7 @@ // делаем здесь что-нибудь } -Другой трюк — использовать и `call` и `apply` вместе, чтобы быстро создать несвязанную обёртку: +Другой трюк — использовать и `call` и `apply` вместе, чтобы создать отвязанную от объекта обёртку, выполняющуюся приемлемо быстро: function Foo() {} @@ -47,9 +47,9 @@ ### Формальные аргументы и индексы аргументов -Объект `arguments` создаёт по *геттеру* и *сеттеру* и для всех своих свойств и для формальных параметров функции. +Объект `arguments` создаёт по одному *геттеру* и по одному *сеттеру* как для всех своих свойств, так и для формальных параметров функции. -В результате, изменение формального параметра также изменит значение соответствующего свойства объекта `arguments` и наоборот. +В результате, изменение формального параметра повлечёт за собой изменение значения соответствующего свойства объекта `arguments` и наоборот. function foo(a, b, c) { arguments[0] = 2; @@ -64,15 +64,15 @@ } foo(1, 2, 3); -### Мифы и правда о производительности +### Мифы и истина о производительности -Объект `arguments` создаётся во всех случаях, лишь за двумя исключениями — когда он переопределён внутри функции (по имени) или когда одним из её параметров является переменная с таким именем. Неважно, используется при этом сам объект или нет. +Объект `arguments` создаётся во всех случаях, лишь одним исключением — когда он переопределён по имени внутри функции или когда одним из её параметров является переменная с таким именем. Неважно, используется при этом сам объект в коде функции или нет. -*Геттеры* и *сеттеры* создаются **всегда**; так что, их использование практически никак не влияет на производительность. +*Геттеры* и *сеттеры* создаются **всегда**; так что их использование практически никак не влияет на производительность, и тем более никак не влияет на неё в реальном коде, где обычно происходят вещи поважнее обычных прочтений и переопределений свойств объекта `arguments`. > **ES5 Замечание:** Эти *геттеры* и *сеттеры* не создаются в strict-режиме. -Однако, есть один момент, который может радикально понизить производительность современных движков JavaScript. Этот момент — использование `arguments.callee`. +Однако, есть одна такая тайна, незнание которой автором кода может радикально понизить его производительность в современных движках JavaScript. Эта тайна — опасность использования `arguments.callee`. function foo() { arguments.callee; // сделать что-либо с этим объектом функции @@ -81,11 +81,11 @@ function bigLoop() { for(var i = 0; i < 100000; i++) { - foo(); // При обычных условиях должна бы была быть развёрнута... + foo(); // должна была бы «развернуться» } } -В коде выше, функция `foo` не может [быть развёрнута][1] (а могла бы), потому что для корректной работы ей необходима ссылка и на себя и на вызвавший её объект. Это не только кладёт на лопатки механизм развёртывания, но и нарушает принцип инкапсуляции, поскольку функция становится зависима от конкретного контекста вызова. +В коде выше, функция `foo` не может [быть «развёрнута»][1] (а могла бы), потому что для корректной работы ей необходима ссылка и на себя и на вызвавший её объект. Такой код не только кладёт на лопатки механизм развёртывания, но и нарушает принцип инкапсуляции, поскольку функция становится зависима от конкретного контекста вызова. **Крайне не рекомендуется** использовать `arguments.callee` или какое-либо из его свойств. **Никогда**. diff --git a/doc/ru/function/closures.md b/doc/ru/function/closures.md index 4851b50e..7257897b 100644 --- a/doc/ru/function/closures.md +++ b/doc/ru/function/closures.md @@ -50,7 +50,7 @@ Для получения желаемого результата необходимо создать **копию** переменной `i`. -### Обход проблемы с ссылкой +### Обход проблемы со ссылкой Для того, чтобы скопировать значение индекса из цикла, лучше всего использовать другую [анонимную функцию](#function.scopes) как обёртку. diff --git a/doc/ru/function/general.md b/doc/ru/function/general.md index acbca972..e42a4634 100644 --- a/doc/ru/function/general.md +++ b/doc/ru/function/general.md @@ -1,4 +1,4 @@ -## Про объявление функций и выражения с ними +## Про объявление функций и о выражениях с ними Функции в JavaScript являются объектами. Следовательно, их можно передавать и присваивать точно так же, как и любой другой объект. Популярным сбособом использования этого свойства является передача *анонимной функции* в качестве функции обратного вызова в некую другую функцию — к примеру, при описании асинхронных вызовов. @@ -23,7 +23,7 @@ foo(); // вызовет TypeError var foo = function() {}; -Поскольку выражение с `var` *резервирует* имя переменной `foo` ещё до запуска кода, `foo` уже имеет некое значение во время его исполнения (отсутствует ошибка «`foo` is not defined»). +Поскольку выражение с применением `var` *резервирует* имя переменной `foo` ещё до запуска кода, `foo` уже имеет некое значение во время его исполнения (отсутствует ошибка «`foo` is not defined»). Но поскольку сами *присвоения* исполняются только непосредственно во время работы кода, `foo` по умолчанию будет иметь лишь значение [`undefined`](#core.undefined) (до обработки строки с определением функции). diff --git a/doc/ru/function/scopes.md b/doc/ru/function/scopes.md index 5e9aac0d..fbc54926 100644 --- a/doc/ru/function/scopes.md +++ b/doc/ru/function/scopes.md @@ -186,6 +186,12 @@ JavaScript **высасывает** определения. Это значит, +function(){}(); (function(){}()); + + ### Заключение Рекомендуется всегда использовать *анонимную обёртку* для заключения кода в его собственное пространство имён. Это не только защищает код от совпадений имён, но и позволяет создавать более модульные программы. From 0b58b920d1491a344ee51c1271bd924485cd97e6 Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Sun, 19 May 2013 21:39:25 +0200 Subject: [PATCH 15/41] russian quotes --- doc/ru/core/eval.md | 2 +- doc/ru/core/semicolon.md | 8 ++++---- doc/ru/function/arguments.md | 4 ++-- doc/ru/function/scopes.md | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/ru/core/eval.md b/doc/ru/core/eval.md index 3750281f..12e494ce 100644 --- a/doc/ru/core/eval.md +++ b/doc/ru/core/eval.md @@ -23,7 +23,7 @@ test(); // 2 foo; // 3 -**Любой ценой** избегайте использования функции `eval`. 99.9% случаев её "использования" могут достигаться **без её участия**. +**Любой ценой** избегайте использования функции `eval`. 99.9% «трюков» с её «использованием» могут решаться **без её участия**. ### `eval` под прикрытием diff --git a/doc/ru/core/semicolon.md b/doc/ru/core/semicolon.md index 18c5749b..87e56993 100644 --- a/doc/ru/core/semicolon.md +++ b/doc/ru/core/semicolon.md @@ -47,7 +47,7 @@ })(window) -Ниже представлен результат игры парсера в "угадалки". +Ниже представлен результат игры парсера в «угадалки». (function(window, undefined) { function test(options) { @@ -62,7 +62,7 @@ 'и ещё одну на всякий случай' ); // <- вставлена - return; // <- вставлена, в результате + return; // <- вставлена, в результате // оператор return разбит на два блока { // теперь парсер считает этот блок отдельным @@ -82,9 +82,9 @@ Парсер радикально подменил поведение изначального кода, а в определённых случаях он сделал **абсолютно неправильные выводы**. -### "Висящие" скобки +### «Висящие» скобки -Если парсер встречает "висящую" скобку, то он **не** вставляет точку с запятой. +Если парсер встречает «висящую» скобку, то он **не** вставляет точку с запятой. log('тестируем!') (options.list || []).forEach(function(i) {}) diff --git a/doc/ru/function/arguments.md b/doc/ru/function/arguments.md index 5269ad2f..a9bfa59b 100644 --- a/doc/ru/function/arguments.md +++ b/doc/ru/function/arguments.md @@ -35,7 +35,7 @@ console.log(this, a, b, c); }; - // Создаём несвязанную версию "method" + // Создаём несвязанную версию метода // Она принимает параметры: this, arg1, arg2...argN Foo.method = function() { @@ -89,7 +89,7 @@ **Крайне не рекомендуется** использовать `arguments.callee` или какое-либо из его свойств. **Никогда**. -> **ES5 Замечание:** В strict-режиме использование `arguments.callee` породит `TypeError`, поскольку его использование принято устаревшим. +> **ES5 Замечание:** В strict-режиме любое использование `arguments.callee` вызовет `TypeError`, поскольку свойство принято устаревшим. [1]: http://en.wikipedia.org/wiki/Inlining diff --git a/doc/ru/function/scopes.md b/doc/ru/function/scopes.md index fbc54926..58946f64 100644 --- a/doc/ru/function/scopes.md +++ b/doc/ru/function/scopes.md @@ -125,7 +125,7 @@ JavaScript **высасывает** определения. Это значит, В исходном коде оператор `if` изменял *глобальную переменную* `goo`, когда, как оказалось, он изменяет *локальную переменную* — в результате работы высасывания. -Если вы не знакомы с *высасываниями*, то можете посчитать, что нижеприведённый код должен породить +Если вы не знакомы с *высасываниями*, то можете предположить, что нижеприведённый код должен породить `ReferenceError`. // проверить, проинициализована ли SomeImportantThing @@ -165,7 +165,7 @@ JavaScript **высасывает** определения. Это значит, Нередкое последствие наличия только одного глобального пространства имён — проблемы с перекрытием имён переменных. В JavaScript эту проблему легко избежать, используя *анонимные обёртки*. (function() { - // самостоятельно созданное "пространство имён" + // самостоятельно созданное «пространство имён» window.foo = function() { // открытое замыкание From 97edd935d4b9f5691540948b460eea747755327e Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Sun, 19 May 2013 21:48:12 +0200 Subject: [PATCH 16/41] =?UTF-8?q?=D0=B2=D1=8B=D1=81=D0=B0=D1=81=D1=8B?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20->=20=D0=B2=D1=8B=D1=82=D1=8F?= =?UTF-8?q?=D0=B3=D0=B8=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/ru/function/scopes.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/ru/function/scopes.md b/doc/ru/function/scopes.md index 58946f64..ef8b49aa 100644 --- a/doc/ru/function/scopes.md +++ b/doc/ru/function/scopes.md @@ -73,9 +73,9 @@ В то время как `foo` и `i` — локальные переменные в области видимости функции `test`, присвоение `bar` переопределит значение одноимённой глобальной переменной. -### Высасывание +### Вытягивание -JavaScript **высасывает** определения. Это значит, что оба определения с использованием `var` и определение `function` будут перенесены наверх заключающей их области видимости. +JavaScript **вытягивает** определения. Это значит, что оба определения с использованием `var` и определение `function` будут перенесены наверх из заключающей их области видимости. bar(); var bar = function() {}; @@ -116,7 +116,7 @@ JavaScript **высасывает** определения. Это значит, bar(); // вылетает с ошибкой TypeError, // поскольку bar всё ещё 'undefined' - someValue = 42; // присвоения не подвержены высасыванию + someValue = 42; // присвоения не подвержены вытягиванию bar = function() {}; test(); @@ -125,7 +125,7 @@ JavaScript **высасывает** определения. Это значит, В исходном коде оператор `if` изменял *глобальную переменную* `goo`, когда, как оказалось, он изменяет *локальную переменную* — в результате работы высасывания. -Если вы не знакомы с *высасываниями*, то можете предположить, что нижеприведённый код должен породить +Если вы не знакомы с *вытягиваниями*, то можете предположить, что нижеприведённый код должен породить `ReferenceError`. // проверить, проинициализована ли SomeImportantThing From 40439588975ec8587239d048165e8a5877cb8484 Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Sun, 19 May 2013 22:21:12 +0200 Subject: [PATCH 17/41] functions.constructors --- doc/ru/function/constructors.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/doc/ru/function/constructors.md b/doc/ru/function/constructors.md index 20b09d4f..dea733db 100644 --- a/doc/ru/function/constructors.md +++ b/doc/ru/function/constructors.md @@ -1,10 +1,10 @@ ## Конструктор -Создание конструкторов в JavaScript также отличается от большинства других языков. Любая функция, вызванная с использованием ключевого слова `new`, будет конструктором. + Конструкторы в JavaScript тоже действуют отличным от большинства других языков образом. Любая функция, вызванная с использованием ключевого слова `new`, станет конструктором. -Внутри конструктора (вызываемой функции) `this` будет указывать на новосозданный `Object`. [Прототипом](#object.prototype) этого **нового** объекта будет `prototype` функции, которая была вызвана в качестве коструктора. +Внутри конструктора (вызываемой функции) `this` будет указывать на новосозданный `Object`. [Прототипом](#object.prototype) этого **нового** экземпляра будет `prototype` функции, которая была вызвана под видом конструктора. -Если вызываемая функция не имеет явного возврата посредством `return`, то вернётся `this` — этот новый объект. +Если вызываемая функция не возвращает явного значения посредством `return`, то она автоматически вернёт `this` — тот самый новый экземпляр. function Foo() { this.bla = 1; @@ -18,7 +18,7 @@ В этом примере `Foo` вызывается в виде конструктора, следовательно прототип созданного объекта будет привязан к `Foo.prototype`. -В случае, когда функция в явном виде возвращает некое значение используя `return`, то в результате выполнения конструктора мы получим именно его, **но только** если возвращаемое значение представляет собой `Object`. +В случае, когда функция в явном виде возвращает некое значение используя `return`, в результате выполнения конструктора мы получим именно его, **но только** если возвращаемое значение представляет собой `Object`. function Bar() { return 2; @@ -37,15 +37,15 @@ Если же опустить ключевое слово `new`, то функция **не** будет возвращать никаких объектов. function Foo() { - this.bla = 1; // устанавливается глобальному объекту + this.bla = 1; // свойство bla устанавливается глобальному объекту } - Foo(); // undefined + Foo(); // возвращает undefined -Этот пример в некоторых случаях всё-таки может сработать: это связано с поведением [`this`](#function.this) в JavaScript — он будет восприниматься парсером как *глобальный объект*. +Хотя этот пример и будет работать — в связи с поведением [`this`](#function.this) в JavaScript, значение будет присвоено *глобальному объекту* — навряд ли это предполагалось автором. ### Фабрики -Если хотите избавится от необходимости использования `new`, напишите конструктор, возвращающий значение посредством `return`. +Если вы хотите предоставить возможность опускать оператор `new` при создании объектов, возвращайте из соответствующего конструктора явное значение посредством `return`. function Bar() { var value = 1; @@ -62,17 +62,17 @@ new Bar(); Bar(); -В обоих случаях при вызове `Bar` мы получим один и тот же результат — новый объект со свойством `method` (спасибо [замыканию](#function.closures) за это). +В обоих случаях при вызове `Bar` мы получим один и тот же результат — новый объект со свойством `method`, являющимся [замыканием](#function.closures)). -Также следует заметить, что вызов `new Bar()` никак **не** связан с прототипом возвращаемого объекта. Хоть прототип и назначается всем новосозданным объектам, но `Bar` никогда не возвращает этот новый объект. +Ещё следует заметить, что вызов `new Bar()` никак **не** воздействует на прототип возвращаемого объекта. Хоть прототип и назначается всем новосозданным объектам, `Bar` никогда не возвращает этот новый объект (''прим. перев.'' — судя по всему, подразумевается, что код `Bar` не может влиять на прототип созданного объекта, и под словами «новый объект» в последнем случае кроется прототип нового объекта, а не сам новый объект). -В предыдущем примере нет функциональных отличий между вызовом конструктора с оператором `new` или без него. +В предыдущем примере нет никаких функциональных различий между вызовом конструктора с оператором `new` и вызовом без него. ### Создание объектов с использованием фабрик -Часто рекомендуют **не** использовать `new`, поскольку если вы его забудете, это может привести к ошибкам. +Нередко встречаются советы **не** использовать оператор `new`, поскольку если вы его забудете, это может привести к ошибкам. -Чтобы создать новый объект, лучше использовать фабрику и создать новый объект *внутри* этой фабрики. +Чтобы создать новый объект, нам предлагают использовать фабрику и создать новый объект *внутри* этой фабрики. function Foo() { var obj = {}; @@ -89,13 +89,13 @@ return obj; } -Хотя данный пример и сработает, если вы забыли ключевое слово `new` и благодаря ему легче работать с [приватными переменными](#function.closures), у него есть несколько недостатков +Хотя данный пример и сработает, если вы забыли ключевое слово `new` и, возможно, благодаря ему вам станет легче работать с [приватными переменными](#function.closures), у него есть несколько недостатков: 1. Он использует больше памяти, поскольку созданные объекты **не** хранят методы в прототипе и соответственно для каждого нового объекта создаётся копия каждого метода. 2. Чтобы эмулировать наследование, фабрике нужно скопировать все методы из другого объекта или установить прототипом нового объекта старый. - 3. Разрыв цепочки прототипов просто по причине забытого ключевого слова `new` идёт в разрез с духом языка. + 3. Разрыв цепочки прототипов по мнимой необходимости избавиться от использования ключевого слова `new` идёт вразрез с духом языка. ### Заключение -Хотя забытое ключевое слово `new` и может привести к багам, это точно **не** причина отказываться от использования прототипов. В конце концов, полезнее решить какой из способов лучше совпадает с требованиями приложения: очень важно выбрать один из стилей создания объектов и после этого **не изменять** ему. +Хотя забытое ключевое слово `new` и может привести к багам, это точно **не** причина отказываться от использования прототипов. В конце концов, полезнее решить какой из способов лучше совпадает с требованиями приложения: крайне важно выбрать один из стилей создания объектов и после этого **не изменять** ему. From 2fe7e5dd829e9289fea28eb3d7f3677a5623a427 Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Sun, 19 May 2013 22:57:01 +0200 Subject: [PATCH 18/41] functions.scopes --- doc/ru/function/scopes.md | 52 +++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/doc/ru/function/scopes.md b/doc/ru/function/scopes.md index ef8b49aa..a3771954 100644 --- a/doc/ru/function/scopes.md +++ b/doc/ru/function/scopes.md @@ -1,6 +1,6 @@ ## Области видимости и пространства имён -Хотя JavaScript нормально понимает синтаксис двух фигурных скобок, окружающих блок, он **не** поддерживает блочную область видимости; всё что остаётся на этот случай в языке — *область видимости функций*. +Хотя JavaScript вполне нормально воспринимает синтаксис двух сопоставимых фигурных скобок, окружающих блок, он **не** поддерживает блочную область видимости; всё что остаётся на этот случай в языке — *область видимости функций*. function test() { // область видимости for(var i = 0; i < 10; i++) { // не область видимости @@ -9,11 +9,11 @@ console.log(i); // 10 } -> **Замечание:** Нотация `{...}` будет интерпретирована как блочное выражение, а **не** как литерал объекта, если она не используется в присваивании, операторе `return` или в качестве функции. Это замечание, вкупе с [автоматической расстановкой точек с запятой](#core.semicolon), может привести к чрезвычайно хитрым ошибкам. +> **Замечание:** Нотация `{...}` будет интерпретирована как блочное выражение, а **не** как литерал объекта, если она не используется в присваивании, операторе `return` или в качестве функции. Это замечание, вкупе с [автоматической расстановкой точек с запятой](#core.semicolon), может привести к чрезвычайно изощрённым ошибкам. -Также JavaScript не знает ничего о различиях в пространствах имён: всё определяется в *глобально доступном* пространстве имён. +Также JavaScript не различает пространств имён: всё определяется на том или ином уровне в единственном *глобально доступном* пространстве имён. -Каждый раз, когда JavaScript обнаруживает ссылку на переменную, он будет искать её всё выше и выше по областям видимости, пока не найдёт её. В случае, если он достигнет глобальной области видимости и не найдет запрошенное имя и там тоже, он ругнётся `ReferenceError`. +Каждый раз, когда JavaScript обнаруживает ссылку на переменную, он будет искать её всё выше и выше по областям видимости, пока не найдёт её. В случае, если он достигнет глобальной области видимости и не найдет запрошенное имя и там тоже, он выбросит `ReferenceError`. ### Проклятие глобальных переменных @@ -23,7 +23,7 @@ // скрипт B var foo = '42' -Вышеприведённые два скрипта **не** приводят к одному результату. Скрипт A определяет переменную по имени `foo` в *глобальной* области видимости, а скрипт B определяет `foo` в текущей области видимости. +Вышеприведённые два скрипта отнюдь **не** приводят к одинаковому результату. Скрипт A определяет переменную по имени `foo` в *глобальной* области видимости, а скрипт B определяет `foo` в текущей области видимости. Повторимся, это **совсем не** *тот же самый эффект*. Если вы не используете `var` — то вы в большой опасности. @@ -36,7 +36,7 @@ test(); foo; // 21 -Из-за того что оператор `var` опущен внутри функции, фунция `test` перезапишет значение `foo`. Это поначалу может показаться не такой уж и большой проблемой, но если у вас имеется тысяча строк JavaScript-кода и вы не используете `var`, то вам на пути встретятся страшные и трудноотлаживаемые ошибки — и это не шутка. +Из-за того что оператор `var` был опущен внутри функции, фунция `test` перезапишет значение `foo`. Это поначалу может показаться не такой уж и большой проблемой, но если у вас имеется тысяча строк JavaScript-кода и вы не используете `var`, то вам на пути встретятся самые страшные и трудноотлаживаемые ошибки — и это не шутка. // глобальная область видимости var items = [/* какой-то список */]; @@ -46,12 +46,12 @@ function subLoop() { // область видимости subLoop - for(i = 0; i < 10; i++) { // пропущенный оператор var - // делаем волшебные вещи! + for(i = 0; i < 10; i++) { // пропущен оператор var + // происходят волшебные вещи! } } -Внешний цикл прекратит работу сразу после первого вызова `subLoop`, поскольку `subLoop` перезаписывает глобальное значение переменной `i`. Использование `var` во втором цикле `for` могло бы вас легко избавить от этой ошибки. **Никогда** не забывайте использовать `var`, если только влияние на внешнюю область видимости не является тем, что вы *намерены получить*. +Внешний цикл прекратит работу сразу после первого вызова `subLoop`, поскольку `subLoop` перезаписывает глобальное значение переменной `i`. Использование `var` во втором цикле `for` могло бы вас легко избавить от этой ошибки. **Никогда** не забывайте использовать `var`, если только вы не *осознанно намеряны* повлиять на внешнюю область видимости. ### Локальные переменные @@ -75,7 +75,7 @@ ### Вытягивание -JavaScript **вытягивает** определения. Это значит, что оба определения с использованием `var` и определение `function` будут перенесены наверх из заключающей их области видимости. +JavaScript **«вытягивает»** определения. Это значит, что оба определения с использованием `var` и определение `function` будут перенесены наверх из заключающей их области видимости. bar(); var bar = function() {}; @@ -101,8 +101,8 @@ JavaScript **вытягивает** определения. Это значит, // определение функции тоже переместилось function test(data) { - var goo, i, e; // потерянная блочная область видимости - // переместилась сюда + var goo, i, e; // пропущенная блочная область видимости + // переместила их сюда if (false) { goo = 1; @@ -116,16 +116,16 @@ JavaScript **вытягивает** определения. Это значит, bar(); // вылетает с ошибкой TypeError, // поскольку bar всё ещё 'undefined' - someValue = 42; // присвоения не подвержены вытягиванию + someValue = 42; // присвоения не зависят от вытягивания bar = function() {}; test(); Потерянная область видимости блока не только переместит операторы `var` вовне циклов и их тел, но и сделает результаты некоторых конструкций с `if` неинтуитивными. -В исходном коде оператор `if` изменял *глобальную переменную* `goo`, когда, как оказалось, он изменяет *локальную переменную* — в результате работы высасывания. +Предполагалось, что в исходном коде оператор `if` изменял *глобальную переменную* `goo`, однако, как оказалось, он изменял *локальную переменную* — в результате работы вытягивания. -Если вы не знакомы с *вытягиваниями*, то можете предположить, что нижеприведённый код должен породить +Если вы не знакомы с *вытягиваниями*, то можете предположить, что нижеприведённый код должен выбросить `ReferenceError`. // проверить, проинициализована ли SomeImportantThing @@ -147,25 +147,25 @@ JavaScript **вытягивает** определения. Это значит, ### Порядок разрешения имён -Все области видимости в JavaScript, включая *глобальную области видимости*, содержат специальную, определённую внутри них, переменную [`this`](#function.this), которая ссылается на *текущий объект*. +Все области видимости в JavaScript, включая *глобальную область видимости*, содержат специальную, определённую внутри них, переменную [`this`](#function.this), которая ссылается на *текущий объект*. Области видимости функций также содержат внутри себя переменную [`arguments`](#function.arguments), которая содержит аргументы, переданные в функцию. Например, когда JavaScript пытается получить доступ к переменной `foo` в области видимости функции, он будет искать её по имени в такой последовательности: - 1. Если в текущей области видимости есть выражение `var foo`, использовать его. - 2. Если один из параметров функции называется `foo`, использовать его. + 1. Если в текущей области видимости есть выражение `var foo`, использовать эту переменную. + 2. Если один из параметров функции называется `foo`, использовать этот параметр. 3. Если функциия сама называется `foo`, использовать её. - 4. Перейти на одну область видимости выше и начать с **п. 1** + 4. Перейти на одну область видимости выше и повторить, начиная с **п. 1** -> **Замечание:** Наличие параметра функции с именем `arguments` **не позволит** движку создать объект `arguments`, создающийся по умолчанию. +> **Замечание:** Наличие параметра функции с именем `arguments` **не позволит** движку создать объект `arguments`, создающийся, в других случаях, по умолчанию. ### Пространства имён -Нередкое последствие наличия только одного глобального пространства имён — проблемы с перекрытием имён переменных. В JavaScript эту проблему легко избежать, используя *анонимные обёртки*. +Нередкое обнаруживается неприятное последствие наличия одного единственного глобального пространства имён — проблемы с перекрытием имён переменных. В JavaScript эту проблему легко избежать, используя *анонимные обёртки*. (function() { - // самостоятельно созданное «пространство имён» + // самодостаточное «пространство имён» window.foo = function() { // открытое замыкание @@ -173,14 +173,14 @@ JavaScript **вытягивает** определения. Это значит, })(); // сразу же выполнить функцию -Безымянные функции являются [выражениями](#function.general); поэтому, чтобы вы имели возможность их выполнить, они сперва должны быть разобраны. +Безымянные функции являются отложенными [выражениями](#function.general) (''прим. перев.'' — то есть, они не разбираются по месту описания, а откладываются парсером напоследок); поэтому, чтобы вы сделать их исполняемыми, следует спровоцировать их разбор. ( // разобрать функцию внутри скобок function() {} ) // и вернуть объект функции () // вызвать результат разбора -Есть другие способы разбора и последующего вызова выражения с функцией; они, хоть и различаются в синтаксисе, но действуют одинаково. +Есть другие способы спровоцировать разбор и последующий вызов выражения с функцией; они, хоть и различаются в синтаксисе, действуют одинаково: // Два других способа +function(){}(); @@ -194,7 +194,7 @@ JavaScript **вытягивает** определения. Это значит, ### Заключение -Рекомендуется всегда использовать *анонимную обёртку* для заключения кода в его собственное пространство имён. Это не только защищает код от совпадений имён, но и позволяет создавать более модульные программы. +Рекомендуется всегда использовать *анонимную обёртку* чтобы заключить код в собственное пространство имён. Это не только защищает код от совпадений имён, но и позволяет создавать модульные программы. -Важно добавить, что использование глобальных переменных считается **плохой практикой**. **Любое** их использование демонстрирует плохое качество кода и может привести к трудноуловимым ошибкам. +Важно добавить, что использование глобальных переменных считается **плохой практикой**. **Любое** их использование демонстрирует плохое качество кода, предполагает его высокую подверженность ошибкам и сложность в его разборе. From cca783bb0032a11192da3b260c86c4424dd47892 Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Sun, 19 May 2013 23:53:51 +0200 Subject: [PATCH 19/41] arrays --- doc/ru/array/constructor.md | 8 ++++---- doc/ru/array/general.md | 22 ++++++++++++---------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/doc/ru/array/constructor.md b/doc/ru/array/constructor.md index f9e56352..05401763 100644 --- a/doc/ru/array/constructor.md +++ b/doc/ru/array/constructor.md @@ -1,6 +1,6 @@ ## Конструктор `Array` -Так как в конструкторе `Array` есть некоторая двусмысленность касающаяся его параметров, настоятельно рекомендуется при создании массивов всегда использовать синтаксис литеральной нотации — `[]`. +Так как конструктор `Array` не однозначен в плане вариантов перечисления его параметров, настоятельно рекомендуется при создании массивов всегда использовать синтаксис литеральной нотации — `[]`. [1, 2, 3]; // Результат: [1, 2, 3] new Array(1, 2, 3); // Результат: [1, 2, 3] @@ -9,17 +9,17 @@ new Array(3); // Результат: [] new Array('3') // Результат: ['3'] -В случае, когда в конструктор `Array` передаётся один аргумент и этот аргумент имеет тип `Number`, конструктор возвращает новый, *заполненный случайными значениями* (в зале подсказывают, _разреженный_), массив, имеющий длину равную значению переданного аргумента. Стоит заметить, что в этом случае будет установлено только свойство `length` нового массива, индексы массива фактически не будут проинициализированы. +В случае, когда конструктору `Array` передаётся только один аргумент, и этот аргумент имеет тип `Number`, конструктор возвращает новый, _разреженный_ (''прим. перев.'' — *заполненный случайными значениями*), массив, имеющий длину, равную значению переданного аргумента. Стоит заметить, что таким образом будет установлено лишь свойство `length` нового массива, а реальные индексы массива не будут инициализированы. var arr = new Array(3); arr[1]; // не определён, undefined 1 in arr; // false, индекс не был установлен -Поведение, которое позволяет изначально установить только размер массива может пригодиться лишь в нескольких случаях, таких как повторение строки, за счёт чего избегается использование цикла `for loop`. +Поведение, которое позволяет заранее установить размер массива может пригодиться лишь в нескольких случаях — таких как повторение строки, за счёт которого избегается использование кода `for loop`. new Array(count + 1).join(stringToRepeat); ### Заключение -Использование конструктора `Array` нужно избегать, насколько это возможно. Литералы определённо предпочтительнее — это краткая запись и она имеет более понятный синтаксис, так что при этом даже улучшается читабельность кода. +Нужно избегать использования конструктора `Array`. Литералы, определённо, более предпочтительны — это краткая запись, она имеет более «чистый» синтаксис и повышает читабельность кода. diff --git a/doc/ru/array/general.md b/doc/ru/array/general.md index 22c58b0c..9c8178ca 100644 --- a/doc/ru/array/general.md +++ b/doc/ru/array/general.md @@ -1,14 +1,14 @@ -##  Итерации по массивам и свойства +##  Перебор массивов и свойств объектов -Несмотря на то, что массивы в JavaScript являются объектами, нет достаточных оснований для использования [цикла `for in`](#object.forinloop) для итерации по элементам массива. Фактически, существует несколько весомых причин **против** использования `for in` в массивах. +Несмотря на то, что массивы в JavaScript являются объектами, достаточных оснований использовать [цикл `for in`](#object.forinloop) для перебора элементов массива **не существует**. Наоборот, существует достаточно хороших причин **против** использования `for in` с массивами. -> **Замечание:** Массивы в JavaScript **не** являются *ассоциативными массивами*. Для связывания ключей и значений в JavaScript есть только [объекты](#object.general). И при том, что ассоциативные массивы **сохраняют** заданный порядок, объекты **не** делают этого. +> **Замечание:** Массивы в JavaScript **не** являются *ассоциативными массивами*. Для связывания ключей и значений в JavaScript есть только [объекты](#object.general). При этом, ассоциативные массивы априори **сохраняют** заданный порядок свойств, объекты же **не** делают этого. -Во время выполнения `for in` циклически перебираются все свойства объекта, находящиеся в цепочке прототипов. Единственный способ исключить ненужные свойства — использовать [`hasOwnProperty`](#object.hasownproperty), а это **до 20 раз** медленнее обычного цикла `for`. +Поскольку во время выполнения `for in` циклически перебираются все свойства объекта, находящиеся в его цепочке прототипов, а единственный способ исключить ненужные свойства — использовать [`hasOwnProperty`](#object.hasownproperty) — такой цикл **до 20 раз** медленнее обычного цикла `for`. ### Итерирование -Для достижения лучшей производительности при итерации по массивам, лучше всего использовать обычный цикл `for`. +Для достижения лучшей производительности при переборе массивов, лучше всего использовать обычный цикл `for`. var list = [1, 2, 3, 4, 5, ...... 100000000]; for(var i = 0, l = list.length; i < l; i++) { @@ -17,13 +17,15 @@ В примере выше есть один дополнительный приём, с помощью которого кэшируется величина длины массива: `l = list.length`. -Несмотря на то, что свойство `length` определено в самом массиве, поиск этого свойства накладывает дополнительные расходы на каждой итерации цикла. Пусть в этом случае новые движки JavaScript теоретически **могут** применить оптимизацию, но нет никакого способа узнать, будет оптимизирован код на новом движке или нет. +Несмотря на то, что свойство `length` определено в самом массиве, поиск этого свойства в объекте накладывает дополнительные расходы на каждой итерации цикла. Пусть в этом случае новые движки JavaScript и **могут** теоретически применить оптимизацию, всё же нет способа точно предугадать, будет оптимизирован код на новом движке или нет. -Фактически, отсутствие кэширования может привести к выполнению цикла в **два раза медленнее**, чем при кэшировании длины +Фактически, цикл без кэширования может выполняться в **два раза медленнее**, нежели цикл с кэшированной длиной. + +''Прим. перев.'' — если вам нужно перебрать элементы в обратном порядке или порядок не имеет для вас значения, есть дополнительный способ (не самый быстрый, поскольку происходит сравнение без приведения типов) перебрать элементы массива: `var i = arr.length; while (i--) { ... }`. ### Свойство `length` -Хотя *геттер* свойства `length` просто возвращает количество элементов содежащихся в массиве, *сеттер* можно использовать для **обрезания** массива. +Хотя *геттер* свойства `length` всего лишь возвращает количество элементов содержащихся в массиве, *сеттер* оказывается удобно использовать для **урезания** массивов. var foo = [1, 2, 3, 4, 5, 6]; foo.length = 3; @@ -32,9 +34,9 @@ foo.length = 6; foo; // [1, 2, 3] -Присвоение свойству `length` меньшей величины урезает массив, однако присвоение большего значения не даст никакого эффекта. +Присвоение свойству `length` меньшей величины урезает массив, однако присвоение большего значения не даёт никакого эффекта. ### Заключение -Для оптимальной работы кода рекомендуется всегда использовать простой цикл `for` и кэшировать свойство `length`. Использование `for in` с массивами является признаком плохого кода, обладающего предпосылками к ошибкам и может привести к низкой скорости его выполнения. +Для оптимальной работы кода рекомендуется всегда использовать простой цикл `for` и кэшировать свойство `length`. Использование `for in` с массивами является признаком плохого кода, содержащего потенциальные ошибки, а также приводит к низкой скорости его выполнения. From 58b12b234d436331e785a9bca4ba9f5eb15fe266 Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Mon, 20 May 2013 00:15:48 +0200 Subject: [PATCH 20/41] types.equality --- doc/ru/index.json | 2 +- doc/ru/types/casting.md | 2 +- doc/ru/types/equality.md | 19 +++++++++---------- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/doc/ru/index.json b/doc/ru/index.json index e1789747..032c872b 100644 --- a/doc/ru/index.json +++ b/doc/ru/index.json @@ -55,7 +55,7 @@ ] }, { - "title": "Нативности", + "title": "Ядро", "dir": "core", "articles": [ "eval", diff --git a/doc/ru/types/casting.md b/doc/ru/types/casting.md index 287a9701..27ff01d3 100644 --- a/doc/ru/types/casting.md +++ b/doc/ru/types/casting.md @@ -1,6 +1,6 @@ ## Приведение типов -JavaScript *слабо типизированный* язык, поэтому *преобразование типов* будет применяться **везде**, где возможно. +JavaScript *слабо типизированный* язык, поэтому *преобразование типов* будет применяться **везде**, где это возможно. // Эти равенства — истинны new Number(10) == 10; // Number.toString() преобразуется diff --git a/doc/ru/types/equality.md b/doc/ru/types/equality.md index 0efb49c4..33a783d3 100644 --- a/doc/ru/types/equality.md +++ b/doc/ru/types/equality.md @@ -1,4 +1,4 @@ -##  Равенство и сравнение +##  Равенство и сравнения JavaScript умеет сравнивать значения объектов на равенство двумя различными способами. @@ -6,7 +6,7 @@ JavaScript умеет сравнивать значения объектов н Оператор сравнения состоит из **двух** символов равенства: `==` -*Слабая типизация* языка JavaScript подразумевает **приведение** обеих переменных к **одному типу** для того, чтобы сравнить два объекта. +Под *слабой типизацией* языка JavaScript подразумевается **приведение** обеих переменных к **одному типу** при сравнении двух объектов. "" == "0" // false 0 == "" // true @@ -18,15 +18,15 @@ JavaScript умеет сравнивать значения объектов н null == undefined // true " \t\r\n" == 0 // true -В таблице выше показаны результаты приведения типов и это главная причина почему использование `==` повсеместно считается плохой практикой: оно приводит к трудностям в отслеживании ошибок из-за сложных правил преобразования типов. +В таблице выше показаны результаты приведения типов в разных ситуациях и показана главная причина, по которой использование `==` повсеместно считается плохой практикой: благодаря непредсказуемости правил преобразования типов, оказывается трудно искать причины возникновения ошибок. -Кроме того, приведение типов во время сравнения также влияет на производительность; например, строка должна быть преобразована в число перед сравнением с другим числом. +Кроме того, приведение типов во время сравнения вынужденно влияет на производительность; например, строка должна быть преобразована в число перед сравнением с другим числом. ### Оператор строгого равенства Оператор строгого равенства состоит из **трёх** символов равенства: `===` -Он работает также как и обычный оператор сравнения, но оператор строгого равенства **не** выполняет приведение типов между операндами. +Он работает также как и обычный оператор сравнения, но оператор строгого равенства **не** выполняет приведения типов между своими операндами. "" === "0" // false 0 === "" // false @@ -38,11 +38,11 @@ JavaScript умеет сравнивать значения объектов н null === undefined // false " \t\r\n" === 0 // false -Результаты выше более понятны и позволяют быстрее выявлять ошибки в коде. Это в определённой степени улучшает код, а также дает прирост производительности в случае, если операнды имеют различные типы. +Результаты выше более предсказуемы и помогают быстрее выявлять ошибки в коде. Использование оператора в определённой степени делает код надёжнее, а кроме того обспечивает прирост производительности в случае, если типы операндов различны. ### Сравнение объектов -Хотя оба оператора `==` и `===` заявлены как операторы равенства, они ведут себя по-разному, когда хотя бы один из операндов является `Object`. +Хотя оба оператора `==` и `===` заявлены как операторы равенства, они ведут себя по-разному, когда хотя бы одним из операндов оказывается `Object`. {} === {}; // false new String('foo') === 'foo'; // false @@ -50,9 +50,8 @@ JavaScript умеет сравнивать значения объектов н var foo = {}; foo === foo; // true -Здесь оба операнда сравниваются на **идентичность**, а **не** на равенство; то есть, будет проверяться, являются ли операнды одним **экземпляром** объекта, так же как делает `is` в Python и сравниваются указатели в С. +Здесь оба операнда сравниваются на **идентичность**, а **не** на равенство; то есть, будет проверяться, являются ли операнды одним и тем же **экземпляром** объекта, так же как делает `is` в Python или сравниваются указатели в С. ### Заключение -Крайне рекомендуется использовать только операторы **строгого равенства**. В случае, когда намечается преобразование типов, нужно сделать [явное приведение](#types.casting) и не оставлять их на совести языковых хитростей с преобразованиями. - +Крайне рекомендуется использовать только операторы **строгого равенства**. В случаях, когда необходимо использовать преобразование типов, нужно сделать [явное приведение](#types.casting), а не оставлять его на совести нарочито мудрых языковых операций. From c4d6ae929bd8c7ce295ffeb4f3d1fec673e84329 Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Mon, 20 May 2013 00:55:25 +0200 Subject: [PATCH 21/41] types.typeof --- doc/ru/types/typeof.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/doc/ru/types/typeof.md b/doc/ru/types/typeof.md index 96cd7ed1..a1819f78 100644 --- a/doc/ru/types/typeof.md +++ b/doc/ru/types/typeof.md @@ -1,8 +1,8 @@ ## Оператор `typeof` -Оператор `typeof` (вместе с [`instanceof`](#types.instanceof)) — это, вероятно, самая большая недоделка в JavaScript, поскольку, похоже, он **поломан более чем полностью**. +Оператор `typeof` (вместе с [`instanceof`](#types.instanceof)) — это, вероятно, самая большая недоделка в JavaScript, поскольку выходит, что он **поломан почти полностью**. -Хотя `instanceof` еще имеет ограниченное применение, `typeof` на самом деле имеет *только один* практический случай применения, который при всём при этом **не** является проверкой типа объекта. +Хотя `instanceof` используется достаточно редко, `typeof` вообще имеет один практический случай применения, который при всём при этом неожиданно **не** оказывается проверкой типа объекта. > **Замечаение:** Хотя для вызова `typeof` также можно использовать синтаксис функции, т.е. `typeof(obj)`, на самом деле это не функция. Двойные круглые скобки будут работать нормально и возвращаемое значение будет использоваться как операнд оператора `typeof`. Но функции `typeof` — **не существует**. @@ -26,13 +26,13 @@ {} Object object new Object() Object object -В таблице выше *Тип* представляет собой значение, возвращаемое оператором `typeof`. Как хорошо видно, это значение может быть абсолютно любым, но не логичным результатом. +В таблице выше, в колонке *Тип* приводится значение, возвращаемое оператором `typeof` для указанного объекта. Как хорошо заметно, это значение может быть чем угодно, но не ожидаемым результатом. -*Класс* представляет собой значение внутреннего свойства `[[Class]]` объекта. +В колонке *Класс* приведено значение внутреннего свойства объекта `[[Class]]`. > **Из спецификации:** Значением `[[Class]]` может быть одна из следующих строк: `Arguments`, `Array`, `Boolean`, `Date`, `Error`, `Function`, `JSON`, `Math`, `Number`, `Object`, `RegExp`, `String`. -Для того, чтобы получить значение `[[Class]]` необходимо вызвать метод `toString` у `Object.prototype`. +Чтобы получить значение `[[Class]]` нужно применить к объекту метод `toString` из `Object.prototype`. ### Класс объекта @@ -46,19 +46,19 @@ is('String', 'test'); // true is('String', new String('test')); // true -В примере выше `Object.prototype.toString` вызывается со значением [this](#function.this), являющимся объектом, значение `[[Class]]` которого нужно получить. +В примере выше `Object.prototype.toString` вызывается со значением [this](#function.this), ссылающимся на объект, значение `[[Class]]` которого нужно получить. -> **ES5 Замечание:** Для удобства в ECMAScript 5 возвращаемое значение `Object.prototype.toString `для `null` и `undefined` было изменено с `Object` на `Null` и `Undefined` соответственно. +> **ES5 Замечание:** Для удобства, в ECMAScript 5 возвращаемое значение `Object.prototype.toString` для `null` и `undefined` было изменено с `Object` на `Null` и `Undefined` соответственно. ### Проверка переменных на определённость typeof foo !== 'undefined' -Выше проверяется, было ли `foo` действительно объявлено или нет; просто обращение к переменной приведёт к `ReferenceError`. Это единственное, чем на самом деле полезен `typeof`. +Выше проверяется, было ли `foo` действительно объявлено или нет; обычное обращение к несуществующей переменной приведёт к `ReferenceError`. И это единственное, чем на самом деле полезен `typeof`. ### Заключение -Для проверки типа объекта настоятельно рекомендуется использовать` Object.prototype.toString` — это единственный надежный способ. Как показано выше в таблице типов, некоторые возвращаемые `typeof` значения не определены в спецификации: таким образом, они могут отличаться в различных реализациях. +Для проверки типа объекта настоятельно рекомендуется использовать `Object.prototype.toString` — это единственный надежный способ для этих действий. Как показано выше в таблице типов, некоторые значения, возвращаемые `typeof`, не описаны в спецификации: таким образом, они могут отличаться в различных реализациях. -Кроме случая проверки, была ли определена переменная, `typeof` следует избегать **во что бы то ни стало**. +Кроме случая проверки, была ли определена переменная, `typeof` следует избегать. From 71efc6098c061f3c3eb2448351b94d112c192fb3 Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Wed, 22 May 2013 12:24:41 +0200 Subject: [PATCH 22/41] minor typeof corrections --- doc/ru/types/typeof.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/ru/types/typeof.md b/doc/ru/types/typeof.md index a1819f78..cd681e3c 100644 --- a/doc/ru/types/typeof.md +++ b/doc/ru/types/typeof.md @@ -1,10 +1,10 @@ ## Оператор `typeof` -Оператор `typeof` (вместе с [`instanceof`](#types.instanceof)) — это, вероятно, самая большая недоделка в JavaScript, поскольку выходит, что он **поломан почти полностью**. +Оператор `typeof` (вместе с [`instanceof`](#types.instanceof)) — это, вероятно, самая большая недоделка в JavaScript, поскольку с течением опыта выясняется, что он **поломан разве что не полностью**. -Хотя `instanceof` используется достаточно редко, `typeof` вообще имеет один практический случай применения, который при всём при этом неожиданно **не** оказывается проверкой типа объекта. +Хотя `instanceof` используется достаточно редко, `typeof` вообще имеет только один практический случай применения, который при всём при этом, неожиданно,.. **не** оказывается проверкой типа объекта. -> **Замечаение:** Хотя для вызова `typeof` также можно использовать синтаксис функции, т.е. `typeof(obj)`, на самом деле это не функция. Двойные круглые скобки будут работать нормально и возвращаемое значение будет использоваться как операнд оператора `typeof`. Но функции `typeof` — **не существует**. +> **Замечаение:** Хотя для вызова `typeof` также можно использовать синтаксис функции, т.е. `typeof(obj)`, на самом деле это вовсе не функция. Да — двойные круглые скобки будут работать нормально и возвращаемое значение будет использоваться как операнд оператора `typeof`, но функции `typeof` — **не существует**. ### Таблица типов JavaScript @@ -26,7 +26,7 @@ {} Object object new Object() Object object -В таблице выше, в колонке *Тип* приводится значение, возвращаемое оператором `typeof` для указанного объекта. Как хорошо заметно, это значение может быть чем угодно, но не ожидаемым результатом. +В этой таблице в колонке *Тип* приводится значение, возвращаемое оператором `typeof` для указанного объекта. Как хорошо заметно, это значение может оказаться чем угодно, но не ожидавшимся результатом. В колонке *Класс* приведено значение внутреннего свойства объекта `[[Class]]`. @@ -54,11 +54,11 @@ typeof foo !== 'undefined' -Выше проверяется, было ли `foo` действительно объявлено или нет; обычное обращение к несуществующей переменной приведёт к `ReferenceError`. И это единственное, чем на самом деле полезен `typeof`. +Этим выражением удостоверяется, была ли переменная `foo` действительно объявлена; явное обращение к несуществующей переменной в коде породит `ReferenceError`. Вот это единственное, чем на самом деле полезен `typeof`. ### Заключение -Для проверки типа объекта настоятельно рекомендуется использовать `Object.prototype.toString` — это единственный надежный способ для этих действий. Как показано выше в таблице типов, некоторые значения, возвращаемые `typeof`, не описаны в спецификации: таким образом, они могут отличаться в различных реализациях. +Для проверки типа объекта настоятельно рекомендуется использовать `Object.prototype.toString` — это единственный и надежный способ. Как показано выше в таблице типов, некоторые значения, возвращаемые `typeof`, не описаны в спецификации: таким образом, они могут отличаться в различных реализациях. Кроме случая проверки, была ли определена переменная, `typeof` следует избегать. From 57a8f74e56e8849a1385d576a2e6093e0f88e979 Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Wed, 22 May 2013 15:14:19 +0200 Subject: [PATCH 23/41] types.* fixed --- doc/ru/types/casting.md | 26 +++++++++++++------------- doc/ru/types/instanceof.md | 8 ++++---- doc/ru/types/typeof.md | 12 ++++++------ 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/doc/ru/types/casting.md b/doc/ru/types/casting.md index 27ff01d3..f481897f 100644 --- a/doc/ru/types/casting.md +++ b/doc/ru/types/casting.md @@ -1,36 +1,36 @@ ## Приведение типов -JavaScript *слабо типизированный* язык, поэтому *преобразование типов* будет применяться **везде**, где это возможно. +JavaScript — *слабо типизированный* язык, поэтому *преобразование типов* будет применяться **везде**, где оно возможно. - // Эти равенства — истинны + // Эти равенства возвращают true new Number(10) == 10; // Number.toString() преобразуется // обратно в число - 10 == '10'; // Strings преобразуется в Number + 10 == '10'; // Строки преобразуются в Number 10 == '+10 '; // Ещё чуток строко-безумия 10 == '010'; // и ещё isNaN(null) == false; // null преобразуется в 0, // который, конечно же, не NaN - // Эти равенства — ложь + // Эти равенства возвращают false 10 == 010; 10 == '-10'; > **ES5 Замечание:** Числовые литералы, которые начинаются с 0 интерпретируются как восьмеричные (Base 8). В ECMAScript 5 strict mode **удалена** поддержка восьмеричной системы. -Для того, чтобы избежать этого, **настоятельно** рекомендуется использовать [оператор строгого равенства](#types.equality). Впрочем, хотя это и позволяет избежать многих распространенных ошибок, существует ещё много дополнительных вопросов, которые возникают из-за слабости типизации JavaScript. +Для того, чтобы избежать такого поведения, **настоятельно** рекомендуется использовать [оператор строгого равенства](#types.equality). Впрочем, хотя это и позволяет избежать многих распространенных ошибок, существует ещё много дополнительных проблем, возникающих по вине слабой типизации JavaScript. ### Конструкторы встроенных типов -Конструкторы встроенных типов, например, `Number` и `String` ведут себя различным образом, в зависимости от того вызываются они с ключевым словом `new` или без. +Конструкторы встроенных типов, например, `Number` и `String` ведут себя различным образом, в зависимости от того, вызываются они с ключевым словом `new` или без. - new Number(10) === 10; // False, Object и Number - Number(10) === 10; // True, Number и Number - new Number(10) + 0 === 10; // True, из-за неявного преобразования + new Number(10) === 10; // False: Object и Number + Number(10) === 10; // True: Number и Number + new Number(10) + 0 === 10; // True: из-за неявного преобразования -Использование встроенных типов, например `Number`, с конструктором создаёт новый экземпляр объекта Number, но использование без ключевого слова `new` создаст функцию `Number`, которая будет вести себя как конвертер. +Использование встроенных типов, таких как `Number`, с конструктором, создаёт новый экземпляр объекта `Number`, но использование без ключевого слова `new` создаёт функцию `Number`, которая будет вести себя в равенствах как конвертер. -Кроме того, присутствие литералов или переменных, которые не являются объектами приведет к еще большему насилию над типами. +Кроме того, присутствие в равенствах литералов или переменных, которые не являются объектами, повлечёт лишь более серьёзное насилие над типами. Лучший вариант — это **явное** приведение к одному из трех возможных типов. @@ -44,11 +44,11 @@ JavaScript *слабо типизированный* язык, поэтому * +'10' === 10; // true -Используя **унарный** оператор плюс можно преобразовать значение в число. +Используя **унарный** оператор плюс, можно преобразовать значение в число. ### Приведение к булеву типу -Используя оператор **not** (**`!`**) дважды, значение может быть приведено к логическому (булеву) типу. +Использование оператора **not** (`!`) дважды поможет привести значение к логическому (булеву) типу. !!'foo'; // true !!''; // false diff --git a/doc/ru/types/instanceof.md b/doc/ru/types/instanceof.md index 76d770c9..060eb8a7 100644 --- a/doc/ru/types/instanceof.md +++ b/doc/ru/types/instanceof.md @@ -1,6 +1,6 @@ ## Оператор `instanceof` -Оператор `instanceof` сравнивает конструкторы двух операндов. Это полезно только когда сравниваются пользовательские объекты. Использование на встроенных типах почти так же бесполезно, как и [оператор typeof](#types.typeof). +Оператор `instanceof` сравнивает конструкторы двух операндов. Работает это только тогда, когда сравниваются пользовательские объекты. Использование же на встроенных типах почти так же бесполезно, как и [оператор typeof](#types.typeof). ### Сравнение пользовательских объектов @@ -11,7 +11,7 @@ new Bar() instanceof Bar; // true new Bar() instanceof Foo; // true - // Всего лишь присваиваем Bar.prototype объект функции Foo, + // Банально присваиваем Bar.prototype объект функции Foo, // но не экземпляра Foo Bar.prototype = Foo; new Bar() instanceof Foo; // false @@ -24,9 +24,9 @@ 'foo' instanceof String; // false 'foo' instanceof Object; // false -Здесь надо отметить одну важную вещь: `instanceof` не работает на объектах, которые происходят из разных контекстов JavaScript (например, из различных документов в web-браузере), так как их конструкторы и правда не будут конструкторами *тех самых* объектов. +Здесь надо отметить одну важную вещь: `instanceof` не работает на объектах, которые происходят из разных контекстов JavaScript (например, из различных документов в web-браузере), так как их конструкторы и правда не будут конструкторами *тех же самых* объектов. ### Заключение -Оператор `instanceof` должен использоваться **только** при обращении к пользовательским объектам, происходящим из одного контекста JavaScript. Так же, как и в случае оператора `typeof`, любое другое использование необходимо **избегать**. +Оператор `instanceof` должен использоваться **только** при обращении к пользовательским объектам, происходящим из одного контекста JavaScript. Так же, как и в случае оператора `typeof`, любого другого использования `instanceof` необходимо **избегать**. diff --git a/doc/ru/types/typeof.md b/doc/ru/types/typeof.md index cd681e3c..75a03838 100644 --- a/doc/ru/types/typeof.md +++ b/doc/ru/types/typeof.md @@ -1,8 +1,8 @@ ## Оператор `typeof` -Оператор `typeof` (вместе с [`instanceof`](#types.instanceof)) — это, вероятно, самая большая недоделка в JavaScript, поскольку с течением опыта выясняется, что он **поломан разве что не полностью**. +Оператор `typeof` (вместе с [`instanceof`](#types.instanceof)) — это, вероятно, самая большая недоделка в JavaScript, поскольку с накоплением опыта выясняется, что он **поломан, разве что не полностью**. -Хотя `instanceof` используется достаточно редко, `typeof` вообще имеет только один практический случай применения, который при всём при этом, неожиданно,.. **не** оказывается проверкой типа объекта. +При том, число поводов для применения `instanceof` ограничено, `typeof` вообще имеет *один-единственный* практический случай применения, который при всём при этом, неожиданно,.. **не** оказывается проверкой типа объекта. > **Замечаение:** Хотя для вызова `typeof` также можно использовать синтаксис функции, т.е. `typeof(obj)`, на самом деле это вовсе не функция. Да — двойные круглые скобки будут работать нормально и возвращаемое значение будет использоваться как операнд оператора `typeof`, но функции `typeof` — **не существует**. @@ -32,7 +32,7 @@ > **Из спецификации:** Значением `[[Class]]` может быть одна из следующих строк: `Arguments`, `Array`, `Boolean`, `Date`, `Error`, `Function`, `JSON`, `Math`, `Number`, `Object`, `RegExp`, `String`. -Чтобы получить значение `[[Class]]` нужно применить к объекту метод `toString` из `Object.prototype`. +Чтобы получить значение `[[Class]]`, нужно применить к объекту метод `toString` из `Object.prototype`. ### Класс объекта @@ -54,11 +54,11 @@ typeof foo !== 'undefined' -Этим выражением удостоверяется, была ли переменная `foo` действительно объявлена; явное обращение к несуществующей переменной в коде породит `ReferenceError`. Вот это единственное, чем на самом деле полезен `typeof`. +Данное выражение позволяет удостовериться, была ли объявлена переменная `foo`; явное обращение к несуществующей переменной в коде породит `ReferenceError`. И вот это — единственное, чем на самом деле полезен `typeof`. ### Заключение -Для проверки типа объекта настоятельно рекомендуется использовать `Object.prototype.toString` — это единственный и надежный способ. Как показано выше в таблице типов, некоторые значения, возвращаемые `typeof`, не описаны в спецификации: таким образом, они могут отличаться в различных реализациях. +Для проверки типа объекта настоятельно рекомендуется использовать `Object.prototype.toString` — это единственный и надежный способ. Как показано выше в таблице типов, некоторые значения, возвращаемые `typeof`, не описаны в спецификации: следовательно, они могут различаться в разных реализациях. -Кроме случая проверки, была ли определена переменная, `typeof` следует избегать. +За исключением случаев проверки, была ли определена переменная, использования `typeof` следует избегать. From 9a3a1a30f1db901ba832628146e8a6915325d9f2 Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Wed, 22 May 2013 17:42:59 +0200 Subject: [PATCH 24/41] part of core.* --- doc/ru/core/eval.md | 12 ++++++------ doc/ru/core/undefined.md | 18 ++++++++++-------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/doc/ru/core/eval.md b/doc/ru/core/eval.md index 12e494ce..0fd5f762 100644 --- a/doc/ru/core/eval.md +++ b/doc/ru/core/eval.md @@ -1,6 +1,6 @@ ## Почему нельзя использовать `eval` -Функция `eval` выполняет строку кода JavaScript в локальной области видимости. +Функция `eval` исполняет хранящийся в строке код JavaScript в локальной области видимости. var foo = 1; function test() { @@ -11,7 +11,7 @@ test(); // 3 foo; // 1 -Но `eval` исполняется в локальной области видимости только тогда, когда он вызывается **напрямую** *и при этом* имя вызываемой функции именно `eval`. +Однако, `eval` исполняется в локальной области видимости тогда и только тогда, когда он вызывается явно *и при этом* имя вызывающейся функции идентично `eval` (''прим. перев.'' — ох!). var foo = 1; function test() { @@ -23,17 +23,17 @@ test(); // 2 foo; // 3 -**Любой ценой** избегайте использования функции `eval`. 99.9% «трюков» с её «использованием» могут решаться **без её участия**. +**Любой ценой** избегайте использования функции `eval`. 99.9% «трюков» с её «использованием» могут легко решаться и **без её участия**. ### `eval` под прикрытием -Обе [функции работы с интервалами времени](#other.timeouts) `setTimeout` и `setInterval` могут принимать строку в качестве первого аргумента. Эта строка **всегда** будет выполняться в глобальной области видимости, поскольку `eval` в этом случае вызывается *не напрямую*. +Обе [функции работы с интервалами времени](#other.timeouts) `setTimeout` и `setInterval` могут принимать строку в качестве первого аргумента. Эта строка **всегда** будет выполняться в глобальной области видимости, поскольку `eval` в этом случае вызывается *неявно*. ### Проблемы с безопасностью -Кроме всего прочего, функция `eval` — это проблема в безопасности, поскольку исполняется **любой** переданный в неё код; **никогда** не следует использовать её со строками из неизвестных или недоверительных источников. +Кроме всего прочего, функция `eval` — это проблема в безопасности, поскольку она выполняет **любой** переданный в неё код; **никогда** не следует использовать её со строками из неизвестных или недоверительных источников. ### Заключение -Никогда не стоит использовать `eval`: любое применение такого кода поднимает вопросы о качестве его работы, производительности и безопасности. Если вдруг для работы вам необходим `eval`, эта часть должна тут же ставиться под сомнение и **не** должна использоваться в первую очередь — необходимо найти *лучший способ* , которому не требуются вызовы `eval`. +Использовать `eval` не стоит никогда: любой код с участием этой функции автоматически порождает вопросы о качестве его работы, производительности и безопасности. Если вдруг для работы вам необходим `eval`, эта часть кода должна тут же ставиться под сомнение и в первую очередь *исключаться** из проекта — необходимо найти *лучший способ*, которому не требуются вызовы `eval`. diff --git a/doc/ru/core/undefined.md b/doc/ru/core/undefined.md index 326f397b..c3fb619b 100644 --- a/doc/ru/core/undefined.md +++ b/doc/ru/core/undefined.md @@ -1,23 +1,25 @@ ## `undefined` и `null` -В JavaScript есть два отдельных типа для представления `ничего`, при этом более полезным из них является `undefined`. +В JavaScript есть два отдельных типа для описания *ничего* — `null` и `undefined`, при этом последний из них более полезен. -### Тип `undefined` +### Значение `undefined` `undefined` — это тип с единственным возможным значением: `undefined`. -Кроме этого, в языке определена глобальная переменная со значением `undefined`, и эта переменная так и называется — `undefined`. Не являясь константой, она не является и ключевым словом. Из этого следует, что её значение можно с лёгкостью переопределить. +Кроме этого, в языке определена глобальная переменная со значением `undefined`, причём эта переменная так и называется — `undefined`. Не являясь константой, она не является и ключевым словом. Из этого следует, что её значение можно с лёгкостью переопределить. -> **ES5 Замечание:** в ECMAScript 5 переменная `undefined` **больше не** *доступна на запись* в strict-режиме, однако она всё так же может быть перегружена по имени, например - функцией с именем `undefined`. +> **ES5 Замечание:** в ECMAScript 5 переменная `undefined` **уже не** *доступна на запись* в strict-режиме, однако она всё так же может быть перегружена по имени, например - функцией с именем `undefined`. -Несколько случаев, когда возвращается `undefined`: +Список случаев, когда код возвращает значение `undefined`: - - При попытке доступа к глобальной переменной `undefined` (если она не изменена). + - При попытке доступа к глобальной переменной `undefined` (если она не была переопределена). + - При попытке доступа к переменной, которая *ещё не была* инициализирована каким-либо значением. - Неявный возврат из функции при отсутствии в ней оператора `return`. - - Из операторов `return`, которые ничего не возвращают. + - Из операторов `return`, которые не возвращают явных значений. - В результате поиска несуществующего свойства у объекта (и доступа к нему). - - Параметры, которые не были переданы в функцию явно. + - При доступе к аргументам функции, которые явно не были в неё переданы. - При доступе ко всему, чьим значением является `undefined`. + - В результате вычисления любого выражения в форме `void(выражение)`. ### Обработка изменений значения `undefined` From 812a04073798488091aafbc60b505df784618e41 Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Thu, 23 May 2013 12:47:39 +0200 Subject: [PATCH 25/41] core translation --- doc/ru/core/delete.md | 76 ++++++++++++++++++++++++++++++++++++++++ doc/ru/core/semicolon.md | 18 +++++----- doc/ru/core/undefined.md | 26 +++++++------- 3 files changed, 98 insertions(+), 22 deletions(-) create mode 100644 doc/ru/core/delete.md diff --git a/doc/ru/core/delete.md b/doc/ru/core/delete.md new file mode 100644 index 00000000..7d083281 --- /dev/null +++ b/doc/ru/core/delete.md @@ -0,0 +1,76 @@ +## Оператор `delete` + +Если кратко — в JavaScript невозможно удалить глобальную переменную или функцию или какую-либо другую сущность, у которой установлен атрибут `DontDelete`. + +### Глобальный код и код внутри функций + +Когда переменная или функция определена в глобальной области видимости или в [области видимости функции](#function.scopes), её судьба предопределена: (''прим. перев.'' — где-то внутри движка JavaScript) она является свойством либо объекта Activation, либо объекта Global. Каждое из таких свойств имеет по набору атрибутов, среди которых присутствует и `DontDelete`. Переменные и объявления функций, обнаруженные движком в глобальной области или в коде функции, создаются с атрибутом `DontDelete` и, посему, не могут быть удалены. + + // глобальная переменная: + var a = 1; // установлен DontDelete + delete a; // false + a; // 1 + + // обычная функция: + function f() {} // установлен DontDelete + delete f; // false + typeof f; // "function" + + // переопределение не помогает: + f = 1; + delete f; // false + f; // 1 + +### Установленные пользователем свойства + +Свойства, установленные явно, могут быть удалены без помех: + + // явно установим свойства: + var obj = {x: 1}; + obj.y = 2; + delete obj.x; // true + delete obj.y; // true + obj.x; // undefined + obj.y; // undefined + +В приведённом примере свойства `obj.x` и `obj.y` могут быть удалены, поскольку у них отсутствует атрибут `DontDelete`. По этой же причине работает и пример ниже: + + // работает нормально, но не в IE + var GLOBAL_OBJECT = this; + GLOBAL_OBJECT.a = 1; + a === GLOBAL_OBJECT.a; // true - просто глобальная переменная + delete GLOBAL_OBJECT.a; // true + GLOBAL_OBJECT.a; // undefined + +Здесь, чтобы удалить `a`, мы используем трюк. В этом коде [`this`](#function.this) ссылается на объект Global и мы явно описываем переменную `a` под видом его свойства, что позволяет нам её успешно удалить. + +В IE (по крайней мере, с 6-го по 8-й), есть парочка багов, из-за которых такой код не заработает. + +### Аргументы функций и встроенные свойства + +Обычные аргументы функций, [объект `arguments`](#function.arguments), а также встроенные свойства, объединены общей особенностью: у них у всех установен атрибут `DontDelete`. + + // аргументы функций и свойства: + (function (x) { + + delete arguments; // false + typeof arguments; // "object" + + delete x; // false + x; // 1 + + function f(){} + delete f.length; // false + typeof f.length; // "number" + + })(1); + +### Хост-объекты + +(''прим. перев.'' — Хост-объекты — объекты, которые, в неком окружении, дополняют функциональность языка JavaScript, не являясь частью его спецификации. В случае браузера это объекты `window`, `document`, `setTimeout` и т.п.) + +Поведение оператора `delete` может быть абсолютно непредсказуемым при применении его к хост-объектам. С позволения спецификации, хост-объекты вольны вести себя как им только вздумается. + +### Заключение + +Оператор `delete` часто ведёт себя непредсказуемо и надёжно может использоваться только для удаления пользовательских свойств обычных объектов. \ No newline at end of file diff --git a/doc/ru/core/semicolon.md b/doc/ru/core/semicolon.md index 87e56993..08de7b08 100644 --- a/doc/ru/core/semicolon.md +++ b/doc/ru/core/semicolon.md @@ -1,8 +1,8 @@ ## Автоматическая вставка точек с запятой -Хоть JavaScript и имеет синтаксис, подобный языкам семейства C, он при этом **не** принуждает вас ставить точки с запятой в исходном коде — вы всегда можете их опустить. +Несмотря на то, что JavaScript имеет синтаксис, подобный языкам семейства C, он никоим образом **не принуждает** вас ставить точки с запятой в исходном коде — вы всегда вольны их опустить. -При этом JavaScript — не язык без точек с запятой, они на самом деле нужны ему, чтобы он мог разобраться в вашем коде. Поэтому парсер JavaScript **автоматически** вставляет их в те места, где сталкивается с ошибкой парсинга из-за их отсутствия. +При этом JavaScript — вовсе не язык с полным отсутствием точек с запятой: они на самом деле нужны ему для того, чтобы он мог разобраться в вашем коде. Поэтому парсер JavaScript **автоматически** вставляет их в те места, где сталкивается с ошибкой парсинга по причине их отсутствия. var foo = function() { } // ошибка разбора, ожидается точка с запятой @@ -14,7 +14,7 @@ }; // ошибки нет, парсер продолжает test() -Автоматическая вставка точек с запятой считается одним из **наибольших** упущений в проекте языка, поскольку она *может* изменить поведение кода. +Автоматическая вставка точек с запятой считается одним из **наибольших** упущений в проекте языка, поскольку она *действительно может* влиять на поведение кода. ### Как это работает @@ -22,7 +22,7 @@ (function(window, undefined) { function test(options) { - log('тестируем!') + log('проверяем!') (options.list || []).forEach(function(i) { @@ -78,22 +78,22 @@ })(window); //<- вставлена -> **Замечание:** Парсер JavaScript некорректно обрабатывает оператор `return`, за которым следует новая строка; кстати, причина может быть и не в автоматической вставке точек с запятой, но это в любом случае нежелательный побочный эффект +> **Замечание:** Парсер JavaScript некорректно обрабатывает оператор `return`, за которым следует новая строка; Причина может быть и не в автоматической вставке точек с запятой, но без сомнений, это нежелательный побочный эффект. -Парсер радикально подменил поведение изначального кода, а в определённых случаях он сделал **абсолютно неправильные выводы**. +Парсер радикально поменял поведение изначального кода, а в определённых случаях он вообще сделал **абсолютно неправильные выводы**. ### «Висящие» скобки -Если парсер встречает «висящую» скобку, то он **не** вставляет точку с запятой. +Если парсер встречает «висящую» открывающую скобку, то он **не** вставляет точку с запятой. log('тестируем!') (options.list || []).forEach(function(i) {}) -Такой код трасформируется в строку +Такой код трасформируется в одну склеенную строку. log('тестируем!')(options.list || []).forEach(function(i) {}) -**Чрезвычайно** высоки шансы, что `log` возращает **не** функцию; таким образом, эта строка вызовет `TypeError` с сообщением о том, что `undefined не является функцией`. +**Чрезвычайно** высоки шансы, что `log` **не** возращает *никаких* функций; таким образом, выполнение кода с такой строкой породит `TypeError` с сообщением о том, что `undefined не является функцией`. ### Заключение diff --git a/doc/ru/core/undefined.md b/doc/ru/core/undefined.md index c3fb619b..578c2f2a 100644 --- a/doc/ru/core/undefined.md +++ b/doc/ru/core/undefined.md @@ -15,19 +15,19 @@ - При попытке доступа к глобальной переменной `undefined` (если она не была переопределена). - При попытке доступа к переменной, которая *ещё не была* инициализирована каким-либо значением. - Неявный возврат из функции при отсутствии в ней оператора `return`. - - Из операторов `return`, которые не возвращают явных значений. - - В результате поиска несуществующего свойства у объекта (и доступа к нему). - - При доступе к аргументам функции, которые явно не были в неё переданы. - - При доступе ко всему, чьим значением является `undefined`. - - В результате вычисления любого выражения в форме `void(выражение)`. + - Из оператора `return`, который не возвращает явного значения. + - В результате поиска несуществующего свойства у объекта (и/или доступа к нему). + - При попытке доступа к аргументу функции, который не был передан в неё явно. + - При попытке доступа ко всему, чьим значением является `undefined`. + - В результате вычисления любого выражения, соответствующего форме `void(выражение)`. -### Обработка изменений значения `undefined` +### Защита от потенциальных изменений значения `undefined` -Поскольку глобальная переменная `undefined` содержит копию настоящего *значения* `undefined`, присвоение этой переменной нового значения **не** изменяет значения *типа* `undefined`. +Поскольку глобальная переменная `undefined` содержит копию реального *значения* `undefined`, присвоение этой переменной нового значения **не** изменяет значения у *типа* `undefined`. -Но при этом, чтобы сравнить что-либо со *значением* `undefined` прежде нужно получить значение самой *переменной* `undefined`. +Получается, чтобы проверить нечто с типом `undefined` на соответствие значению `undefined`, прежде нужно узнать изначальное значение переменной `undefined`. -Чтобы защитить код от переопределения переменной `undefined`, часто используется техника [анонимной обёртки](#function.scopes), которая использует отсутствующий аргумент. +Чтобы защитить код от переопределения переменной `undefined`, часто используют технику [анонимной обёртки](#function.scopes), в которую добавляют аргумент и намеренно не передают его значение. var undefined = 123; (function(something, foo, undefined) { @@ -45,11 +45,11 @@ })('Hello World', 42); -Единственная разница между этими вариантами в том, что последняя версия будет больше на 4 байта при минификации, а в первом случае внутри анонимной обёртки нет дополнительного оператора `var`. +Единственная разница между этими вариантами в том, что последняя версия будет больше на 4 байта при минификации, и в первом случае внутри анонимной обёртки нет дополнительного оператора `var`. -### Использование `null` +### Применение `null` -Хотя `undefined` в контексте языка JavaScript чаще используется в качестве традиционного *null*, настоящий `null` (и тип и литерал) является в большей или меньшей степени просто другим типом данных. +Хотя `undefined` в контексте языка JavaScript чаще используется в роли традиционного *null*, настоящий `null` (и тип и литерал) является, в некоторой степени, просто другим типом данных. -Он используется во внутренних механизмах JavaScript (например для определения конца цепочки прототипов засчёт присваивания `Foo.prototype = null`). Но в большинстве случаев тип `null` может быть заменён на `undefined`. +Он используется во внутренних механизмах JavaScript (в случаях вроде установки конца цепочки прототипов через присваивание `Foo.prototype = null`). Но почти во всех случаях тип `null` может быть заменён на `undefined`. From 2b1e3ff085c9cff8216f7d3819ee5b7ee13a061e Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Thu, 23 May 2013 16:08:22 +0200 Subject: [PATCH 26/41] other.* translation, a final thing --- doc/ru/other/timeouts.md | 59 ++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/doc/ru/other/timeouts.md b/doc/ru/other/timeouts.md index b9b27d29..5d3b26f3 100644 --- a/doc/ru/other/timeouts.md +++ b/doc/ru/other/timeouts.md @@ -1,17 +1,17 @@ ### `setTimeout` и `setInterval` -Поскольку JavaScript поддерживает асинхронность, есть возможность запланировать выполнение функции, используя функции `setTimeout` и `setInterval`. +В виду того, что JavaScript умеет совершать асинхронные операции, есть возможность запланировать отложенное выполнение пользовательской функции, используя предназначенные для этого функции `setTimeout` и `setInterval`. -> **Замечание:** Таймауты **не** являются частью стандарта ECMAScript, они были разработаны как раздел спецификации[DOM][1]. +> **Замечание:** Таймауты **не** являются частью стандарта ECMAScript, они были разработаны будучи частью спецификации[DOM][1]. function foo() {} var id = setTimeout(foo, 1000); // возвращает число > 0 -Функция `setTimeout` возвращает идентификатор таймаута и планирует вызвать `foo` через, **примерно**, тысячу миллисекунд. Фунция `foo` при этом будет вызвана ровно **один** раз. +Функция `setTimeout` возвращает идентификатор назначенного таймаута и откладывает вызов `foo` на, **примерно**, тысячу миллисекунд. Фунция `foo`, при этом, будет вызвана только **один** раз. В зависимости от разрешения таймера в используемом для запуска кода движке JavaScript, а также с учётом того, что JavaScript является однопоточным языком и посторонний код может заблокировать выполнение потока, нет **никакой** гарантии, что переданный код будет выполнен ровно через указанное в вызове `setTimeout` время. -Переданная первым параметром функция будет вызвана как *глобальный объект* — это значит, что оператор [`this`](#function.this) в вызываемой функции будет ссылаться на этот самый объект. +Функция, переданная первым параметром, будет вызвана в контексте *глобального объекта* — это значит, что оператор [`this`](#function.this) в вызываемой функции будет ссылаться на тот самый глобальный объект. function Foo() { this.value = 42; @@ -26,54 +26,67 @@ > **Замечание:** Поскольку `setTimeout` принимает **объект функции** в качестве первого параметра, часто совершается ошибка в использовании `setTimeout(foo(), 1000)`, при котором будет использоваться **возвращённое значение** от вызова функции `foo`, а **не** вызываться сама функция `foo`. В большинстве случаев ошибка пройдёт незамеченной, а в случае если функция возвращает `undefined`, `setTimeout` вообще **не** породит никакой ошибки. -### Поочерёдные вызовы с использованием `setInterval` +### Очереди вызовов с `setInterval` -`setTimeout` вызывает функцию единожды; `setInterval` — как и предполагает название — вызывает функцию **каждые** `X` миллисекунд. И его использование не рекомендуется. +`setTimeout` вызывает функцию единожды; `setInterval` — как и предполагает название — вызывает функцию **каждые** `X` миллисекунд. И использовать его не рекомендуется. -В то время, когда исполняющийся код будет блокироваться во время вызова с таймаутом, `setInterval` будет продолжать планировать последующие вызовы переданной функции. Это может (особенно в случае небольших интервалов) повлечь за собой выстраивание вызовов функций в очередь. +В то время как, если применять `setTimeout`, исполняющийся в данный момент код будет блокировать запланированный — `setInterval` будет продолжать планировать последующие вызовы переданной функции. Это может, особенно при указании небольших интервалов, повлечь за собой выстраивание функций в ожидающую очередь. function foo(){ - // что-то, что выполняется одну секунду + // что-то, выполняющееся одну секунду или более } setInterval(foo, 1000); -В приведённом коде `foo` выполнится один раз и заблокирует этим главный поток на одну секунду. +В приведённом примере `foo` в первый же раз заблокирует своим процессом главный поток на одну секунду. Пока `foo` блокирует код, `setInterval` продолжает планировать последующие её вызовы. Теперь, когда первая `foo` закончила выполнение, в очереди будут уже **десять** ожидающих выполнения вызовов `foo`. ### Разбираемся с потенциальной блокировкой кода -Самый простой и контролируемый способ — использовать `setTimeout` внутри самой функции. +Самый простой и наиболее легко контролируемый способ — использовать `setTimeout` внутри такой функции. function foo(){ - // что-то, выполняющееся одну секунду + // что-то, выполняющееся одну секунду или более setTimeout(foo, 1000); } foo(); Такой способ не только инкапсулирует вызов `setTimeout`, но и предотвращает от очередей блокирующих вызовов и при этом обеспечивает дополнительный контроль. Сама функция `foo` теперь принимает решение, хочет ли она запускаться ещё раз или нет. -### Очистка таймаутов вручную +(''прим. перев.'' — такая техника теперь активно используется при использовании браузерного метода `requestAnimationFrame` для анимации, работающей на `canvas`). -Удаление таймаутов и интервалов работает через передачу соответствуюего идентификатора либо в функцию `clearTimeout`, либо в функцию `clearInterval` — в зависимости от того, какая функция `set...` использовалась для его получения. +### Сброс таймаутов вручную + +Удалить таймаут или интервал можно посредством передачи соответствующего идентификатора либо в функцию `clearTimeout`, либо в функцию `clearInterval` — в зависимости от того, какая функция `set...` использовалась для его создания. var id = setTimeout(foo, 1000); clearTimeout(id); -### Очистка всех таймаутов +### Сброс всех таймаутов -Из-за того, что встроенного метода для удаления всех таймаутов и/или интервалов не существует, для достижения этой цели приходится использовать брутфорс. +Из-за того, что встроенного метода для удаления всех созданных таймаутов и/или интервалов не существует, для успешного достижения этой цели приходится использовать силу. - // удаляем "все" таймауты + // сбрасываем «все» таймауты for(var i = 1; i < 1000; i++) { clearTimeout(i); } -Вполне могут остаться таймауты, которые не будут захвачены этим произвольным числом; так что всё же рекомендуется следить за идентификаторами всех создающихся таймаутов, засчёт чего их можно будет удалять индивидуально. +Впрочем, с таким кодом, вполне могут остаться «живыми» таймауты, которые не окажутся охвачены настолько произвольным числом. + +Есть и другой способ воплотить желаемое — условиться, что значения ID, выдающихся таймаутам, постоянно увеличиваются — с каждым новыми вызовом `setTimeout`. + + // сбрасываем «все» таймауты + var biggestTimeoutId = window.setTimeout(function(){}, 1), + i; + for(i = 1; i <= biggestTimeoutId; i++) { + clearTimeout(i); + } + +Однако, даже при том, что такой код работает сегодня во всех современных браузерах, нигде не указано и не гарантируется, что значения ID всегда увеличиваются. Поэтому, всё же, рекомендуется следить за *каждым* идентификатором *каждого* создающегося таймаута — это позволит вам надёжно контролировать процесс, сбрасывая их индивидуально. ### Скрытое использование `eval` -`setTimeout` и `setInterval` могут принимать строку в качестве первого параметра. Эту возможность не следует использовать **никогда**, поскольку изнутри при этом производится скрытый вызов `eval`. +`setTimeout` и `setInterval` могут принимать строку в качестве первого параметра. Эту возможность не стоит использовать **никогда**, поскольку изнутри, при этом, производится скрытый вызов `eval`. > **Замечание**: Поскольку функции работы с таймаутами **не** определены в стандарте ECMAScript, точная внутренняя механика их работы может различаться от движка к движку. Например, Microsoft JScript использует конструктор `Function` вместо `eval`. @@ -89,9 +102,9 @@ } bar(); -Поскольку `eval` в этом случае не вызывается [напрямую](#core.eval), переданная в `setTimeout` строка будет выполнена в *глобальной области видимости*; так что локальная переменная `foo` из области видимости `bar` не будет выполнена. +Поскольку `eval` в этом случае не вызывается [явно](#core.eval), переданная в `setTimeout` строка будет выполнена в *глобальной области видимости*; так что локальная функция `foo` из области видимости `bar` вообще не будет выполнена. -По этим же причинам рекомендуется **не** использовать строку для передачи аргументов в функцию, которая должна быть вызвана из одной из двух функций, работающих с таймаутами. +По этим же причинам **не рекомендуется** использовать строковое представление вызова функции для передачи аргументов в функцию, которая должна быть вызвана посредством любого из двух известных способов назначения таймаутов. function foo(a, b, c) {} @@ -103,13 +116,13 @@ foo(a, b, c); }, 1000) -> **Замечание:** При том, что синтаксис `setTimeout(foo, 1000, a, b, c)` разрешено использовать, это крайне не рекомендуется, поскольку может привести к сложно-разпознаваемым ошибкам при работе с [методами](#function.this). +> **Замечание:** При том, что практически возможно использовать синтаксис `setTimeout(foo, 1000, a, b, c)`, делать это крайне не рекомендуется, поскольку может привести к трудно-отлавливаемым ошибкам при операциях с [методами](#function.this). ### Заключение -**Никогда** не используйте строки как параметры `setTimeout` или `setInterval`. Это явный признак **действительно** плохого кода. Если вызываемой функции необходимо передавать аргументы, лучше передавать *анонимную функцию*, которая самостоятельно будет отвечать за сам вызов. +**Никогда** не используйте строки как параметры для `setTimeout` или `setInterval`. Это явный признак **действительно** плохого кода. Если вызываемой функции необходимо передавать аргументы, лучше передавать *анонимную функцию*, которая самостоятельно будет отвечать за сам вызов. -Кроме того, избегайте использования `setInterval` в случаях, когда его планировщик может блокировать выполнение JavaScript. +Кроме прочего, избегайте использования `setInterval` в случаях, когда его планировщик может заблокировать выполнение основного кода JavaScript. [1]: http://ru.wikipedia.org/wiki/Document_Object_Model "Document Object Model" From d5fb8dcc3ade37f43fafc31a0d50ab0d4d84d368 Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Thu, 23 May 2013 23:35:27 +0200 Subject: [PATCH 27/41] some more final corrections --- doc/ru/types/casting.md | 2 +- doc/ru/types/equality.md | 2 +- doc/ru/types/typeof.md | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/ru/types/casting.md b/doc/ru/types/casting.md index f481897f..01ca7fd4 100644 --- a/doc/ru/types/casting.md +++ b/doc/ru/types/casting.md @@ -1,6 +1,6 @@ ## Приведение типов -JavaScript — *слабо типизированный* язык, поэтому *преобразование типов* будет применяться **везде**, где оно возможно. +JavaScript — язык, в котором господствует *слабая типизация*, поэтому *преобразование типов* будет применяться **везде**, где только возможно. // Эти равенства возвращают true new Number(10) == 10; // Number.toString() преобразуется diff --git a/doc/ru/types/equality.md b/doc/ru/types/equality.md index 33a783d3..fcc3ca39 100644 --- a/doc/ru/types/equality.md +++ b/doc/ru/types/equality.md @@ -38,7 +38,7 @@ JavaScript умеет сравнивать значения объектов н null === undefined // false " \t\r\n" === 0 // false -Результаты выше более предсказуемы и помогают быстрее выявлять ошибки в коде. Использование оператора в определённой степени делает код надёжнее, а кроме того обспечивает прирост производительности в случае, если типы операндов различны. +Результаты выше немного более предсказуемы и помогают быстрее выявлять ошибки в коде. Использование этого оператора в определённой степени делает код надёжнее, а кроме того обспечивает прирост производительности в случае, если типы операндов различны. ### Сравнение объектов diff --git a/doc/ru/types/typeof.md b/doc/ru/types/typeof.md index 75a03838..573e73aa 100644 --- a/doc/ru/types/typeof.md +++ b/doc/ru/types/typeof.md @@ -32,7 +32,7 @@ > **Из спецификации:** Значением `[[Class]]` может быть одна из следующих строк: `Arguments`, `Array`, `Boolean`, `Date`, `Error`, `Function`, `JSON`, `Math`, `Number`, `Object`, `RegExp`, `String`. -Чтобы получить значение `[[Class]]`, нужно применить к объекту метод `toString` из `Object.prototype`. +Чтобы получить значение `[[Class]]`, нужно применить к интересующему объекту метод `toString` из прототипа `Object.prototype`. (''прим. перев.'' — то есть не вызвать метод у самого объекта, а именно применить к нему метод из прототипа, см. ниже). ### Класс объекта @@ -46,7 +46,7 @@ is('String', 'test'); // true is('String', new String('test')); // true -В примере выше `Object.prototype.toString` вызывается со значением [this](#function.this), ссылающимся на объект, значение `[[Class]]` которого нужно получить. +В примере выше `Object.prototype.toString` вызывается со значением [this](#function.this), ссылающимся на объект, значение `[[Class]]` которого требуется получить. > **ES5 Замечание:** Для удобства, в ECMAScript 5 возвращаемое значение `Object.prototype.toString` для `null` и `undefined` было изменено с `Object` на `Null` и `Undefined` соответственно. @@ -58,7 +58,7 @@ ### Заключение -Для проверки типа объекта настоятельно рекомендуется использовать `Object.prototype.toString` — это единственный и надежный способ. Как показано выше в таблице типов, некоторые значения, возвращаемые `typeof`, не описаны в спецификации: следовательно, они могут различаться в разных реализациях. +Для проверки типа объекта настоятельно рекомендуется использовать `Object.prototype.toString` — это единственный и надежный способ. Как показано выше в таблице типов, некоторые значения, возвращаемые `typeof`, не описаны в спецификации: следовательно, они могут различаться в разных реализациях движка. За исключением случаев проверки, была ли определена переменная, использования `typeof` следует избегать. From 0cb93321e87984ca5c4d4160750dd02173bd4398 Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Fri, 24 May 2013 02:13:50 +0200 Subject: [PATCH 28/41] some new important corrections --- doc/ru/array/constructor.md | 8 ++++---- doc/ru/array/general.md | 6 ++---- doc/ru/core/delete.md | 4 ++-- doc/ru/core/eval.md | 8 ++++---- doc/ru/core/semicolon.md | 6 +++--- doc/ru/core/undefined.md | 8 ++++---- doc/ru/function/arguments.md | 8 ++++---- doc/ru/function/closures.md | 6 +++--- doc/ru/function/constructors.md | 6 +++--- doc/ru/function/general.md | 6 +++--- doc/ru/function/scopes.md | 12 ++++++------ doc/ru/function/this.md | 6 +++--- doc/ru/index.json | 3 ++- doc/ru/intro/index.md | 2 +- doc/ru/intro/translators.md | 5 +++-- doc/ru/object/forinloop.md | 4 ++-- doc/ru/object/general.md | 18 +++++++++--------- doc/ru/object/hasownproperty.md | 2 +- doc/ru/object/prototype.md | 12 ++++++------ doc/ru/other/timeouts.md | 18 +++++++++--------- doc/ru/types/casting.md | 8 ++++---- doc/ru/types/typeof.md | 4 ++-- 22 files changed, 80 insertions(+), 80 deletions(-) diff --git a/doc/ru/array/constructor.md b/doc/ru/array/constructor.md index 05401763..ad3838d6 100644 --- a/doc/ru/array/constructor.md +++ b/doc/ru/array/constructor.md @@ -1,6 +1,6 @@ ## Конструктор `Array` -Так как конструктор `Array` не однозначен в плане вариантов перечисления его параметров, настоятельно рекомендуется при создании массивов всегда использовать синтаксис литеральной нотации — `[]`. +Так как конструктор `Array` не однозначен в плане вариантов перечисления его параметров, настоятельно рекомендуется при создании массивов всегда использовать только синтаксис литеральной нотации — `[]`. [1, 2, 3]; // Результат: [1, 2, 3] new Array(1, 2, 3); // Результат: [1, 2, 3] @@ -9,17 +9,17 @@ new Array(3); // Результат: [] new Array('3') // Результат: ['3'] -В случае, когда конструктору `Array` передаётся только один аргумент, и этот аргумент имеет тип `Number`, конструктор возвращает новый, _разреженный_ (''прим. перев.'' — *заполненный случайными значениями*), массив, имеющий длину, равную значению переданного аргумента. Стоит заметить, что таким образом будет установлено лишь свойство `length` нового массива, а реальные индексы массива не будут инициализированы. +В случае, когда в конструктор `Array` передаётся только один аргумент, и этот аргумент имеет тип `Number`, конструктор возвращает новый, *разреженный* (_прим. перев._ — *заполненный случайными значениями*), массив, имеющий длину, равную значению переданного аргумента. Стоит заметить, что таким образом будет установлено лишь свойство `length` нового массива, а реальные индексы массива не будут инициализированы. var arr = new Array(3); arr[1]; // не определён, undefined 1 in arr; // false, индекс не был установлен -Поведение, которое позволяет заранее установить размер массива может пригодиться лишь в нескольких случаях — таких как повторение строки, за счёт которого избегается использование кода `for loop`. +Поведение, которое позволяет заранее установить размер массива может пригодиться лишь в нескольких случаях — таких, как повторение строки, за счёт которого можно избежать использования `for loop`. new Array(count + 1).join(stringToRepeat); ### Заключение -Нужно избегать использования конструктора `Array`. Литералы, определённо, более предпочтительны — это краткая запись, она имеет более «чистый» синтаксис и повышает читабельность кода. +Использования конструктора `Array` нужно избегать. Литералы, определённо, намного более предпочтительны — это краткая запись, она имеет более «чистый» синтаксис и повышает читабельность кода. diff --git a/doc/ru/array/general.md b/doc/ru/array/general.md index 9c8178ca..41b703bb 100644 --- a/doc/ru/array/general.md +++ b/doc/ru/array/general.md @@ -4,7 +4,7 @@ > **Замечание:** Массивы в JavaScript **не** являются *ассоциативными массивами*. Для связывания ключей и значений в JavaScript есть только [объекты](#object.general). При этом, ассоциативные массивы априори **сохраняют** заданный порядок свойств, объекты же **не** делают этого. -Поскольку во время выполнения `for in` циклически перебираются все свойства объекта, находящиеся в его цепочке прототипов, а единственный способ исключить ненужные свойства — использовать [`hasOwnProperty`](#object.hasownproperty) — такой цикл **до 20 раз** медленнее обычного цикла `for`. +Поскольку во время выполнения `for in` циклически перебираются все свойства объекта, находящиеся в его цепочке прототипов, а единственный способ исключить ненужные свойства — использовать [`hasOwnProperty`](#object.hasownproperty) — в действии такой цикл **до 20 раз** медленнее обычного цикла `for`. ### Итерирование @@ -21,8 +21,6 @@ Фактически, цикл без кэширования может выполняться в **два раза медленнее**, нежели цикл с кэшированной длиной. -''Прим. перев.'' — если вам нужно перебрать элементы в обратном порядке или порядок не имеет для вас значения, есть дополнительный способ (не самый быстрый, поскольку происходит сравнение без приведения типов) перебрать элементы массива: `var i = arr.length; while (i--) { ... }`. - ### Свойство `length` Хотя *геттер* свойства `length` всего лишь возвращает количество элементов содержащихся в массиве, *сеттер* оказывается удобно использовать для **урезания** массивов. @@ -34,7 +32,7 @@ foo.length = 6; foo; // [1, 2, 3] -Присвоение свойству `length` меньшей величины урезает массив, однако присвоение большего значения не даёт никакого эффекта. +Присвоение свойству `length` меньшей величины урезает массив, однако присвоение большего значения не производит никакого эффекта. ### Заключение diff --git a/doc/ru/core/delete.md b/doc/ru/core/delete.md index 7d083281..a229d8d5 100644 --- a/doc/ru/core/delete.md +++ b/doc/ru/core/delete.md @@ -4,7 +4,7 @@ ### Глобальный код и код внутри функций -Когда переменная или функция определена в глобальной области видимости или в [области видимости функции](#function.scopes), её судьба предопределена: (''прим. перев.'' — где-то внутри движка JavaScript) она является свойством либо объекта Activation, либо объекта Global. Каждое из таких свойств имеет по набору атрибутов, среди которых присутствует и `DontDelete`. Переменные и объявления функций, обнаруженные движком в глобальной области или в коде функции, создаются с атрибутом `DontDelete` и, посему, не могут быть удалены. +Когда переменная или функция определена в глобальной области видимости или в [области видимости функции](#function.scopes), её судьба предопределена: (_прим. перев._ — где-то внутри движка JavaScript) она является свойством либо объекта Activation, либо объекта Global. Каждое из таких свойств имеет по набору атрибутов, среди которых присутствует и `DontDelete`. Переменные и объявления функций, обнаруженные движком в глобальной области или в коде функции, создаются с атрибутом `DontDelete` и, посему, не могут быть удалены. // глобальная переменная: var a = 1; // установлен DontDelete @@ -67,7 +67,7 @@ ### Хост-объекты -(''прим. перев.'' — Хост-объекты — объекты, которые, в неком окружении, дополняют функциональность языка JavaScript, не являясь частью его спецификации. В случае браузера это объекты `window`, `document`, `setTimeout` и т.п.) +(_прим. перев._ — Хост-объекты — это объекты, которые, в неком окружении, дополняют функциональность языка JavaScript, не являясь частью его спецификации. В случае браузера это объекты `window`, `document`, `setTimeout` и т.п.) Поведение оператора `delete` может быть абсолютно непредсказуемым при применении его к хост-объектам. С позволения спецификации, хост-объекты вольны вести себя как им только вздумается. diff --git a/doc/ru/core/eval.md b/doc/ru/core/eval.md index 0fd5f762..dbbe5190 100644 --- a/doc/ru/core/eval.md +++ b/doc/ru/core/eval.md @@ -1,6 +1,6 @@ ## Почему нельзя использовать `eval` -Функция `eval` исполняет хранящийся в строке код JavaScript в локальной области видимости. +Функция `eval` выполняет переданный строкой код JavaScript в локальной области видимости. var foo = 1; function test() { @@ -11,7 +11,7 @@ test(); // 3 foo; // 1 -Однако, `eval` исполняется в локальной области видимости тогда и только тогда, когда он вызывается явно *и при этом* имя вызывающейся функции идентично `eval` (''прим. перев.'' — ох!). +Однако, функция `eval` выполняет указанный код в локальной области видимости тогда и только тогда, когда она вызывается явно *и при этом* имя вызывающейся функции *идентично* `eval` (_прим. перев._ — ох!). var foo = 1; function test() { @@ -31,9 +31,9 @@ ### Проблемы с безопасностью -Кроме всего прочего, функция `eval` — это проблема в безопасности, поскольку она выполняет **любой** переданный в неё код; **никогда** не следует использовать её со строками из неизвестных или недоверительных источников. +Кроме всего прочего, функция `eval` — это дыра в безопасности, поскольку она выполняет **любой** переданный в неё код; **никогда** не следует использовать её со строками из неизвестных или недоверительных источников. ### Заключение -Использовать `eval` не стоит никогда: любой код с участием этой функции автоматически порождает вопросы о качестве его работы, производительности и безопасности. Если вдруг для работы вам необходим `eval`, эта часть кода должна тут же ставиться под сомнение и в первую очередь *исключаться** из проекта — необходимо найти *лучший способ*, которому не требуются вызовы `eval`. +Использовать `eval` не стоит никогда: любой код с участием этой функции автоматически порождает вопросы о качестве его работы, производительности и безопасности. Если вдруг для работы вам необходим `eval`, эта часть кода должна тут же ставиться под сомнение и в первую очередь *исключаться* из проекта — необходимо найти *лучший способ*, которому не требуются вызовы `eval`. diff --git a/doc/ru/core/semicolon.md b/doc/ru/core/semicolon.md index 08de7b08..3f8083d7 100644 --- a/doc/ru/core/semicolon.md +++ b/doc/ru/core/semicolon.md @@ -1,8 +1,8 @@ ## Автоматическая вставка точек с запятой -Несмотря на то, что JavaScript имеет синтаксис, подобный языкам семейства C, он никоим образом **не принуждает** вас ставить точки с запятой в исходном коде — вы всегда вольны их опустить. +Несмотря на то, что JavaScript имеет синтаксис, подобный языкам семейства C, он никоим образом **не принуждает** вас ставить точки с запятой в исходном коде — вам всегда позволяется их опустить. -При этом JavaScript — вовсе не язык с полным отсутствием точек с запятой: они на самом деле нужны ему для того, чтобы он мог разобраться в вашем коде. Поэтому парсер JavaScript **автоматически** вставляет их в те места, где сталкивается с ошибкой парсинга по причине их отсутствия. +При этом JavaScript — вовсе не язык с абсолютным отсутствием точек с запятой: они на самом деле нужны ему для того, чтобы он мог разобраться в вашем коде. Поэтому парсер JavaScript **автоматически** вставляет их в те места, где сталкивается с ошибкой парсинга по причине их отсутствия. var foo = function() { } // ошибка разбора, ожидается точка с запятой @@ -93,7 +93,7 @@ log('тестируем!')(options.list || []).forEach(function(i) {}) -**Чрезвычайно** высоки шансы, что `log` **не** возращает *никаких* функций; таким образом, выполнение кода с такой строкой породит `TypeError` с сообщением о том, что `undefined не является функцией`. +**Чрезвычайно** высоки шансы того, что `log` **не** возращает *никаких* функций; таким образом, выполнение этой строки кода породит `TypeError` с сообщением о том, что `undefined не является функцией`. ### Заключение diff --git a/doc/ru/core/undefined.md b/doc/ru/core/undefined.md index 578c2f2a..38a388cb 100644 --- a/doc/ru/core/undefined.md +++ b/doc/ru/core/undefined.md @@ -1,6 +1,6 @@ ## `undefined` и `null` -В JavaScript есть два отдельных типа для описания *ничего* — `null` и `undefined`, при этом последний из них более полезен. +В JavaScript есть два отдельных типа для описания *ничего* — `null` и `undefined`, при этом последний из них наиболее полезен. ### Значение `undefined` @@ -18,7 +18,7 @@ - Из оператора `return`, который не возвращает явного значения. - В результате поиска несуществующего свойства у объекта (и/или доступа к нему). - При попытке доступа к аргументу функции, который не был передан в неё явно. - - При попытке доступа ко всему, чьим значением является `undefined`. + - При попытке доступа к чему-либо, чьим значением является `undefined`. - В результате вычисления любого выражения, соответствующего форме `void(выражение)`. ### Защита от потенциальных изменений значения `undefined` @@ -45,11 +45,11 @@ })('Hello World', 42); -Единственная разница между этими вариантами в том, что последняя версия будет больше на 4 байта при минификации, и в первом случае внутри анонимной обёртки нет дополнительного оператора `var`. +Единственная разница между этими вариантами в том, что последняя версия будет больше на 4 байта при минификации, а в первом случае внутри анонимной обёртки нет дополнительного оператора `var`. ### Применение `null` Хотя `undefined` в контексте языка JavaScript чаще используется в роли традиционного *null*, настоящий `null` (и тип и литерал) является, в некоторой степени, просто другим типом данных. -Он используется во внутренних механизмах JavaScript (в случаях вроде установки конца цепочки прототипов через присваивание `Foo.prototype = null`). Но почти во всех случаях тип `null` может быть заменён на `undefined`. +Он используется во внутренних механизмах JavaScript (в случаях вроде установки конца цепочки прототипов через присваивание `Foo.prototype = null`). Но почти во всех случаях тип `null` может быть равносильно заменён на `undefined`. diff --git a/doc/ru/function/arguments.md b/doc/ru/function/arguments.md index a9bfa59b..428fbe57 100644 --- a/doc/ru/function/arguments.md +++ b/doc/ru/function/arguments.md @@ -4,11 +4,11 @@ > **Замечание:** В случае, если переменная `arguments` уже была объявлена в области видимости функции либо путём присвоения через выражение `var`, либо являясь формальным параметром, объект `arguments` не будет создан. -Объект `arguments` **не** является ни экземпляром, ни наследником `Array`. Он, конечно же, очень похож на массив, и даже содержит свойство `length` — но он не наследует `Array.prototype`, и если внимательно присмотреться, он окажется обычным `Object`. +Объект `arguments` **не** является ни экземпляром, ни наследником `Array`. Он, конечно же, очень похож на массив, и даже обладает свойством `length` — но он не наследует `Array.prototype`, и если внимательно присмотреться, он окажется обычным `Object`. -По этой причине, у объекта `arguments` **отсутствуют** стандартные методы массивов, такие как `push`, `pop` или `slice`. Пусть перебор с использованием обычного цикла `for` по аргументам работает вполне корректно, но вам придётся конвертировать этот объект в настоящий массив типа `Array`, чтобы применять к нему стандартные методы массивов. +По этой причине, у объекта `arguments` **отсутствуют** стандартные методы массивов, такие как `push`, `pop` или `slice`. Пусть перебор с использованием обычного цикла `for` по аргументам работает вполне корректно, но вам придётся конвертировать этот объект в настоящий массив типа `Array`, для того чтобы получить возможность применять к нему стандартные методы массивов. -### Конвертация в массив +### Преобразование в массив Этот код вернёт новый массив типа `Array`, содержащий все элементы объекта `arguments`. @@ -64,7 +64,7 @@ } foo(1, 2, 3); -### Мифы и истина о производительности +### Разоблачение мифов о производительности Объект `arguments` создаётся во всех случаях, лишь одним исключением — когда он переопределён по имени внутри функции или когда одним из её параметров является переменная с таким именем. Неважно, используется при этом сам объект в коде функции или нет. diff --git a/doc/ru/function/closures.md b/doc/ru/function/closures.md index 7257897b..cd2a6ac3 100644 --- a/doc/ru/function/closures.md +++ b/doc/ru/function/closures.md @@ -32,7 +32,7 @@ count = 1337; }; -В приведенном примере мы **не** изменяем переменную `count` из области видимости `Counter`, т.к. `foo.hack` не объявлен в **той** области. Вместо этого будет создана или перезаписана *глобальная* переменная `count` (''прим. перев.'' — замена кода внутри `foo.hack` на `this.count = 1337`, не поможет, конечно же, тоже, поскольку `count` и не был свойством объекта `Counter`, а был лишь внутренней переменной); +В приведенном примере мы **не** изменяем переменную `count` из области видимости `Counter`, т.к. `foo.hack` не объявлен в **той** области. Вместо этого будет создана или перезаписана *глобальная* переменная `count` (_прим. перев._ — замена кода внутри `foo.hack` на `this.count = 1337`, не поможет, конечно же, тоже, поскольку `count` никогда не был свойством объекта `Counter`, а был лишь внутренней переменной); ### Замыкания внутри циклов @@ -62,7 +62,7 @@ })(i); } -Анонимная функция-обертка вызвается сразу же, и в качестве первого аргумента получает индекс `i`, **значение** которого будет скопировано в параметр `e`. +Анонимная функция-обертка вызывается сразу же, и в качестве первого аргумента получает индекс `i`, **значение** которого будет скопировано в параметр `e`. Анонимная функция, которая передается в `setTimeout`, теперь содержит ссылку на переменную `e`, значение которой **не** изменяется циклом. @@ -76,7 +76,7 @@ })(i), 1000) } -''Прим, перев.'' В качестве упражнения на замыкания и анонимные функции, попробуйте заменить оборачивающие вызовы анонимных функций на варианты с `.call` и `.apply`. +_Прим, перев._ В качестве упражнения на замыкания и анонимные функции, попробуйте заменить оборачивающие вызовы анонимных функций в примерах на варианты с `.call` и `.apply`. > **Замечание** от перев. Переменную `e` можно тоже назвать `i`, если вы хотите: это не поменяет поведения кода — внутренняя переменная `i` всё так же будет *копией* внешней переменной. diff --git a/doc/ru/function/constructors.md b/doc/ru/function/constructors.md index dea733db..d53a04f8 100644 --- a/doc/ru/function/constructors.md +++ b/doc/ru/function/constructors.md @@ -1,6 +1,6 @@ ## Конструктор - Конструкторы в JavaScript тоже действуют отличным от большинства других языков образом. Любая функция, вызванная с использованием ключевого слова `new`, станет конструктором. + Конструкторы в JavaScript тоже действуют отличным от большинства языков образом. Любая функция, вызванная с использованием ключевого слова `new`, станет конструктором. Внутри конструктора (вызываемой функции) `this` будет указывать на новосозданный `Object`. [Прототипом](#object.prototype) этого **нового** экземпляра будет `prototype` функции, которая была вызвана под видом конструктора. @@ -41,7 +41,7 @@ } Foo(); // возвращает undefined -Хотя этот пример и будет работать — в связи с поведением [`this`](#function.this) в JavaScript, значение будет присвоено *глобальному объекту* — навряд ли это предполагалось автором. +Хотя этот пример и будет работать — в связи с поведением [`this`](#function.this) в JavaScript, значение будет присвоено *глобальному объекту* — навряд ли это предполагалось его автором. ### Фабрики @@ -64,7 +64,7 @@ В обоих случаях при вызове `Bar` мы получим один и тот же результат — новый объект со свойством `method`, являющимся [замыканием](#function.closures)). -Ещё следует заметить, что вызов `new Bar()` никак **не** воздействует на прототип возвращаемого объекта. Хоть прототип и назначается всем новосозданным объектам, `Bar` никогда не возвращает этот новый объект (''прим. перев.'' — судя по всему, подразумевается, что код `Bar` не может влиять на прототип созданного объекта, и под словами «новый объект» в последнем случае кроется прототип нового объекта, а не сам новый объект). +Ещё следует заметить, что вызов `new Bar()` никак **не** воздействует на прототип возвращаемого объекта. Хоть прототип и назначается всем новосозданным объектам, `Bar` никогда не возвращает этот новый объект (_прим. перев._ — судя по всему, подразумевается, что код `Bar` не может влиять на прототип созданного объекта, и под словами «новый объект» в последнем случае кроется прототип нового объекта, а не сам новый объект). В предыдущем примере нет никаких функциональных различий между вызовом конструктора с оператором `new` и вызовом без него. diff --git a/doc/ru/function/general.md b/doc/ru/function/general.md index e42a4634..b28dc62c 100644 --- a/doc/ru/function/general.md +++ b/doc/ru/function/general.md @@ -7,7 +7,7 @@ // всё просто и привычно function foo() {} -В следующем примереб ещё перед запуском всего скрипта, для описанной функции [резервируется](#function.scopes) переменная; за счёт этого она доступна *в любом месте* кода, вне зависимости от того, где она *определена* — даже если она вызывается заранее, перед её фактическим объявлением в коде (и сколь угодно задолго до такого определения). +В следующем примере, ещё перед запуском всего скрипта, для описанной функции [резервируется](#function.scopes) переменная; за счёт этого она доступна *в любом месте* кода, вне зависимости от того, где она *определена* — даже если она вызывается заранее, перед её фактическим объявлением в коде (и сколь угодно задолго до такого определения). foo(); // сработает, т.к. функция будет создана до выполнения кода @@ -17,7 +17,7 @@ var foo = function() {}; -В конце этого примера переменной `foo` присваивается безымянная *анонимная* функция. +В конце примера ниже переменной `foo` присваивается безымянная *анонимная* функция. foo; // 'undefined' foo(); // вызовет TypeError @@ -29,7 +29,7 @@ ### Выражения с именованными фунциями -Существует еще один ньюанс, касающийся присваивания именованных функций: +Существует еще один ньюанс, касающийся присваиваний именованных функций: var foo = function bar() { bar(); // работает diff --git a/doc/ru/function/scopes.md b/doc/ru/function/scopes.md index a3771954..f0dd027f 100644 --- a/doc/ru/function/scopes.md +++ b/doc/ru/function/scopes.md @@ -51,7 +51,7 @@ } } -Внешний цикл прекратит работу сразу после первого вызова `subLoop`, поскольку `subLoop` перезаписывает глобальное значение переменной `i`. Использование `var` во втором цикле `for` могло бы вас легко избавить от этой ошибки. **Никогда** не забывайте использовать `var`, если только вы не *осознанно намеряны* повлиять на внешнюю область видимости. +Внешний цикл прекратит работу сразу после первого вызова `subLoop`, поскольку `subLoop` перезаписывает глобальное значение переменной `i`. Использование `var` во втором цикле `for` могло бы вас легко избавить от этой ошибки. **Никогда** не забывайте использовать `var`, если только вы не обладаете полностью *осознанным намерением* повлиять на внешнюю область видимости. ### Локальные переменные @@ -101,7 +101,7 @@ JavaScript **«вытягивает»** определения. Это знач // определение функции тоже переместилось function test(data) { - var goo, i, e; // пропущенная блочная область видимости + var goo, i, e; // упущенная область видимости // переместила их сюда if (false) { goo = 1; @@ -121,7 +121,7 @@ JavaScript **«вытягивает»** определения. Это знач test(); -Потерянная область видимости блока не только переместит операторы `var` вовне циклов и их тел, но и сделает результаты некоторых конструкций с `if` неинтуитивными. +Потерянная область видимости не только переместит операторы `var` вовне циклов и их тел, но и лишит смысла конструкцию c `if. Предполагалось, что в исходном коде оператор `if` изменял *глобальную переменную* `goo`, однако, как оказалось, он изменял *локальную переменную* — в результате работы вытягивания. @@ -133,7 +133,7 @@ JavaScript **«вытягивает»** определения. Это знач var SomeImportantThing = {}; } -Но конечно же этот код работает: из-за того, что оператор `var` был перемещён наверх *глобальной области видимости* +Но, конечно же, этот код работает: из-за того, что оператор `var` был перемещён наверх *глобальной области видимости* var SomeImportantThing; @@ -162,7 +162,7 @@ JavaScript **«вытягивает»** определения. Это знач ### Пространства имён -Нередкое обнаруживается неприятное последствие наличия одного единственного глобального пространства имён — проблемы с перекрытием имён переменных. В JavaScript эту проблему легко избежать, используя *анонимные обёртки*. +Нередко можно столкнуться с неприятным последствием от наличия одного единственного глобального пространства имён — проблемы с перекрытием имён переменных. В JavaScript эту проблему легко избежать, используя *анонимные обёртки*. (function() { // самодостаточное «пространство имён» @@ -173,7 +173,7 @@ JavaScript **«вытягивает»** определения. Это знач })(); // сразу же выполнить функцию -Безымянные функции являются отложенными [выражениями](#function.general) (''прим. перев.'' — то есть, они не разбираются по месту описания, а откладываются парсером напоследок); поэтому, чтобы вы сделать их исполняемыми, следует спровоцировать их разбор. +Безымянные функции являются отложенными [выражениями](#function.general) (_прим. перев._ — то есть, они не разбираются по месту описания, а откладываются парсером напоследок); поэтому, чтобы вы сделать их исполняемыми, следует спровоцировать их разбор. ( // разобрать функцию внутри скобок function() {} diff --git a/doc/ru/function/this.md b/doc/ru/function/this.md index 1ec66a95..79acf46a 100644 --- a/doc/ru/function/this.md +++ b/doc/ru/function/this.md @@ -53,7 +53,7 @@ test(); } -Распространено заблуждение о том, что `this` внутри `test` ссылается на `Foo`, но это совсем **не так**. +Распространено заблуждение в том, что `this` внутри `test` ссылается на `Foo`, но это совсем **не так**. Для того, чтобы получить доступ к `Foo` внутри функции `test`, необходимо создать локальную переменную внутри `method`, которая и будет ссылаться на `Foo`. @@ -65,7 +65,7 @@ test(); } -Подходящее имя для такой переменной — `that`, и его часто используют для ссылки на внешний `this`. В комбинациях с [замыканиями](#function.closures) такая переменная может использоваться, чтобы «пробрасывать» `this` в глобальную область, или в любой другой объект. +Подходящее имя для такой переменной — `that`, и его часто используют для ссылки на внешний `this`. В комбинации с [замыканиями](#function.closures) такая переменная может использоваться, чтобы «пробрасывать» `this` в глобальную область, или в любой другой объект. ### Присвоение методов @@ -76,7 +76,7 @@ Следуя первому правилу, `test` вызывается как обычная функция; следовательно `this` внутри него больше не ссылается на `someObject`. -Хотя позднее связывание `this` на первый взгляд может показаться не очень хорошей идеей, но на самом деле это именно то, благодаря чему работает [наследование прототипов](#object.prototype). +Хотя позднее связывание `this` на первый взгляд может показаться не очень хорошей идеей, на самом деле это именно то, благодаря чему работает [наследование прототипов](#object.prototype). function Foo() {} Foo.prototype.method = function() {}; diff --git a/doc/ru/index.json b/doc/ru/index.json index 032c872b..9a14c4a9 100644 --- a/doc/ru/index.json +++ b/doc/ru/index.json @@ -60,7 +60,8 @@ "articles": [ "eval", "undefined", - "semicolon" + "semicolon", + "delete" ] }, { diff --git a/doc/ru/intro/index.md b/doc/ru/intro/index.md index 2401cce1..88e5887c 100644 --- a/doc/ru/intro/index.md +++ b/doc/ru/intro/index.md @@ -2,7 +2,7 @@ **JavaScript Гарден** — это постоянно обновляющаяся и растущая документация по самым заковыристым темам языка JavaScript. В ней вы найдёте советы о том, как избежать распространённых ошибок и предсказать появление тех или иных багов. В документации подробно освещены проблемы оптимизации и нерекомендуемые практики с которыми, продираясь к глубинам языка, могут столкнуться даже просвещённые JavaScript-программисты. -JavaScript Гарден **не cтавит** себе целью научить вас языку JavaScript. Вам понадобится реальный опыт работы с языком чтобы понимать темы, рассматриваемые в этом руководстве. Если вам требуется изучить основы языка, пожалуйста обратитесь к замечательному [руководством][1] на сайте Mozilla Developer Network. +JavaScript Гарден **не cтавит** себе целью научить вас языку JavaScript. Вам понадобится реальный опыт работы с языком чтобы понимать темы, рассматриваемые в этом руководстве. Если вам требуется изучить основы языка, пожалуйста обратитесь к замечательному [руководству][1] на сайте Mozilla Developer Network. [1]: https://developer.mozilla.org/en/JavaScript/Guide diff --git a/doc/ru/intro/translators.md b/doc/ru/intro/translators.md index d08ba2a1..a8c26b07 100644 --- a/doc/ru/intro/translators.md +++ b/doc/ru/intro/translators.md @@ -4,9 +4,10 @@ - [Антон Шевчук][2] - [Максим Лозовой][3] - [Елена Пашкова][4] + - [binariti][5] очень помог со стилистикой текста -[1]: http://shamansir.madfire.net/ +[1]: http://shamansir.github.com/ [2]: http://anton.shevchuk.name/ [3]: http://nixsolutions.com/ [4]: http://nixsolutions.com/ - +[5]: http://habrahabr.ru/users/binariti/ \ No newline at end of file diff --git a/doc/ru/object/forinloop.md b/doc/ru/object/forinloop.md index a6eb3655..36242c4b 100644 --- a/doc/ru/object/forinloop.md +++ b/doc/ru/object/forinloop.md @@ -2,7 +2,7 @@ Как и оператор `in`, цикл `for in` проходит по всей цепочке прототипов, обходя свойства объекта. -> **Примечание:** Цикл `for in` **не** обходит те свойства объекта, у которых внутренний атрибут `enumerable` установлен в `false`; как пример - свойство `length` у массивов +> **Примечание:** Цикл `for in` **не** обходит те свойства объекта, у которых внутренний атрибут `enumerable` установлен в `false`; как пример - свойство `length` у массивов. // Подпортим Object.prototype Object.prototype.bar = 1; @@ -25,7 +25,7 @@ } } -Это единственно правильная версия использования такого цикла. За счёт использования `hasOwnProperty` будет выведено одно **только** свойство `moo`. Если же вы уберёте проверку `hasOwnProperty`, код станет нестабилен и, если кто-то позволил себе изменить прототипы встроенных типов, такие как `Object.prototype`, у вас возникнут непредвиденные ошибки. +Это единственно правильная версия выполнения такого цикла. За счёт использования `hasOwnProperty` будет выведено одно **только** свойство `moo`. Если же вы уберёте проверку `hasOwnProperty`, код станет нестабилен и, если кто-то позволил себе изменить прототипы встроенных типов, такие как `Object.prototype`, у вас возникнут непредвиденные сюрпризы. Один из самых популярных фреймворков [Prototype][1] использует упомянутое расширение `Object.prototype` — и если вы его подключаете — ни в коем случае не забывайте использовать `hasOwnProperty` внутри всех циклов `for in` — иначе у вас гарантированно возникнут проблемы. diff --git a/doc/ru/object/general.md b/doc/ru/object/general.md index 90856e25..176f4c60 100644 --- a/doc/ru/object/general.md +++ b/doc/ru/object/general.md @@ -9,11 +9,11 @@ Foo.bar = 1; Foo.bar; // 1 -Распростанено заблуждение, что числовые литералы нельзя использовать в роли объектов — оно неверно и зародилось из-за упущения в парсере JavaScript, благодаря которому применение *точечной нотации* к числу воспринимается им как литерал числа с плавающей точкой. +Среди программистов на JavaScript распростанено заблуждение, что числовые литералы нельзя использовать в роли объектов — оно является неверным и зародилось по причине известного упущения в парсере JavaScript, благодаря которому применение *точечной нотации* к числу воспринимается им как литерал числа с плавающей точкой. 2.toString(); // вызывает SyntaxError -Есть несколько способов обойти этот недостаток и любой из них подойдёт, если нужно добиться от числа поведения объекта: +Есть несколько способов обойти этот недостаток и любой из них подойдёт, если от числового значения нужно добиться поведения объекта: 2..toString(); // вторая точка распознаётся корректно 2 .toString(); // обратите внимание на пробел перед точкой @@ -21,7 +21,7 @@ ### Объекты как хранилища данных -Объекты в JavaScript могут использоваться и как [*хеш-таблицы*][1]: подавляющей частью они состоят из именованных свойств (ключей), привязанных к значениям. +Объекты в JavaScript могут использоваться и как [*хеш-таблицы*][1]: подавляющей частью они состоят из именованных свойств (ключей), привязанных к соответствующим значениям. Используя объектный литерал — нотацию `{}` — можно создать простой объект. Новый объект [наследуется](#object.prototype) от `Object.prototype` и не имеет [собственных свойств](#object.hasownproperty). @@ -44,13 +44,13 @@ foo.1234; // SyntaxError foo['1234']; // работает -Обе нотации идентичны по принципу работы, одна лишь разница в том, что использование квадратных скобок позволяет устанавливать свойства динамически и использовать такие имена свойств, какие в других случаях могли бы привести к синтаксической ошибке. +Обе нотации идентичны по принципу работы; разница между ними лишь в том, что использование квадратных скобок позволяет устанавливать свойства динамически и использовать такие имена свойств, какие в других случаях могли бы привести к синтаксической ошибке. ### Удаление свойств Единственный способ полностью удалить свойство у объекта — использовать оператор `delete`; устанавливая свойство в `undefined` или `null`, вы только заменяете связанное с ним *значение*, но не удаляете *ключ*. -> **Замечание** от перев.: Если ссылок на значение больше нет, то сборщиком мусора удаляется и само значение, но ключ объекта при этом всё так же имеет новое значение. +> **Замечание** от перев.: Если ссылок на значение больше нет, то сборщиком мусора удаляется и само значение, но ключ объекта при этом всё так же указывает на новое значение. var obj = { bar: 1, @@ -67,7 +67,7 @@ } } -Приведённый код выведет две строки: `bar undefined` и `foo null` — на самом деле удалено было только свойство `baz` и посему только оно будет отсутствовать в выводе. +Приведённый код выведет две строки — `bar undefined` и `foo null`: на самом деле удалено было только свойство `baz` и посему лишь оно будет отсутствовать в выводе. ### Запись ключей @@ -76,11 +76,11 @@ delete: 'Я тоже ключевое слово, и меня' // порождает SyntaxError }; -Ключи свойств объектов могут записываться как явно символами без кавычек, так и в виде закавыченных строк. В связи с другим упущением в парсере JavaScript, вышеприведённый код выбросит `SyntaxError` во всех версиях ранее ECMAScript 5. +Ключи для свойств объектов могут записываться как посимвольно без кавычек, так и в виде закавыченных строк. В связи с другим упущением в парсере JavaScript, вышеприведённый код породит `SyntaxError` во всех версиях ранее ECMAScript 5. -Источником ошибки является факт, что `delete` — это *ключевое слово* и поэтому его *необходимо* записывать как *строчный литерал*, ради уверенности в том, что оно будет корректно опознано более старыми движками JavaScript. +Источником ошибки является факт, что `delete` — это *ключевое слово* и поэтому его *необходимо* записывать как *строчный литерал*, хотя бы ради уверенности, что оно будет корректно опознано более старыми движками JavaScript. -*От перев.:* И еще один пример в пользу строковой нотации, это относится к [JSON][2]: +*От перев.:* Дополнительный пример в пользу строковой нотации, это относится к [JSON][2]: // валидный JavaScript и валидный JSON { diff --git a/doc/ru/object/hasownproperty.md b/doc/ru/object/hasownproperty.md index 55043b65..b72f282d 100644 --- a/doc/ru/object/hasownproperty.md +++ b/doc/ru/object/hasownproperty.md @@ -4,7 +4,7 @@ > **Примечание:** Для проверки существования свойства **недостаточно** проверять, эквивалентно ли оно `undefined`. Свойство может вполне себе существовать, но при этом ему может быть присвоено значение `undefined`. -`hasOwnProperty` — единственная функция в JavaScript, которая позволяет получить свойства объекта **без обращения** к цепочке его прототипов. +`hasOwnProperty` — единственная функция в JavaScript, которая помогает получать свойства объекта **без обращения** к цепочке его прототипов. // Подпортим Object.prototype Object.prototype.bar = 1; diff --git a/doc/ru/object/prototype.md b/doc/ru/object/prototype.md index 7e4413ab..de546886 100644 --- a/doc/ru/object/prototype.md +++ b/doc/ru/object/prototype.md @@ -2,7 +2,7 @@ В JavaScript отсутствует классическая модель наследования — вместо неё используется [*прототипная модель*][1]. -Хоть её и часто причисляют к недостаткам JavaScript, на самом деле прототипная модель наследования *мощнее* классической. К примеру, поверх неё можно предельно легко реализовать классическое наследование, а попытки совершить обратное вынудят вас попотеть. +Хоть её и часто причисляют к недостаткам JavaScript, на самом деле прототипная модель наследования *мощнее* классической. К примеру, поверх неё можно предельно легко реализовать классическое наследование, а попытки совершить обратное непременно вынудят вас попотеть. Из-за того, что JavaScript — практически единственный широко используемый язык с прототипным наследованием, придётся потратить некоторое время на осознание различий между этими двумя моделями. @@ -37,19 +37,19 @@ Object.prototype { toString: ... /* и т.д. */ } -В приведённом коде объект `test` будет наследовать оба прототипа: `Bar.prototype` и `Foo.prototype`; следовательно, он будет иметь и доступ к функции `method`, которую мы определили в прототипе `Foo`. Также, у него есть доступ к свойству `value` **одного уникального** экземпляра `Foo`, который является его прототипом. Важно заметить, что `new Bar()` при вызове **не создаёт** новый экземпляр `Foo`, а повторно использует тот объект, который был установлен ему (`Bar`) в прототипе: таким образом, все новые экземпляры `Bar` будут иметь **одно и то же** свойство `value`. +В приведённом коде объект `test` будет наследовать оба прототипа: `Bar.prototype` и `Foo.prototype`; следовательно, у него будет доступ к функции `method`, которую мы определили в прототипе `Foo`. Также, у него будет доступ к свойству `value` **одного уникального** экземпляра `Foo`, который является его прототипом. Важно заметить, что `new Bar()` при вызове **не создаёт** новый экземпляр `Foo`, а повторно использует тот объект, который был установлен ему (`Bar`) в прототипе: таким образом, все новые экземпляры `Bar` будут иметь **одно и то же** свойство `value` (_прим. перев._ — то есть, все ссылки по имени `value`, во всех экземплярах `Bar`, будут указывать на одно и то же место в памяти). -> **Замечание:** Никогда **не используйте** конструкцию `Bar.prototype = Foo`, поскольку ссылка будет указывать не на прототип `Foo`, а на объект-функцию `Foo`. Из-за этого цепочка прототипов будет проходить через `Function.prototype`, а не через `Foo.prototype` и в результате чего функция `method` вообще не будет содержаться в цепочке прототипов. +> **Замечание:** Никогда **не используйте** конструкцию `Bar.prototype = Foo`, поскольку ссылка будет указывать не на прототип `Foo`, а на объект-функцию `Foo`. Из-за этого цепочка прототипов будет проходить через `Function.prototype`, а не через `Foo.prototype`, в результате чего функция `method` вообще не будет содержаться в цепочке прототипов. ### Поиск свойств -При обращении к какому-либо свойству объекта, JavaScript проходит **вверх** по цепочке прототипов этого объекта, пока не найдет свойство c запрашиваемым именем. +При обращении к какому-либо свойству объекта, движок JavaScript проходит **вверх** по цепочке прототипов этого объекта, пока не найдет свойство c запрашиваемым именем. Если он достигнет верхушки этой цепочки (а именно `Object.prototype`), и при этом так и не найдёт указанное свойство, вместо него вернётся значение [undefined](#core.undefined). ### Свойство `prototype` -Тот факт, что свойство `prototype` используется языком для построения цепочек прототипов, даёт нам возможность присвоить **любое** значение этому свойству. Однако обычные примитивы, если назначать их в качестве прототипа, будут просто-напросто игнорироваться. +Тот факт, что свойство `prototype` используется языком для построения цепочек прототипов, даёт нам возможность присвоить **любое** значение этому свойству. Впрочем, обычные примитивы, если назначать их в качестве прототипов, будут просто-напросто игнорироваться. function Foo() {} Foo.prototype = 1; // никакого эффекта @@ -57,7 +57,7 @@ "foo":"bar" }; // это сработает -Но присвоение объектов, как в примерах здесь и выше, сработает, и позволит вам динамически создавать цепочки прототипов. +Но присвоение объектов, как в примерах здесь и выше, работает, и позволяет вам создавать цепочки прототипов динамически. ### Производительность diff --git a/doc/ru/other/timeouts.md b/doc/ru/other/timeouts.md index 5d3b26f3..2269f72b 100644 --- a/doc/ru/other/timeouts.md +++ b/doc/ru/other/timeouts.md @@ -39,11 +39,11 @@ В приведённом примере `foo` в первый же раз заблокирует своим процессом главный поток на одну секунду. -Пока `foo` блокирует код, `setInterval` продолжает планировать последующие её вызовы. Теперь, когда первая `foo` закончила выполнение, в очереди будут уже **десять** ожидающих выполнения вызовов `foo`. +Пока `foo` блокирует код, `setInterval` продолжает планировать последующие её вызовы. Теперь, когда первая `foo` закончила выполнение, в очереди будет уже **десяток** ожидающих выполнения вызовов `foo`. ### Разбираемся с потенциальной блокировкой кода -Самый простой и наиболее легко контролируемый способ — использовать `setTimeout` внутри такой функции. +Самый простой и легко контролируемый способ — использовать `setTimeout` внутри такой функции. function foo(){ // что-то, выполняющееся одну секунду или более @@ -51,9 +51,9 @@ } foo(); -Такой способ не только инкапсулирует вызов `setTimeout`, но и предотвращает от очередей блокирующих вызовов и при этом обеспечивает дополнительный контроль. Сама функция `foo` теперь принимает решение, хочет ли она запускаться ещё раз или нет. +Такой способ не только инкапсулирует вызов `setTimeout`, но и предотвращает от очередей блокирующих вызовов и при этом обеспечивает дополнительный контроль: сама функция `foo` теперь принимает решение, хочет ли она запускаться ещё раз или нет. -(''прим. перев.'' — такая техника теперь активно используется при использовании браузерного метода `requestAnimationFrame` для анимации, работающей на `canvas`). +(_прим. перев._ — такая техника сейчас активно используется для привязывания браузерного метода `requestAnimationFrame` к анимации, работающей на базе `canvas`). ### Сброс таймаутов вручную @@ -64,7 +64,7 @@ ### Сброс всех таймаутов -Из-за того, что встроенного метода для удаления всех созданных таймаутов и/или интервалов не существует, для успешного достижения этой цели приходится использовать силу. +Из-за того, что встроенного метода для удаления всех созданных таймаутов и/или интервалов не существует, даже ради просто приемлимого достижения этой цели приходится использовать силу. // сбрасываем «все» таймауты for(var i = 1; i < 1000; i++) { @@ -82,7 +82,7 @@ clearTimeout(i); } -Однако, даже при том, что такой код работает сегодня во всех современных браузерах, нигде не указано и не гарантируется, что значения ID всегда увеличиваются. Поэтому, всё же, рекомендуется следить за *каждым* идентификатором *каждого* создающегося таймаута — это позволит вам надёжно контролировать процесс, сбрасывая их индивидуально. +Однако, даже при том, что такой код работает сегодня во всех современных браузерах, нигде не указано и не гарантируется, что значения ID всегда увеличиваются. Поэтому, всё же, рекомендуется следить за *каждым* идентификатором *каждого* создающегося таймаута — это позволит вам уверенно контролировать процесс, сбрасывая их индивидуально. ### Скрытое использование `eval` @@ -104,7 +104,7 @@ Поскольку `eval` в этом случае не вызывается [явно](#core.eval), переданная в `setTimeout` строка будет выполнена в *глобальной области видимости*; так что локальная функция `foo` из области видимости `bar` вообще не будет выполнена. -По этим же причинам **не рекомендуется** использовать строковое представление вызова функции для передачи аргументов в функцию, которая должна быть вызвана посредством любого из двух известных способов назначения таймаутов. +По этим же причинам **не рекомендуется** использовать строковое представление вызова функции для передачи аргументов в функцию, которая должна быть вызвана посредством одного из двух известных способов назначения таймаутов. function foo(a, b, c) {} @@ -120,9 +120,9 @@ ### Заключение -**Никогда** не используйте строки как параметры для `setTimeout` или `setInterval`. Это явный признак **действительно** плохого кода. Если вызываемой функции необходимо передавать аргументы, лучше передавать *анонимную функцию*, которая самостоятельно будет отвечать за сам вызов. +**Никогда** не используйте строки как параметры для `setTimeout` или `setInterval`. Это явный признак **действительно** плохого кода. Если вызываемой функции необходимо передать аргументы, лучше передавать *анонимную функцию*, которая самостоятельно будет отвечать за сам вызов. -Кроме прочего, избегайте использования `setInterval` в случаях, когда его планировщик может заблокировать выполнение основного кода JavaScript. +Кроме того, избегайте использования `setInterval`, поскольку его планировщик не блокируется выполняемым кодом. [1]: http://ru.wikipedia.org/wiki/Document_Object_Model "Document Object Model" diff --git a/doc/ru/types/casting.md b/doc/ru/types/casting.md index 01ca7fd4..0160c0b1 100644 --- a/doc/ru/types/casting.md +++ b/doc/ru/types/casting.md @@ -28,9 +28,9 @@ JavaScript — язык, в котором господствует *слаба Number(10) === 10; // True: Number и Number new Number(10) + 0 === 10; // True: из-за неявного преобразования -Использование встроенных типов, таких как `Number`, с конструктором, создаёт новый экземпляр объекта `Number`, но использование без ключевого слова `new` создаёт функцию `Number`, которая будет вести себя в равенствах как конвертер. +Использование встроенных типов, таких как `Number`, с конструктором, создаёт новый экземпляр объекта `Number`, но использование без ключевого слова `new` создаёт функцию `Number`, которая будет вести себя в равенствах как «преобразователь». -Кроме того, присутствие в равенствах литералов или переменных, которые не являются объектами, повлечёт лишь более серьёзное насилие над типами. +Кроме того, присутствие в равенствах дополнительных литералов или переменных, которые не являются объектами, повлечёт за собой лишь ещё больше преобразований типов. Лучший вариант — это **явное** приведение к одному из трех возможных типов. @@ -38,13 +38,13 @@ JavaScript — язык, в котором господствует *слаба '' + 10 === '10'; // true -Путём добавления в начале пустой строки, значение легко приводится к строке. +Путём добавления в начало пустой строки, значение легко приводится к строке. ### Приведение к числовому типу +'10' === 10; // true -Используя **унарный** оператор плюс, можно преобразовать значение в число. +Применив **унарный** оператор плюс, можно преобразовать значение в число. ### Приведение к булеву типу diff --git a/doc/ru/types/typeof.md b/doc/ru/types/typeof.md index 573e73aa..ee7359cf 100644 --- a/doc/ru/types/typeof.md +++ b/doc/ru/types/typeof.md @@ -2,7 +2,7 @@ Оператор `typeof` (вместе с [`instanceof`](#types.instanceof)) — это, вероятно, самая большая недоделка в JavaScript, поскольку с накоплением опыта выясняется, что он **поломан, разве что не полностью**. -При том, число поводов для применения `instanceof` ограничено, `typeof` вообще имеет *один-единственный* практический случай применения, который при всём при этом, неожиданно,.. **не** оказывается проверкой типа объекта. +Учитывая, что число возможных поводов для применения `instanceof` довольно ограничено, важно отметить, что `typeof` вообще имеет *один-единственный* практический случай применения, который при всём при этом, неожиданно,.. **не** оказывается проверкой типа объекта. > **Замечаение:** Хотя для вызова `typeof` также можно использовать синтаксис функции, т.е. `typeof(obj)`, на самом деле это вовсе не функция. Да — двойные круглые скобки будут работать нормально и возвращаемое значение будет использоваться как операнд оператора `typeof`, но функции `typeof` — **не существует**. @@ -32,7 +32,7 @@ > **Из спецификации:** Значением `[[Class]]` может быть одна из следующих строк: `Arguments`, `Array`, `Boolean`, `Date`, `Error`, `Function`, `JSON`, `Math`, `Number`, `Object`, `RegExp`, `String`. -Чтобы получить значение `[[Class]]`, нужно применить к интересующему объекту метод `toString` из прототипа `Object.prototype`. (''прим. перев.'' — то есть не вызвать метод у самого объекта, а именно применить к нему метод из прототипа, см. ниже). +Чтобы получить значение `[[Class]]`, нужно применить к интересующему объекту метод `toString` из прототипа `Object.prototype`. (_прим. перев._ — то есть не вызвать метод у самого объекта, а именно применить к нему метод из прототипа, см. ниже). ### Класс объекта From b8745270d131e69c9bd58e2981f4458959912505 Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Fri, 24 May 2013 02:29:28 +0200 Subject: [PATCH 29/41] somehow affected polish translation --- doc/pl/intro/authors.md | 14 +++++++------- doc/pl/intro/contributors.md | 14 +++++++------- doc/pl/intro/hosting.md | 12 ++++++------ doc/pl/intro/license.md | 22 +++++++++++----------- doc/pl/intro/translators.md | 14 +++++++------- doc/ru/array/general.md | 2 +- doc/ru/types/typeof.md | 2 +- 7 files changed, 40 insertions(+), 40 deletions(-) diff --git a/doc/pl/intro/authors.md b/doc/pl/intro/authors.md index 7cc692fd..380c158e 100644 --- a/doc/pl/intro/authors.md +++ b/doc/pl/intro/authors.md @@ -1,8 +1,8 @@ -## Autorzy - -Ten przewodnik jest dziełem dwóch uroczych użytkowników [Stack Overflow][1], -[Ivo Wetzel][2] (Treść) oraz [Zhang Yi Jiang][3] (Projekt). - -[1]: http://stackoverflow.com/ -[2]: http://stackoverflow.com/users/170224/ivo-wetzel +## Autorzy + +Ten przewodnik jest dziełem dwóch uroczych użytkowników [Stack Overflow][1], +[Ivo Wetzel][2] (Treść) oraz [Zhang Yi Jiang][3] (Projekt). + +[1]: http://stackoverflow.com/ +[2]: http://stackoverflow.com/users/170224/ivo-wetzel [3]: http://stackoverflow.com/users/313758/yi-jiang \ No newline at end of file diff --git a/doc/pl/intro/contributors.md b/doc/pl/intro/contributors.md index 6c8ca72a..7fc5675d 100644 --- a/doc/pl/intro/contributors.md +++ b/doc/pl/intro/contributors.md @@ -1,7 +1,7 @@ -## Współtwórcy - - - [Caio Romão][1] (Poprawki pisowni) - - [Andreas Blixt][2] (Poprawki językowe) - -[1]: https://github.com/caio -[2]: https://github.com/blixt +## Współtwórcy + + - [Caio Romão][1] (Poprawki pisowni) + - [Andreas Blixt][2] (Poprawki językowe) + +[1]: https://github.com/caio +[2]: https://github.com/blixt diff --git a/doc/pl/intro/hosting.md b/doc/pl/intro/hosting.md index 4f766e43..19ac9028 100644 --- a/doc/pl/intro/hosting.md +++ b/doc/pl/intro/hosting.md @@ -1,6 +1,6 @@ -## Hosting -JavaScript Garden znajduje się na serwerach GitHub, ale dzięki wsparciu -[Cramer Development] [1] posiadamy również mirror na serwerze [JavaScriptGarden.info] [2]. - -[1]: http://cramerdev.com/ -[2]: http://javascriptgarden.info/ +## Hosting +JavaScript Garden znajduje się na serwerach GitHub, ale dzięki wsparciu +[Cramer Development] [1] posiadamy również mirror na serwerze [JavaScriptGarden.info] [2]. + +[1]: http://cramerdev.com/ +[2]: http://javascriptgarden.info/ diff --git a/doc/pl/intro/license.md b/doc/pl/intro/license.md index 4d244a83..5b0e855d 100644 --- a/doc/pl/intro/license.md +++ b/doc/pl/intro/license.md @@ -1,11 +1,11 @@ -## Licencja - -JavaScript Garden jest publikowany w ramach [licencji MIT] [1] i kod źródłowy znajduje -się na serwerze [GitHub] [2]. Jeśli znajdziesz jakieś błędy lub literówki, zgłoś proszę -[problem] [3] lub rozwiąż go i zgloś pull request ze swojego repozytorium. -Możesz nas także znaleźć w pokoju [JavaScript] [4] na chacie Stack Overflow. - -[1]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE -[2]: https://github.com/BonsaiDen/JavaScript-Garden -[3]: https://github.com/BonsaiDen/JavaScript-Garden/issues -[4]: http://chat.stackoverflow.com/rooms/17/javascript +## Licencja + +JavaScript Garden jest publikowany w ramach [licencji MIT] [1] i kod źródłowy znajduje +się na serwerze [GitHub] [2]. Jeśli znajdziesz jakieś błędy lub literówki, zgłoś proszę +[problem] [3] lub rozwiąż go i zgloś pull request ze swojego repozytorium. +Możesz nas także znaleźć w pokoju [JavaScript] [4] na chacie Stack Overflow. + +[1]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE +[2]: https://github.com/BonsaiDen/JavaScript-Garden +[3]: https://github.com/BonsaiDen/JavaScript-Garden/issues +[4]: http://chat.stackoverflow.com/rooms/17/javascript diff --git a/doc/pl/intro/translators.md b/doc/pl/intro/translators.md index a766a003..5197a9fd 100644 --- a/doc/pl/intro/translators.md +++ b/doc/pl/intro/translators.md @@ -1,7 +1,7 @@ -## Tłumaczenie - - - [Łukasz Kufel][1] - - [Maciej Ciemborowicz][2] - -[1]: http://qfel13.pl -[2]: http://blog.ciemborowicz.pl +## Tłumaczenie + + - [Łukasz Kufel][1] + - [Maciej Ciemborowicz][2] + +[1]: http://qfel13.pl +[2]: http://blog.ciemborowicz.pl diff --git a/doc/ru/array/general.md b/doc/ru/array/general.md index 41b703bb..8d3afcd8 100644 --- a/doc/ru/array/general.md +++ b/doc/ru/array/general.md @@ -1,6 +1,6 @@ ##  Перебор массивов и свойств объектов -Несмотря на то, что массивы в JavaScript являются объектами, достаточных оснований использовать [цикл `for in`](#object.forinloop) для перебора элементов массива **не существует**. Наоборот, существует достаточно хороших причин **против** использования `for in` с массивами. +Несмотря на то, что массивы в JavaScript являются объектами, достаточных оснований использовать [цикл `for in`](#object.forinloop) для перебора элементов массива **не существует**. Наоборот, существует достаточно весомых причин **против** использования `for in` с массивами. > **Замечание:** Массивы в JavaScript **не** являются *ассоциативными массивами*. Для связывания ключей и значений в JavaScript есть только [объекты](#object.general). При этом, ассоциативные массивы априори **сохраняют** заданный порядок свойств, объекты же **не** делают этого. diff --git a/doc/ru/types/typeof.md b/doc/ru/types/typeof.md index ee7359cf..5ab136c0 100644 --- a/doc/ru/types/typeof.md +++ b/doc/ru/types/typeof.md @@ -2,7 +2,7 @@ Оператор `typeof` (вместе с [`instanceof`](#types.instanceof)) — это, вероятно, самая большая недоделка в JavaScript, поскольку с накоплением опыта выясняется, что он **поломан, разве что не полностью**. -Учитывая, что число возможных поводов для применения `instanceof` довольно ограничено, важно отметить, что `typeof` вообще имеет *один-единственный* практический случай применения, который при всём при этом, неожиданно,.. **не** оказывается проверкой типа объекта. +Учитывая, что число потенциальных поводов для применения `instanceof` довольно ограничено, важно отметить, что `typeof` вообще имеет *один-единственный* практический случай применения, который при всём при этом, неожиданно,.. **не** оказывается проверкой типа объекта. > **Замечаение:** Хотя для вызова `typeof` также можно использовать синтаксис функции, т.е. `typeof(obj)`, на самом деле это вовсе не функция. Да — двойные круглые скобки будут работать нормально и возвращаемое значение будет использоваться как операнд оператора `typeof`, но функции `typeof` — **не существует**. From 74c20e710762303092996e4efc66dea956cc6f46 Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Fri, 24 May 2013 02:43:50 +0200 Subject: [PATCH 30/41] some more minors --- doc/ru/object/general.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ru/object/general.md b/doc/ru/object/general.md index 176f4c60..42fba1c1 100644 --- a/doc/ru/object/general.md +++ b/doc/ru/object/general.md @@ -13,7 +13,7 @@ 2.toString(); // вызывает SyntaxError -Есть несколько способов обойти этот недостаток и любой из них подойдёт, если от числового значения нужно добиться поведения объекта: +Есть несколько способов обойти этот недостаток, и любой из них подойдёт, если от числового значения нужно добиться поведения объекта: 2..toString(); // вторая точка распознаётся корректно 2 .toString(); // обратите внимание на пробел перед точкой From 9e85ab40edc5333a1a7bdd087160fbaa1d105eb7 Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Fri, 24 May 2013 02:44:45 +0200 Subject: [PATCH 31/41] newline --- doc/pl/intro/authors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/pl/intro/authors.md b/doc/pl/intro/authors.md index 380c158e..26a567dc 100644 --- a/doc/pl/intro/authors.md +++ b/doc/pl/intro/authors.md @@ -5,4 +5,4 @@ Ten przewodnik jest dziełem dwóch uroczych użytkowników [Stack Overflow][1], [1]: http://stackoverflow.com/ [2]: http://stackoverflow.com/users/170224/ivo-wetzel -[3]: http://stackoverflow.com/users/313758/yi-jiang \ No newline at end of file +[3]: http://stackoverflow.com/users/313758/yi-jiang From 94f04284ac986f8d26468abe1459fdc0a9925bab Mon Sep 17 00:00:00 2001 From: Anton Date: Thu, 16 Jan 2014 15:55:34 +0200 Subject: [PATCH 32/41] Update eval.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Запутанный перевод был, упростил и пояснил я его :) --- doc/ru/core/eval.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/ru/core/eval.md b/doc/ru/core/eval.md index dbbe5190..c197a78e 100644 --- a/doc/ru/core/eval.md +++ b/doc/ru/core/eval.md @@ -1,6 +1,6 @@ ## Почему нельзя использовать `eval` -Функция `eval` выполняет переданный строкой код JavaScript в локальной области видимости. +Функция `eval` выполнит переданную строку как код JavaScript в локальной области видимости: var foo = 1; function test() { @@ -11,7 +11,7 @@ test(); // 3 foo; // 1 -Однако, функция `eval` выполняет указанный код в локальной области видимости тогда и только тогда, когда она вызывается явно *и при этом* имя вызывающейся функции *идентично* `eval` (_прим. перев._ — ох!). +Но только тогда, когда функция `eval` вызывается явно *и при этом* имя вызываемой функции *идентично* `eval` (_прим. перев._ — ох! вот вам анти-пример): var foo = 1; function test() { @@ -35,5 +35,5 @@ ### Заключение -Использовать `eval` не стоит никогда: любой код с участием этой функции автоматически порождает вопросы о качестве его работы, производительности и безопасности. Если вдруг для работы вам необходим `eval`, эта часть кода должна тут же ставиться под сомнение и в первую очередь *исключаться* из проекта — необходимо найти *лучший способ*, которому не требуются вызовы `eval`. +Никогда не стоит использовать `eval`: любой код с участием этой функции автоматически порождает вопросы о качестве его работы, производительности и безопасности. Если вдруг для работы вам необходим `eval`, эта часть кода должна тут же ставиться под сомнение и в первую очередь *исключаться* из проекта — необходимо найти *лучший способ*, которому не требуются вызовы `eval`. From 1188f3e095cf51b02e188ba933fe155469ba3a39 Mon Sep 17 00:00:00 2001 From: heckfy Date: Wed, 3 Dec 2014 18:10:02 +0300 Subject: [PATCH 33/41] small correction --- doc/ru/function/scopes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ru/function/scopes.md b/doc/ru/function/scopes.md index f0dd027f..ba147930 100644 --- a/doc/ru/function/scopes.md +++ b/doc/ru/function/scopes.md @@ -173,7 +173,7 @@ JavaScript **«вытягивает»** определения. Это знач })(); // сразу же выполнить функцию -Безымянные функции являются отложенными [выражениями](#function.general) (_прим. перев._ — то есть, они не разбираются по месту описания, а откладываются парсером напоследок); поэтому, чтобы вы сделать их исполняемыми, следует спровоцировать их разбор. +Безымянные функции являются отложенными [выражениями](#function.general) (_прим. перев._ — то есть, они не разбираются по месту описания, а откладываются парсером напоследок); поэтому, чтобы сделать их исполняемыми, следует спровоцировать их разбор. ( // разобрать функцию внутри скобок function() {} From 830a92c503a78382c5254d2a6cd3c74921e40994 Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Wed, 14 Jun 2017 02:12:43 +0200 Subject: [PATCH 34/41] Update `doc/pl/intro/authors.md` with the `upstream` version, it shouldn't be a conflict --- doc/pl/intro/authors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/pl/intro/authors.md b/doc/pl/intro/authors.md index 26a567dc..380c158e 100644 --- a/doc/pl/intro/authors.md +++ b/doc/pl/intro/authors.md @@ -5,4 +5,4 @@ Ten przewodnik jest dziełem dwóch uroczych użytkowników [Stack Overflow][1], [1]: http://stackoverflow.com/ [2]: http://stackoverflow.com/users/170224/ivo-wetzel -[3]: http://stackoverflow.com/users/313758/yi-jiang +[3]: http://stackoverflow.com/users/313758/yi-jiang \ No newline at end of file From 911cc09b75e174244095b32938d7aaeb0e9ebc1c Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Wed, 14 Jun 2017 02:17:36 +0200 Subject: [PATCH 35/41] forgotten changes to `forniloop.md` --- doc/ru/object/forinloop.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ru/object/forinloop.md b/doc/ru/object/forinloop.md index e54ad756..53633591 100644 --- a/doc/ru/object/forinloop.md +++ b/doc/ru/object/forinloop.md @@ -25,7 +25,7 @@ } } -Это единственно правильная версия выполнения такого цикла. За счёт использования `hasOwnProperty` будет выведено одно **только** свойство `moo`. Если же вы уберёте проверку `hasOwnProperty`, код станет нестабилен и, если кто-то позволил себе изменить прототипы встроенных типов, такие как `Object.prototype`, вам грозят непредвиденные сюрпризы. +Это единственно правильная версия выполнения такого цикла. За счёт использования `hasOwnProperty` будет выведено одно **только** свойство `moo`. Если же вы уберёте проверку `hasOwnProperty`, код станет нестабилен и, если кто-то всё же позволил себе изменить прототипы встроенных типов, такие как `Object.prototype`, вам грозят непредвиденные сюрпризы. Один из самых популярных фреймворков [Prototype][1] использует упомянутое расширение `Object.prototype` — и если вы его подключаете — ни в коем случае не забывайте использовать `hasOwnProperty` внутри всех циклов `for in` — иначе у вас гарантированно возникнут проблемы. From 34837a03c448fece614272e6aa821acc67598110 Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Sun, 2 Jul 2017 13:10:14 +0200 Subject: [PATCH 36/41] lots of re-applied fixes from the original repository + some wording improvements --- CONTRIBUTING.md | 2 +- doc/ru/array/constructor.md | 2 +- doc/ru/core/delete.md | 4 ++-- doc/ru/core/semicolon.md | 4 ++-- doc/ru/core/undefined.md | 2 +- doc/ru/function/constructors.md | 6 +++--- doc/ru/function/general.md | 2 +- doc/ru/function/scopes.md | 20 ++++++++++---------- doc/ru/function/this.md | 6 +++--- doc/ru/object/general.md | 2 +- doc/ru/object/prototype.md | 4 ++-- doc/ru/other/timeouts.md | 4 ++-- doc/ru/types/equality.md | 4 ++-- doc/ru/types/instanceof.md | 6 +++--- doc/ru/types/typeof.md | 2 +- 15 files changed, 35 insertions(+), 35 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fe3c6b6f..20faf510 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,7 +9,7 @@ Thank you for being kind enough to help out! ## Testing locally -1. Run `npm run build` to build +1. Run `npm run build.js` to build 1. Run a webserver from the root of the repo to view ## Getting changes merged diff --git a/doc/ru/array/constructor.md b/doc/ru/array/constructor.md index 2db28c9d..aac276b2 100644 --- a/doc/ru/array/constructor.md +++ b/doc/ru/array/constructor.md @@ -15,7 +15,7 @@ arr[1]; // не определён, undefined 1 in arr; // false, индекс не был установлен -Поведение, позволяющее заранее установить размер массива, может пригодиться лишь в нескольких случаях — таких, как повторение строки, с помощью которого вы можете избежать использования `for loop`. +Поведение, позволяющее заранее установить размер массива, может пригодиться лишь в нескольких случаях — таких, как повторение строки, с помощью которого вы можете избежать использования `for`. new Array(count + 1).join(stringToRepeat); diff --git a/doc/ru/core/delete.md b/doc/ru/core/delete.md index 579fd7ff..d18d26be 100644 --- a/doc/ru/core/delete.md +++ b/doc/ru/core/delete.md @@ -1,10 +1,10 @@ ## Оператор `delete` -Если кратко — в JavaScript невозможно удалить глобальную переменную или функцию или какую-либо другую сущность, у которой установлен атрибут `DontDelete`. +Если говорить кратко — в JavaScript невозможно удалить глобальную переменную или функцию или любую другую сущность, у которой установлен атрибут `DontDelete`. ### Глобальный код и код внутри функций -Когда переменная или функция определена в глобальной области видимости или в [области видимости функции](#function.scopes), её судьба предопределена: (_прим. перев._ — где-то внутри движка JavaScript) она является свойством либо объекта Activation, либо объекта Global. Подобные свойства имеют набор атрибутов, одним из которых и является +Когда переменная или функция определена в глобальной области видимости или в [области видимости функции](#function.scopes), её судьба предопределена: (_прим. перев._ — где-то внутри движка JavaScript) она является свойством (`property`) либо объекта `Activation`, либо объекта `Global`. Подобные свойства имеют набор атрибутов, одним из которых и является упомянутый ранее `DontDelete`. Переменные и объявления функций, замеченные движком в глобальной области или в коде функции, создаются с атрибутом `DontDelete` и посему не могут быть удалены. // глобальная переменная: diff --git a/doc/ru/core/semicolon.md b/doc/ru/core/semicolon.md index 3f8083d7..31eb0f37 100644 --- a/doc/ru/core/semicolon.md +++ b/doc/ru/core/semicolon.md @@ -89,11 +89,11 @@ log('тестируем!') (options.list || []).forEach(function(i) {}) -Такой код трасформируется в одну склеенную строку. +Такой код трансформируется в одну склеенную строку. log('тестируем!')(options.list || []).forEach(function(i) {}) -**Чрезвычайно** высоки шансы того, что `log` **не** возращает *никаких* функций; таким образом, выполнение этой строки кода породит `TypeError` с сообщением о том, что `undefined не является функцией`. +**Чрезвычайно** высоки шансы того, что `log` **не** возвращает *никаких* функций; таким образом, выполнение этой строки кода породит `TypeError` с сообщением о том, что `undefined не является функцией`. ### Заключение diff --git a/doc/ru/core/undefined.md b/doc/ru/core/undefined.md index 2afab764..3693109e 100644 --- a/doc/ru/core/undefined.md +++ b/doc/ru/core/undefined.md @@ -8,7 +8,7 @@ Кроме этого, в языке определена глобальная переменная со значением `undefined`, причём эта переменная так и называется — `undefined`. Не являясь константой, она не является и ключевым словом. Из этого следует, что её значение можно с лёгкостью переопределить. -> **ES5 Замечание:** в ECMAScript 5 переменная `undefined` **уже не** *доступна на запись* в strict-режиме, однако она всё так же может быть перегружена по имени, например - функцией с именем `undefined`. +> **ES5 Замечание:** в ECMAScript 5 переменная `undefined` **уже не** *доступна на запись* в strict-режиме, однако она всё так же может быть перегружена по имени, например — функцией с именем `undefined`. Список случаев, когда код возвращает значение `undefined`: diff --git a/doc/ru/function/constructors.md b/doc/ru/function/constructors.md index 62639c15..3dd76d38 100644 --- a/doc/ru/function/constructors.md +++ b/doc/ru/function/constructors.md @@ -70,7 +70,7 @@ ### Создание объектов с использованием фабрик -Нередко встречаются советы **не** использовать оператор `new`, поскольку если вы забудете его написать, это может привести к потенциальным ошибкам. +Многие **не** рекомендуют использовать оператор `new`, поскольку если вы забудете его написать, такое «необдуманное» действие может привести к ошибкам. Чтобы создать новый объект, нам предлагают использовать фабрику и создать новый объект *внутри* этой фабрики. @@ -89,7 +89,7 @@ return obj; } -Хотя данный пример и сработает, если вы забыли ключевое слово `new` и, возможно, благодаря ему вам станет легче работать с [приватными переменными](#function.closures), у него есть несколько недостатков: +Хотя данный пример и сработает, если вы забыли ключевое слово `new`, и благодаря ему вам станет легче работать с [приватными переменными](#function.closures), у него есть несколько недостатков: 1. Он использует больше памяти, поскольку созданные объекты **не** хранят методы в прототипе и соответственно для каждого нового объекта создаётся копия каждого метода; 2. Чтобы эмулировать наследование, фабрике нужно скопировать все методы из другого объекта или установить прототипом нового объекта старый; @@ -97,5 +97,5 @@ ### Заключение -Хотя забытое ключевое слово `new` и может привести к багам, это точно **не** причина отказываться от использования прототипов. В конце концов, полезнее решить какой из способов лучше совпадает с требованиями приложения: крайне важно выбрать один из стилей создания объектов и после этого **не изменять** ему. +Хотя забытое ключевое слово `new` и может привести к багам, это точно **не** причина отказываться от использования прототипов. В конце концов, полезнее решить, какой из способов лучше совпадает с требованиями приложения: крайне важно выбрать один из стилей создания объектов и после этого **не изменять** ему. diff --git a/doc/ru/function/general.md b/doc/ru/function/general.md index d09f2638..251529e6 100644 --- a/doc/ru/function/general.md +++ b/doc/ru/function/general.md @@ -27,7 +27,7 @@ Но поскольку сами *присвоения* исполняются только непосредственно во время работы кода, `foo` по умолчанию будет иметь лишь значение [`undefined`](#core.undefined) (до обработки строки с определением функции). -### Выражения с именованными фунциями +### Выражения с именованными функциями Существует еще один нюанс, касающийся присваиваний именованных функций: diff --git a/doc/ru/function/scopes.md b/doc/ru/function/scopes.md index f3ad7242..85fb57af 100644 --- a/doc/ru/function/scopes.md +++ b/doc/ru/function/scopes.md @@ -36,7 +36,7 @@ test(); foo; // 21 -Из-за того что оператор `var` был опущен внутри функции, фунция `test` перезапишет значение `foo`. Это поначалу может показаться не такой уж и большой проблемой, но если у вас имеется тысяча строк JavaScript-кода и вы не используете `var`, то вам на пути встретятся самые страшные и трудноотлаживаемые ошибки — и это не шутка. +Из-за того что оператор `var` был опущен внутри функции, функция `test` перезапишет значение `foo`. Это поначалу может показаться не такой уж и большой проблемой, но если у вас имеется тысяча строк JavaScript-кода и вы не используете `var`, то вам на пути встретятся самые страшные и трудноотлаживаемые ошибки — и это не шутка. // глобальная область видимости var items = [/* какой-то список */]; @@ -73,9 +73,9 @@ В то время как `foo` и `i` — локальные переменные в области видимости функции `test`, присвоение `bar` переопределит значение одноимённой глобальной переменной. -### Вытягивание +### Всплытие -JavaScript **«вытягивает»** определения. Это значит, что оба определения с использованием `var` и определение `function` будут перенесены наверх из заключающей их области видимости. +В JavaScript действует механизм **всплытия** (или *вытягивания*) определения. Это значит, что оба определения с использованием `var` и определение `function` будут перенесены наверх из заключающей их области видимости. bar(); var bar = function() {}; @@ -116,16 +116,16 @@ JavaScript **«вытягивает»** определения. Это знач bar(); // вылетает с ошибкой TypeError, // поскольку bar всё ещё 'undefined' - someValue = 42; // присвоения не зависят от вытягивания + someValue = 42; // присвоения не подвержены всплытию bar = function() {}; test(); -Потерянная область видимости не только переместит операторы `var` вовне циклов и их тел, но и лишит смысла конструкцию c `if. +Потерянная область видимости не только переместит операторы `var` вовне циклов и их тел, но и лишит смысла конструкцию c `if`. -Предполагалось, что в исходном коде оператор `if` изменял *глобальную переменную* `goo`, однако, как оказалось, он изменял *локальную переменную* — в результате работы вытягивания. +Предполагалось, что в исходном коде оператор `if` изменял *глобальную переменную* `goo`, однако, как оказалось, он изменял *локальную переменную* — в результате работы всплытия. -Если вы не знакомы с *вытягиваниями*, то можете предположить, что нижеприведённый код должен выбросить `ReferenceError`. +Если вы не имели дела с *всплытием*, то можете предположить, что нижеприведённый код должен выбросить `ReferenceError`. // проверить, проинициализована ли SomeImportantThing if (!SomeImportantThing) { @@ -154,14 +154,14 @@ JavaScript **«вытягивает»** определения. Это знач 1. Если в текущей области видимости есть выражение `var foo`, использовать эту переменную; 2. Если один из параметров функции называется `foo`, использовать этот параметр; - 3. Если функциия сама называется `foo`, использовать её; + 3. Если функция сама называется `foo`, использовать её; 4. Перейти на одну область видимости выше и повторить, начиная с **п. 1**; > **Замечание:** Наличие параметра функции с именем `arguments` **не позволит** движку создать объект `arguments`, создающийся, в других случаях, по умолчанию. ### Пространства имён -Нередко можно столкнуться с неприятным последствием единого глобального пространства имён — проблемы с перекрытием имён переменных. В JavaScript эту проблему легко избежать, используя *анонимные обёртки*. +Нередко можно столкнуться с неприятным последствием единого глобального пространства имён — проблема с перекрытием имён переменных. В JavaScript эту проблему легко избежать, используя *анонимные обёртки*. (function() { // самодостаточное «пространство имён» @@ -172,7 +172,7 @@ JavaScript **«вытягивает»** определения. Это знач })(); // сразу же выполнить функцию -Безымянные функции являются отложенными [выражениями](#function.general) (_прим. перев._ — то есть, они не разбираются по месту описания, а откладываются парсером напоследок); поэтому, чтобы сделать их исполняемыми, следует спровоцировать их разбор. +Безымянные функции являются отложенными [выражениями](#function.general) (_прим. перев._ — то есть они не разбираются по месту описания, а откладываются парсером напоследок); поэтому, чтобы сделать их исполняемыми, следует спровоцировать их разбор. ( // разобрать функцию внутри скобок function() {} diff --git a/doc/ru/function/this.md b/doc/ru/function/this.md index dafa09b3..b13e3cb1 100644 --- a/doc/ru/function/this.md +++ b/doc/ru/function/this.md @@ -26,7 +26,7 @@ new foo(); -Если перед вызовом функции присутствует ключевое слово `new` то данная функция будет действовать как [конструктор](#function.constructors). Внутри такой функции `this` будет указывать на *новый созданный* `Object`. +Если перед вызовом функции присутствует ключевое слово `new`, то данная функция будет действовать как [конструктор](#function.constructors). Внутри такой функции `this` будет указывать на *новый созданный* `Object`. ### 5. Переопределение `this` @@ -38,7 +38,7 @@ Когда мы используем методы `call` или `apply` из `Function.prototype`, то внутри вызываемой функции `this` **явным образом** будет присвоено значение первого передаваемого параметра. -Исходя из этого, в предыдущем примере (строка с `apply`), правило №3 *«вызов метода»* **не** будет применёно, и `this` внутри `foo` будет присвоено `bar`. +Исходя из этого, в предыдущем примере (строка с `apply`), правило №3 *«вызов метода»* **не** будет применено, и `this` внутри `foo` будет присвоено `bar`. > **Замечание:** `this` **нельзя** использовать внутри литералов `{}` (`Object`) для ссылки на сам объект. Т.е. если мы напишем `var obj = {me: this}`, то `me` не будет ссылаться на `obj`, поскольку `this` присваивается только по одному из пяти описанных правил. @@ -65,7 +65,7 @@ test(); }; -Подходящее имя для такой переменной — `that`, и его часто используют для ссылки на внешний `this`. В комбинации с [замыканиями](#function.closures) такая переменная может использоваться, чтобы «пробрасывать» `this` в глобальную область, или в любой другой объект. +Подходящее имя для такой переменной — `that`, и его часто используют для ссылки на внешний `this`. В комбинации с [замыканиями](#function.closures) такая переменная может использоваться, чтобы «пробрасывать» `this` в глобальную область или в любой другой объект. ### Присвоение методов diff --git a/doc/ru/object/general.md b/doc/ru/object/general.md index ad7cc364..e052ea4e 100644 --- a/doc/ru/object/general.md +++ b/doc/ru/object/general.md @@ -50,7 +50,7 @@ Единственный способ полностью удалить свойство у объекта — использовать оператор `delete`; устанавливая свойство в `undefined` или `null`, вы только заменяете связанное с ним *значение*, но не удаляете *ключ*. -> **Замечание** от перев.: Если ссылок на значение больше нет, то сборщиком мусора удаляется и само значение, но ключ объекта при этом всё так же указывает на новое значение. +> **Замечание** от перев.: Если ссылок на значение больше нет, то сборщиком мусора удаляется и само значение, но ключ объекта при этом всё также указывает на новое значение. var obj = { bar: 1, diff --git a/doc/ru/object/prototype.md b/doc/ru/object/prototype.md index f1f6ae4c..b53b714e 100644 --- a/doc/ru/object/prototype.md +++ b/doc/ru/object/prototype.md @@ -39,7 +39,7 @@ Object.prototype { toString: ... /* и т.д. */ } -В приведённом коде объект `test` будет наследовать оба прототипа: `Bar.prototype` и `Foo.prototype`; следовательно, у него будет доступ к функции `method`, которую мы определили в прототипе `Foo`. Также, у него будет доступ к свойству `value` **одного уникального** экземпляра `Foo`, который является его прототипом. Важно заметить, что `new Bar()` при вызове **не создаёт** новый экземпляр `Foo`, а повторно использует тот объект, который был установлен ему (`Bar`) в прототипе: таким образом, все новые экземпляры `Bar` будут иметь **одно и то же** свойство `value` (_прим. перев._ — то есть, все ссылки по имени `value`, во всех экземплярах `Bar`, будут указывать на одно и то же место в памяти). +В приведённом коде объект `test` будет наследовать оба прототипа: `Bar.prototype` и `Foo.prototype`; следовательно, у него будет доступ к функции `method`, которую мы определили в прототипе `Foo`. Также, у него будет доступ к свойству `value` **одного уникального** экземпляра `Foo`, который является его прототипом. Важно заметить, что код `new Bar()` при вызове **не создаёт** новый экземпляр `Foo`, а повторно вызываеи функцию, которая была назначена его (`Bar`) прототипом: таким образом, все новые экземпляры `Bar` будут иметь **одно и то же** свойство `value` (_прим. перев._ — то есть все ссылки по имени `value`, во всех экземплярах `Bar`, будут указывать на одно и то же место в памяти). > **Замечание:** Никогда **не используйте** конструкцию `Bar.prototype = Foo`, поскольку ссылка будет указывать не на прототип `Foo`, а на объект-функцию `Foo`. Из-за этого цепочка прототипов будет проходить через `Function.prototype`, а не через `Foo.prototype`, в результате чего функция `method` вообще не будет содержаться в цепочке прототипов. @@ -71,7 +71,7 @@ Часто встречается неверное применение прототипов — расширение прототипа `Object.prototype` или прототипов одного из встроенных объектов JavaScript. -Подобная практика нарушает принцип *инкапсуляции*, и имеет соответствующее название — [monkey patching][2]. К сожалению, в основу многих широко распространенных фреймворков, например Prototype, положен принцип изменения базовых прототипов. На самом деле — до сих пор не известно разумных причин примешивать во встроенные типы *нестандартную функциональность*. +Подобная практика нарушает принцип *инкапсуляции* и имеет соответствующее название — [monkey patching][2]. К сожалению, в основу многих широко распространенных фреймворков, например Prototype, положен принцип изменения базовых прототипов. На самом деле — до сих пор не известно разумных причин примешивать во встроенные типы *нестандартную функциональность*. **Единственным** оправданием для расширения встроенных прототипов может быть только воссоздание возможностей более новых движков JavaScript, например функции [`Array.forEach`][4], которая появилась в версии 1.6. diff --git a/doc/ru/other/timeouts.md b/doc/ru/other/timeouts.md index 50851b56..8011467a 100644 --- a/doc/ru/other/timeouts.md +++ b/doc/ru/other/timeouts.md @@ -7,7 +7,7 @@ function foo() {} var id = setTimeout(foo, 1000); // возвращает число > 0 -Функция `setTimeout` возвращает идентификатор назначенного таймаута и откладывает вызов `foo` на, **примерно**, тысячу миллисекунд. Фунция `foo`, при этом, будет вызвана ровно **один** раз. +Функция `setTimeout` возвращает идентификатор назначенного таймаута и откладывает вызов `foo` на, **примерно**, тысячу миллисекунд. Функция `foo`, при этом, будет вызвана ровно **один** раз. В зависимости от разрешения таймера в используемом для запуска кода движке JavaScript, а также с учётом того, что JavaScript является однопоточным языком и посторонний код может заблокировать выполнение потока, нет **никакой** гарантии, что переданный код будет выполнен ровно через указанное в вызове `setTimeout` время. @@ -116,7 +116,7 @@ foo(1, 2, 3); }, 1000) -> **Замечание:** При том, что практически возможно использовать синтаксис `setTimeout(foo, 1000, a, b, c)`, делать это крайне не рекомендуется — такие вызовы могут привести к трудно-отлавливаемым ошибкам при операциях с [методами](#function.this). +> **Замечание:** При том, что практически возможно использовать синтаксис `setTimeout(foo, 1000, 1, 2, 3)`, делать это крайне не рекомендуется — такие вызовы могут привести к трудно-отлавливаемым ошибкам при операциях с [методами](#function.this). ### Заключение diff --git a/doc/ru/types/equality.md b/doc/ru/types/equality.md index fcc3ca39..d0da4784 100644 --- a/doc/ru/types/equality.md +++ b/doc/ru/types/equality.md @@ -26,7 +26,7 @@ JavaScript умеет сравнивать значения объектов н Оператор строгого равенства состоит из **трёх** символов равенства: `===` -Он работает также как и обычный оператор сравнения, но оператор строгого равенства **не** выполняет приведения типов между своими операндами. +Он работает так же, как и обычный оператор сравнения, но оператор строгого равенства **не** выполняет приведения типов между своими операндами. "" === "0" // false 0 === "" // false @@ -50,7 +50,7 @@ JavaScript умеет сравнивать значения объектов н var foo = {}; foo === foo; // true -Здесь оба операнда сравниваются на **идентичность**, а **не** на равенство; то есть, будет проверяться, являются ли операнды одним и тем же **экземпляром** объекта, так же как делает `is` в Python или сравниваются указатели в С. +Здесь оба операнда сравниваются на **идентичность**, а **не** на равенство; то есть будет проверяться, являются ли операнды одним и тем же **экземпляром** объекта, так же как делает `is` в Python или сравниваются указатели в С. ### Заключение diff --git a/doc/ru/types/instanceof.md b/doc/ru/types/instanceof.md index 060eb8a7..bc1a1b90 100644 --- a/doc/ru/types/instanceof.md +++ b/doc/ru/types/instanceof.md @@ -1,6 +1,6 @@ ## Оператор `instanceof` -Оператор `instanceof` сравнивает конструкторы двух операндов. Работает это только тогда, когда сравниваются пользовательские объекты. Использование же на встроенных типах почти так же бесполезно, как и [оператор typeof](#types.typeof). +Оператор `instanceof` сравнивает конструкторы двух операндов. Он работает правильно только тогда, когда сравниваются пользовательские объекты. Использование же его на встроенных типах практически так же бесполезно, как и использование [оператора typeof](#types.typeof). ### Сравнение пользовательских объектов @@ -24,9 +24,9 @@ 'foo' instanceof String; // false 'foo' instanceof Object; // false -Здесь надо отметить одну важную вещь: `instanceof` не работает на объектах, которые происходят из разных контекстов JavaScript (например, из различных документов в web-браузере), так как их конструкторы и правда не будут конструкторами *тех же самых* объектов. +Здесь необходимо отметить одну важную вещь: `instanceof` не работает с объектами, которые происходят из разных контекстов JavaScript (например, из различных документов в web-браузере), так как их конструкторы в действительности не будут конструкторами *тех же самых* объектов. ### Заключение -Оператор `instanceof` должен использоваться **только** при обращении к пользовательским объектам, происходящим из одного контекста JavaScript. Так же, как и в случае оператора `typeof`, любого другого использования `instanceof` необходимо **избегать**. +Оператор `instanceof` должен использоваться **только** при обращении к пользовательским объектам, происходящим из одного контекста JavaScript. Также, как и в случае оператора `typeof`, любого другого использования `instanceof` необходимо **избегать**. diff --git a/doc/ru/types/typeof.md b/doc/ru/types/typeof.md index f4f6fb31..dc474a0d 100644 --- a/doc/ru/types/typeof.md +++ b/doc/ru/types/typeof.md @@ -4,7 +4,7 @@ Учитывая, что число потенциальных поводов для применения `instanceof` довольно ограничено, важно отметить, что `typeof` вообще имеет *один-единственный* практический случай применения, который при всём при этом, неожиданно,.. **не** оказывается проверкой типа объекта. -> **Замечаение:** Хотя для вызова `typeof` также можно использовать синтаксис функции, т.е. `typeof(obj)`, на самом деле это вовсе не функция. Да — двойные круглые скобки будут работать нормально и возвращаемое значение будет использоваться как операнд оператора `typeof`, но функции `typeof` — **не существует**. +> **Замечание:** Хотя для вызова `typeof` также можно использовать синтаксис функции, т.е. `typeof(obj)`, на самом деле это вовсе не функция. Да — двойные круглые скобки будут работать нормально и возвращаемое значение будет использоваться как операнд оператора `typeof`, но функции `typeof` — **не существует**. ### Таблица типов JavaScript From 69987497af65e4a8e412b5c4aa695b661593148c Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Sun, 2 Jul 2017 13:12:54 +0200 Subject: [PATCH 37/41] no, `npm run build.js` is wrong` --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 20faf510..fe3c6b6f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,7 +9,7 @@ Thank you for being kind enough to help out! ## Testing locally -1. Run `npm run build.js` to build +1. Run `npm run build` to build 1. Run a webserver from the root of the repo to view ## Getting changes merged From a72d82556263e642d4d34dcd6639c1645a1cf009 Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Sun, 2 Jul 2017 14:50:03 +0200 Subject: [PATCH 38/41] new stylistic fixes, p.1 --- doc/ru/array/constructor.md | 6 +++--- doc/ru/array/general.md | 20 ++++++++++---------- doc/ru/core/delete.md | 15 +++++++-------- doc/ru/core/eval.md | 10 +++++----- doc/ru/core/semicolon.md | 14 +++++++------- doc/ru/core/undefined.md | 14 +++++++------- 6 files changed, 39 insertions(+), 40 deletions(-) diff --git a/doc/ru/array/constructor.md b/doc/ru/array/constructor.md index aac276b2..4a45b0e8 100644 --- a/doc/ru/array/constructor.md +++ b/doc/ru/array/constructor.md @@ -9,17 +9,17 @@ new Array(3); // Результат: [] new Array('3') // Результат: ['3'] -В случае, когда в конструктор `Array` передаётся только один аргумент, и этот аргумент имеет тип `Number`, конструктор возвращает новый, *разреженный* (_прим. перев._ — *заполненный случайными значениями*), массив, имеющий длину, равную значению переданного аргумента. Стоит заметить, что таким образом будет установлено лишь свойство `length` нового массива, а реальные индексы массива не будут инициализированы. +В ситуации, когда в конструктор `Array` передаётся только один аргумент, и этот аргумент имеет тип `Number` — конструктор возвращает новый, *разреженный* (_прим. перев._ — *заполненный случайными значениями*) массив, имеющий длину, равную значению переданного аргумента. Стоит заметить, что в этом случае будет установлено лишь свойство `length` нового массива, а реальные индексы массива не будут инициализированы. var arr = new Array(3); arr[1]; // не определён, undefined 1 in arr; // false, индекс не был установлен -Поведение, позволяющее заранее установить размер массива, может пригодиться лишь в нескольких случаях — таких, как повторение строки, с помощью которого вы можете избежать использования `for`. +Поведение, позволяющее заранее установить размер массива, может пригодиться лишь в некоторых случаях — например, для повторения строки — так вы сможете не использовать цикл `for`. new Array(count + 1).join(stringToRepeat); ### Заключение -Использования конструктора `Array` нужно избегать. Литералы, определённо, намного более предпочтительны — это краткая запись, она имеет более «чистый» синтаксис и повышает читабельность кода. +Использования конструктора `Array` нужно избегать. Литералы, безусловно, намного предпочтительнее — это краткая запись, её синтаксис «чище» — а это, в свою очередь повышает, читабельность кода. diff --git a/doc/ru/array/general.md b/doc/ru/array/general.md index 0f44352e..ac1b0f18 100644 --- a/doc/ru/array/general.md +++ b/doc/ru/array/general.md @@ -1,29 +1,29 @@ -##  Перебор массивов и свойств объектов +## Перебор массивов и свойств объектов -Несмотря на то, что массивы в JavaScript являются объектами, достаточных оснований использовать [цикл `for in`](#object.forinloop) для перебора элементов массива **не существует**. Наоборот, существует достаточно весомых причин **против** использования `for in` с массивами. +Несмотря на то, что массивы в JavaScript являются объектами, **не существует** достаточных оснований использовать [цикл `for in`](#object.forinloop) для перебора элементов массива. Наоборот, существует множество весомых причин **против** использования циклов `for in` при переборе массивов. -> **Замечание:** Массивы в JavaScript **не** являются *ассоциативными массивами*. Для связывания ключей и значений в JavaScript есть только [объекты](#object.general). При этом, ассоциативные массивы априори **сохраняют** заданный порядок свойств, объекты же **не** делают этого. +> **Замечание:** Массивы в JavaScript **не** являются *ассоциативными массивами*. Для группировки ключей и значений по парам в JavaScript есть только [объекты](#object.general). При этом, ассоциативные массивы по определению **сохраняют** заданный порядок свойств, объекты JavaScript этого **не** делают. Поскольку во время выполнения `for in` циклически перебираются все свойства объекта, находящиеся в его цепочке прототипов, а единственный способ исключить ненужные свойства — использовать [`hasOwnProperty`](#object.hasownproperty) — в действии такой цикл **до 20 раз** медленнее обычного цикла `for`. ### Итерирование -Для достижения лучшей производительности при переборе массивов, лучше всего использовать обычный цикл `for`. +Наилучшей производительности при переборе массивов можно достичь используя обычный цикл `for`. var list = [1, 2, 3, 4, 5, ...... 100000000]; for(var i = 0, l = list.length; i < l; i++) { console.log(list[i]); } -В примере выше есть один дополнительный приём, с помощью которого кэшируется величина длины массива: `l = list.length`. +В примере выше есть один дополнительный приём, которым кэшируется длина массива: `l = list.length`. -Несмотря на то, что свойство `length` определено в самом массиве, поиск этого свойства в объекте накладывает дополнительные расходы на каждой итерации цикла. Пусть в этом случае новые движки JavaScript и **могут** теоретически применить оптимизацию, всё же нет способа точно предугадать, будет оптимизирован код на новом движке или нет. +Несмотря на то, что свойство `length` определено в самом массиве, поиск этого свойства в прототипе объекта накладывает дополнительные расходы на каждую итерацию цикла. Да, в этом случае современные движки JavaScript и **теоретически** могут применить оптимизацию, но нет способа предугадать наверняка, будет ли оптимизирован код на используемом движке, или нет. -Фактически, цикл без кэширования может выполняться в **два раза медленнее**, нежели цикл с кэшированной длиной. +Фактически, цикл без кэширования может выполняться в **два раза медленнее**, нежели цикл с закэшированной длиной. ### Свойство `length` -Хотя *геттер* свойства `length` просто возвращает количество элементов содержащихся в массиве, *сеттер* можно использовать для **обрезания** массива. +Хотя *геттер* свойства `length` просто возвращает количество элементов содержащихся в массиве, его *сеттер* можно использовать для **обрезания** массива. var foo = [1, 2, 3, 4, 5, 6]; foo.length = 3; @@ -32,9 +32,9 @@ foo.length = 6; foo; // [1, 2, 3] -Присвоение свойству `length` меньшей величины урезает массив, однако присвоение большего значения не производит никакого эффекта. +Присвоение свойству `length` величины, меньшей чем текущая его длина, урезает массив, однако присвоение большего значения не производит никакого эффекта. ### Заключение -Для оптимальной работы кода рекомендуется всегда использовать простой цикл `for` и кэшировать свойство `length`. Использование `for in` с массивами является признаком плохого кода, содержащего потенциальные ошибки, а также приводит к низкой скорости его выполнения. +Для оптимальной работы кода рекомендуется всегда использовать обычный цикл `for` и кэшировать свойство `length`. Использование `for in` с массивами является признаком плохого кода, содержащего потенциальные ошибки, а также приводит к низкой скорости его выполнения. diff --git a/doc/ru/core/delete.md b/doc/ru/core/delete.md index d18d26be..5058236b 100644 --- a/doc/ru/core/delete.md +++ b/doc/ru/core/delete.md @@ -4,8 +4,7 @@ ### Глобальный код и код внутри функций -Когда переменная или функция определена в глобальной области видимости или в [области видимости функции](#function.scopes), её судьба предопределена: (_прим. перев._ — где-то внутри движка JavaScript) она является свойством (`property`) либо объекта `Activation`, либо объекта `Global`. Подобные свойства имеют набор атрибутов, одним из которых и является -упомянутый ранее `DontDelete`. Переменные и объявления функций, замеченные движком в глобальной области или в коде функции, создаются с атрибутом `DontDelete` и посему не могут быть удалены. +Когда переменная или функция определена в глобальной области видимости или в [области видимости функции](#function.scopes), её судьба предопределена: (_прим. перев._ — внутри движка JavaScript) она является свойством (`property`) либо объекта `Activation`, либо объекта `Global`. Подобные сущности имеют набор внутренних атрибутов, одним из которых и является упомянутый ранее `DontDelete`. Переменные и объявления функций, замеченные движком в глобальной области или в коде функций, создаются с атрибутом `DontDelete` и поэтому не могут быть удалены. // глобальная переменная: var a = 1; // установлен DontDelete @@ -24,7 +23,7 @@ ### Установленные пользователем свойства -Свойства, установленные явным образом, могут быть безпрепятственно удалены: +Свойства, установленные явно, могут быть безпрепятственно удалены: // явно установим свойства: var obj = {x: 1}; @@ -43,13 +42,13 @@ delete GLOBAL_OBJECT.a; // true GLOBAL_OBJECT.a; // undefined -Здесь, чтобы удалить `a`, мы используем трюк. В этом коде [`this`](#function.this) ссылается на объект Global и мы явно описываем переменную `a` под видом его свойства, что позволяет нам её успешно удалить. +Здесь, чтобы удалить `a`, мы используем один трюк. В этом коде [`this`](#function.this) ссылается на объект `Global` и мы явно описываем переменную `a` под видом его свойства, что и позволяет нам её успешно удалить. -В IE (по крайней мере, с 6-го по 8-й), есть парочка багов, из-за которых такой код не сработает. +Internet Explorer (по крайней мере, с 6-го по 8-й) содержит баги, из-за которых такой код не сработает. ### Аргументы функций и встроенные свойства -Обычные аргументы функций, [объект `arguments`](#function.arguments), а также встроенные свойства, объединены общей особенностью: у них у всех установен атрибут `DontDelete`. +Обычные аргументы функций, [объект `arguments`](#function.arguments), а также встроенные свойства, объединены общей особенностью: у всех у них установен атрибут `DontDelete`. // аргументы функций и свойства: (function (x) { @@ -70,8 +69,8 @@ (_прим. перев._ — Хост-объекты — это объекты, которые, в неком окружении, дополняют функциональность языка JavaScript, не являясь частью его спецификации. В случае браузера это объекты `window`, `document`, `setTimeout` и т.п.) -Поведение оператора `delete` может быть абсолютно непредсказуемым при применении его к хост-объектам. С позволения спецификации, хост-объекты вольны вести себя как им только вздумается. +Поведение оператора `delete` может быть полностью непредсказуемым, когда вы примененяете его к таким хост-объектам. С позволения спецификации, хост-объекты вольны вести себя как им только вздумается. ### Заключение -Оператор `delete` часто ведёт себя непредсказуемо и может использоваться условно-безопасно только для удаления пользовательских свойств у обычных объектов. +Оператор `delete` часто ведёт себя непредсказуемо и может использоваться относительно безопасно только для удаления пользовательских свойств у обычных объектов. diff --git a/doc/ru/core/eval.md b/doc/ru/core/eval.md index c197a78e..66d4f435 100644 --- a/doc/ru/core/eval.md +++ b/doc/ru/core/eval.md @@ -1,6 +1,6 @@ ## Почему нельзя использовать `eval` -Функция `eval` выполнит переданную строку как код JavaScript в локальной области видимости: +Функция `eval` выполнит переданную строку в качестве кода JavaScript в локальной области видимости: var foo = 1; function test() { @@ -11,7 +11,7 @@ test(); // 3 foo; // 1 -Но только тогда, когда функция `eval` вызывается явно *и при этом* имя вызываемой функции *идентично* `eval` (_прим. перев._ — ох! вот вам анти-пример): +но только тогда, когда функция `eval` вызывается явно *и при этом* имя вызываемой функции *идентично* `eval`: var foo = 1; function test() { @@ -23,7 +23,7 @@ test(); // 2 foo; // 3 -**Любой ценой** избегайте использования функции `eval`. 99.9% «трюков» с её «использованием» могут легко решаться и **без её участия**. +**Любой ценой** избегайте функции `eval`. 99.9% «трюков» с её «использованием» могут быть запросто решены и **без её участия**. ### `eval` под прикрытием @@ -31,9 +31,9 @@ ### Проблемы с безопасностью -Кроме всего прочего, функция `eval` — это дыра в безопасности, поскольку она выполняет **любой** переданный в неё код; **никогда** не следует использовать её со строками из неизвестных или недоверительных источников. +Кроме всего прочего, функция `eval` — это дыра в безопасности, поскольку она выполняет **любой** переданный в неё код; **никогда** не используйте её со строками из неизвестных или недоверительных источников. ### Заключение -Никогда не стоит использовать `eval`: любой код с участием этой функции автоматически порождает вопросы о качестве его работы, производительности и безопасности. Если вдруг для работы вам необходим `eval`, эта часть кода должна тут же ставиться под сомнение и в первую очередь *исключаться* из проекта — необходимо найти *лучший способ*, которому не требуются вызовы `eval`. +Никогда не используйте `eval`: любой код с участием этой функции автоматически порождает вопросы о качестве его работы, производительности и безопасности. Если вдруг для работы вам необходим `eval`, эта часть кода должна тут же ставиться под сомнение и в первую очередь *исключаться* из проекта — необходимо найти *лучший способ*, которому не требуются вызовы `eval`. diff --git a/doc/ru/core/semicolon.md b/doc/ru/core/semicolon.md index 31eb0f37..6714c970 100644 --- a/doc/ru/core/semicolon.md +++ b/doc/ru/core/semicolon.md @@ -1,8 +1,8 @@ ## Автоматическая вставка точек с запятой -Несмотря на то, что JavaScript имеет синтаксис, подобный языкам семейства C, он никоим образом **не принуждает** вас ставить точки с запятой в исходном коде — вам всегда позволяется их опустить. +Несмотря на то, что синтаксис JavaScript подобен языкам семейства C, он **не принуждает** вас ставить точки с запятой в исходном коде — вам всегда позволено обойтись без них. -При этом JavaScript — вовсе не язык с абсолютным отсутствием точек с запятой: они на самом деле нужны ему для того, чтобы он мог разобраться в вашем коде. Поэтому парсер JavaScript **автоматически** вставляет их в те места, где сталкивается с ошибкой парсинга по причине их отсутствия. +При этом JavaScript — не из тех языков, в которых отсутствуют точки с запятой: на самом деле они очень нужны ему — для того, чтобы он мог разобраться в вашем коде. Поэтому парсер JavaScript **автоматически** вставляет их в те места, где сталкивается с ошибкой парсинга, вызванной их отсутствием. var foo = function() { } // ошибка разбора, ожидается точка с запятой @@ -14,7 +14,7 @@ }; // ошибки нет, парсер продолжает test() -Автоматическая вставка точек с запятой считается одним из **наибольших** упущений в проекте языка, поскольку она *действительно может* влиять на поведение кода. +Автоматическая вставка точек с запятой считается одним из **наибольших** упущений в проекте языка, поскольку такая вставка *действительно может* влиять на поведение кода. ### Как это работает @@ -78,13 +78,13 @@ })(window); //<- вставлена -> **Замечание:** Парсер JavaScript некорректно обрабатывает оператор `return`, за которым следует новая строка; Причина может быть и не в автоматической вставке точек с запятой, но без сомнений, это нежелательный побочный эффект. +> **Замечание:** Парсер JavaScript некорректно обрабатывает оператор `return`, за которым следует новая строка; Причина может скрываться и не за автоматической вставкой точек с запятой — но без сомнений — этот побочный эффект нежелателен. Парсер радикально поменял поведение изначального кода, а в определённых случаях он вообще сделал **абсолютно неправильные выводы**. ### «Висящие» скобки -Если парсер встречает «висящую» открывающую скобку, то он **не** вставляет точку с запятой. +Если парсер встречает «висящую» открывающую скобку, он **не** вставляет точку с запятой. log('тестируем!') (options.list || []).forEach(function(i) {}) @@ -93,9 +93,9 @@ log('тестируем!')(options.list || []).forEach(function(i) {}) -**Чрезвычайно** высоки шансы того, что `log` **не** возвращает *никаких* функций; таким образом, выполнение этой строки кода породит `TypeError` с сообщением о том, что `undefined не является функцией`. +Шансы на то, что `log` **не** вернёт функцию, **крайне** высоки; так что выполнение этой строки кода породит `TypeError`, приправив его сообщением о том, что `undefined не является функцией`. ### Заключение -Настоятельно рекомендуем **никогда** не забывать ставить точку с запятой; также рекомендуется оставлять скобки на одной строке с соответствующим оператором и никогда не опускать их для выражений с использованием `if` / `else`. Оба этих совета не только повысят читабельность вашего кода, но и предотвратят от изменения поведения кода, произведённого парсером втихую. +Настоятельно рекомендуем **никогда** не забывать ставить точку с запятой; также рекомендуется оставлять скобки на одной строке с соответствующим оператором и всегда использовать их в выражениях `if` / `else`. Оба этих совета не только повысят читабельность вашего кода, но и предотвратят вас от изменений в поведении кода, сделанных парсером без вашего ведома. diff --git a/doc/ru/core/undefined.md b/doc/ru/core/undefined.md index 3693109e..71689fed 100644 --- a/doc/ru/core/undefined.md +++ b/doc/ru/core/undefined.md @@ -1,6 +1,6 @@ ## `undefined` и `null` -В JavaScript есть два отдельных типа для описания *ничего* — `null` и `undefined`, при этом последний из них наиболее полезен. +В JavaScript используется два отдельных типа для описания *ничего* — `null` и `undefined`, при этом более полезным из них оказывается `undefined`. ### Значение `undefined` @@ -8,7 +8,7 @@ Кроме этого, в языке определена глобальная переменная со значением `undefined`, причём эта переменная так и называется — `undefined`. Не являясь константой, она не является и ключевым словом. Из этого следует, что её значение можно с лёгкостью переопределить. -> **ES5 Замечание:** в ECMAScript 5 переменная `undefined` **уже не** *доступна на запись* в strict-режиме, однако она всё так же может быть перегружена по имени, например — функцией с именем `undefined`. +> **Замечание по ES5:** в ECMAScript 5 переменная `undefined` **больше не** *доступна на запись* в strict-режиме, однако она всё ещё может быть перегружена по имени, например — функцией с именем `undefined`. Список случаев, когда код возвращает значение `undefined`: @@ -25,9 +25,9 @@ Поскольку глобальная переменная `undefined` содержит копию реального *значения* `undefined`, присвоение этой переменной нового значения **не** изменяет значения у *типа* `undefined`. -Получается, чтобы проверить что-либо с *типом* `undefined` на соответствие *значению* `undefined`, прежде нужно узнать изначальное значение самой *переменной* `undefined`. +Получается, чтобы проверить что-либо с *типом* `undefined` (на соответствие *значению* `undefined`), прежде нужно узнать изначальное значение самой *переменной* `undefined`. -Чтобы защитить код от переопределения переменной `undefined`, часто используют технику [анонимной обёртки](#function.scopes), в которую добавляют аргумент и намеренно не передают его значение. +Для того, чтобы защитить код от случайного переопределения переменной `undefined`, часто используют технику [анонимной обёртки](#function.scopes), в которую добавляют аргумент и намеренно не передают его значение. var undefined = 123; (function(something, foo, undefined) { @@ -45,11 +45,11 @@ })('Hello World', 42); -Единственная разница между этими вариантами в том, что последняя версия будет больше на 4 байта при минификации, а в первом случае внутри анонимной обёртки нет дополнительного оператора `var`. +Единственная разница между этими вариантами в том, что последняя версия при минификации будет занимать больше на 4 байта, поскольку в первом случае внутри анонимной обёртки нет дополнительного оператора `var`. ### Применение `null` -Хотя `undefined` в контексте языка JavaScript чаще используется в роли традиционного *null*, настоящий `null` (и тип и литерал) является, в некоторой степени, просто другим типом данных. +Хотя `undefined` в контексте языка JavaScript чаще используется в роли традиционного *null*, настоящий `null` (и тип и литерал) является, в какой-то степени, просто другим типом данных. -Он используется во внутренних механизмах JavaScript (в случаях вроде установки конца цепочки прототипов, через присваивание `Foo.prototype = null`). Но почти во всех случаях тип `null` может быть равносильно заменён на `undefined`. +Он используется во внутренних механизмах JavaScript (в случаях вроде установки конца цепочки прототипов, через присваивание `Foo.prototype = null`). Но практически во всех случаях тип `null` может быть заменён на равносильный ему `undefined`. From f0958f0c23127e4e0948200cb3dfad6624b810b1 Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Sun, 2 Jul 2017 16:29:55 +0200 Subject: [PATCH 39/41] new stylistic fixes, p.2 --- doc/ru/function/arguments.md | 16 ++++++++-------- doc/ru/function/closures.md | 14 ++++++-------- doc/ru/function/constructors.md | 20 ++++++++++---------- doc/ru/function/general.md | 8 ++++---- doc/ru/function/scopes.md | 22 +++++++++++----------- doc/ru/function/this.md | 10 ++++++---- doc/ru/object/forinloop.md | 2 +- doc/ru/object/general.md | 6 +++--- doc/ru/object/hasownproperty.md | 2 +- doc/ru/object/prototype.md | 4 ++-- doc/ru/other/timeouts.md | 20 ++++++++++---------- doc/ru/types/casting.md | 6 +++--- doc/ru/types/equality.md | 4 ++-- doc/ru/types/instanceof.md | 8 ++++---- doc/ru/types/typeof.md | 2 +- 15 files changed, 72 insertions(+), 72 deletions(-) diff --git a/doc/ru/function/arguments.md b/doc/ru/function/arguments.md index 4a6fb33f..8a564585 100644 --- a/doc/ru/function/arguments.md +++ b/doc/ru/function/arguments.md @@ -6,7 +6,7 @@ Объект `arguments` **не** является ни экземпляром, ни наследником `Array`. Он, конечно же, очень похож на массив, и даже обладает свойством `length` — но он не наследует `Array.prototype`, и если внимательно присмотреться, он окажется обычным `Object`. -По этой причине, у объекта `arguments` **отсутствуют** стандартные методы массивов, такие как `push`, `pop` или `slice`. Пусть перебор с использованием обычного цикла `for` по аргументам работает вполне корректно, но вам придётся конвертировать этот объект в настоящий массив типа `Array`, чтобы обладать возможностью применять к нему стандартные методы массивов. +По этой причине, у объекта `arguments` **отсутствуют** стандартные методы массивов, такие как `push`, `pop` или `slice`. Пусть перебор с использованием обычного цикла `for` по аргументам работает вполне корректно, но вам придётся конвертировать этот объект в настоящий массив типа `Array`, чтобы обрести возможность применять к нему стандартные методы массивов. ### Преобразование в массив @@ -14,7 +14,7 @@ Array.prototype.slice.call(arguments); -Будьте внимательны — это преобразование занимает **много времени** и использовать его в чувствительных к производительности частях кода **не рекомендуется**. +Будьте внимательны — это преобразование занимает **много времени** и поэтому **не рекомендуется** использовать его в чувствительных к производительности частях кода. ### Передача аргументов @@ -27,7 +27,7 @@ // делаем здесь что-нибудь } -Другой трюк — использовать и `call` и `apply` вместе, чтобы создать отвязанную от объекта обёртку, выполняющуюся приемлемо быстро: +Другой трюк — использовать и `call` и `apply` вместе, чтобы создать обёртку, отвязанную от объекта, и при этом выполняющуюся приемлемо быстро: function Foo() {} @@ -66,13 +66,13 @@ ### Разоблачение мифов о производительности -Объект `arguments` создаётся во всех случаях, лишь одним исключением — когда он переопределён по имени внутри функции или когда одним из её параметров является переменная с таким именем. Неважно, используется при этом сам объект в коде функции или нет. +Объект `arguments` создаётся во всех случаях, за одним лишь исключением — когда он переопределён по имени внутри функции, или когда одним из её параметров является переменная с таким именем. При этом ееважно, используется ли сам объект в коде функции или нет. *Геттеры* и *сеттеры* создаются **всегда**; так что их использование практически никак не влияет на производительность, и тем более никак не влияет на неё в реальном коде, где обычно происходят вещи посерьёзнее обычных прочтений и переопределений свойств объекта `arguments`. -> **ES5 Замечание:** Эти *геттеры* и *сеттеры* не создаются в strict-режиме. +> **Замечание по ES5:** Эти *геттеры* и *сеттеры* не создаются в strict-режиме. -Однако, есть одна такая тайна, незнание которой автором кода может радикально понизить его производительность в современных движках JavaScript. Эта тайна — опасность использования `arguments.callee`. +Однако, есть одна такая тайна, что её незнание может радикально понизить производительность кода в современных движках JavaScript. Эта тайна — опасность использования `arguments.callee`. function foo() { arguments.callee; // сделать что-либо с этим объектом функции @@ -85,11 +85,11 @@ } } -В коде выше, функция `foo` не может [быть «развёрнута»][1] (а могла бы), потому что для корректной работы ей необходима ссылка и на себя и на вызвавший её объект. Такой код не только кладёт на лопатки механизм развёртывания, но и нарушает принцип инкапсуляции, поскольку функция становится зависима от конкретного контекста вызова. +В коде выше, функция `foo` не может [быть «развёрнута»][1] (а могла бы), потому что для корректной работы ей необходима ссылка как на себя, так и на вызвавший её объект. Такой код не только кладёт на лопатки механизм развёртывания, но и нарушает принцип инкапсуляции, поскольку функция становится зависима от конкретного контекста вызова. **Крайне не рекомендуется** использовать `arguments.callee` или какое-либо из его свойств. **Никогда**. -> **ES5 Замечание:** В strict-режиме любое использование `arguments.callee` вызовет `TypeError`, поскольку свойство принято устаревшим. +> **Замечание по ES5:** В strict-режиме любое использование `arguments.callee` вызовет `TypeError`, поскольку свойство принято устаревшим. [1]: http://en.wikipedia.org/wiki/Inlining diff --git a/doc/ru/function/closures.md b/doc/ru/function/closures.md index f0a5dd1b..5b3c50cf 100644 --- a/doc/ru/function/closures.md +++ b/doc/ru/function/closures.md @@ -1,6 +1,6 @@ ## Замыкания и ссылки -Одним из самых мощных инструментов язка JavaScript считают возможность создавать *замыкания*. Это такой приём, когда новые области видимости (например, функций) **всегда** имеют доступ к внешней области, в которых они были объявлены. Собственно, единственный механизм создания областей видимости в JavaScript — это и есть [функции](#function.scopes): таким образом, объявляя функцию, вы автоматически реализуете замыкания. Или, другими словами: любая объявленная функция по умолчанию ведёт себя как замыкание. +Одним из самых мощных инструментов языка JavaScript считают возможность создавать *замыкания*. Это такой приём, когда новые области видимости (например, функций) **постоянно** имеют доступ к внешней области, в которой они были объявлены. Собственно, единственный механизм создания областей видимости в JavaScript — это и есть [функции](#function.scopes): таким образом, объявляя функцию, вы автоматически реализуете замыкания. Или, другими словами: любая объявленная функция по умолчанию ведёт себя как замыкание. ### Эмуляция приватных переменных @@ -21,22 +21,22 @@ foo.increment(); foo.get(); // 5 -В данном примере `Counter` возвращает **два** замыкания: функции `increment` и `get`. Обе эти функции сохраняют внутри себя **ссылку** на область видимости `Counter` и, соответственно, имеют свободный доступ к переменной `count` из этой самой области. +В данном примере `Counter` возвращает **два** замыкания: функции `increment` и `get`. Обе эти функции сохраняют внутри себя **ссылку** на область видимости `Counter` и, соответственно, имеют свободный доступ к переменной `count`, объявленный в этой самой области. ### Как работают приватные переменные -Поскольку в JavaScript нельзя присваивать или ссылаться на области видимости, заполучить `count` извне — **не** представляется возможным. Единственный способ взаимодействовать с этой переменной — изменять её внутри двух описанных замыканий. +Поскольку в JavaScript нельзя присваивать или ссылаться на области видимости, заполучить `count` извне — **не** представляется возможным. Единственный способ взаимодействовать с этой переменной — её изменение внутри двух приведённых выше замыканий. var foo = new Counter(4); foo.hack = function() { count = 1337; }; -В приведенном примере мы **не** изменяем переменную `count` из области видимости `Counter`, т.к. `foo.hack` не объявлен в **той** области. Вместо этого будет создана или перезаписана *глобальная* переменная `count` (_прим. перев._ — замена кода внутри `foo.hack` на `this.count = 1337`, не поможет, конечно же, тоже, поскольку `count` никогда не был свойством объекта `Counter`, а был лишь внутренней переменной); +В приведенном примере мы **не** изменяем переменную `count` из области видимости `Counter`, т.к. `foo.hack` не объявлен в **той же** области. Вместо этого будет создана или перезаписана *глобальная* переменная `count` (_прим. перев._ — замена кода внутри `foo.hack` на `this.count = 1337`, не поможет, конечно же, тоже, поскольку `count` никогда не был свойством объекта `Counter`, а был лишь внутренней переменной); ### Замыкания внутри циклов -Существует одна, довольно часто встречающаяся, ловушка — когда замыкания используют внутри циклов, передавая переменную индекса внутрь. +Существует одна ловушка, которую можно встретить довольно часто — когда замыкания используют внутри циклов, передавая переменную индекса внутрь. for(var i = 0; i < 10; i++) { setTimeout(function() { @@ -46,7 +46,7 @@ Данный код **не** будет выводить числа с `0` до `9` — вместо этого число `10` будет выведено десять раз. -*Анонимная* функция сохраняет лишь **ссылку** на `i`, и в тот момент, когда будет вызвана функция `console.log`, цикл `for` уже *завершит* свою работу — и именно поэтому в переменной `i` будет покоиться значение `10`. +*Анонимная* функция сохраняет лишь **ссылку** на `i` — и в тот момент, когда будет вызвана функция `console.log`, цикл `for` уже давно *завершит* свою работу — и именно поэтому в переменной `i` уже будет покоиться последнее значение `10`. Для получения желаемого результата необходимо создать **копию** переменной `i`. @@ -78,5 +78,3 @@ _Прим, перев._ В качестве упражнения на замыкания и анонимные функции, попробуйте заменить оборачивающие вызовы анонимных функций в примерах на варианты с `.call` и `.apply`. -> **Замечание** от перев. Переменную `e` можно тоже назвать `i`, если вы хотите: это не поменяет поведения кода — внутренняя переменная `i` всё так же будет *копией* внешней переменной. - diff --git a/doc/ru/function/constructors.md b/doc/ru/function/constructors.md index 3dd76d38..05c50e44 100644 --- a/doc/ru/function/constructors.md +++ b/doc/ru/function/constructors.md @@ -1,10 +1,10 @@ ## Конструктор - Конструкторы в JavaScript тоже действуют отличным от большинства языков образом. Любая функция, вызванная с использованием ключевого слова `new`, станет конструктором. + Конструкторы в JavaScript тоже ведут себя не так, как в большинстве языков. Любая функция, вызванная с использованием ключевого слова `new`, станет конструктором. -Внутри конструктора (вызываемой функции) `this` будет указывать на новосозданный `Object`. [Прототипом](#object.prototype) этого **нового** экземпляра будет `prototype` функции, которая была вызвана в качестве конструктора. +Внутри конструктора (вызываемой функции) `this` будет указывать на созданный `Object`. [Прототипом](#object.prototype) этого **нового** экземпляра будет `prototype` функции, вызванной под именем конструктора. -Если вызываемая функция не возвращает явного значения посредством `return`, то она автоматически вернёт `this` — тот самый новый экземпляр. +Если вызываемая функция не возвращает явного значения при помощи `return`, она автоматически вернёт `this` — тот самый новый экземпляр. function Foo() { this.bla = 1; @@ -18,7 +18,7 @@ В этом примере `Foo` вызывается в виде конструктора, следовательно прототип созданного объекта будет привязан к `Foo.prototype`. -В случае, когда функция в явном виде возвращает некое значение используя `return`, в результате выполнения конструктора мы получим именно его, **но только** если возвращаемое значение представляет собой `Object`. +В случае, когда функция в явном виде возвращает некое значение, при выполнении конструктора мы получим именно это значение, **но только** если возвращаемое значение представляет собой `Object`. function Bar() { return 2; @@ -34,14 +34,14 @@ } new Test(); // возвращённый объект -Если же опустить ключевое слово `new`, то функция **не** будет возвращать никаких объектов. +Если же опустить ключевое слово `new`, то функция **не** будет возвращать объекта. function Foo() { this.bla = 1; // свойство bla устанавливается глобальному объекту } Foo(); // возвращает undefined -Хотя этот пример и будет работать — в связи с поведением [`this`](#function.this) в JavaScript, значение будет присвоено *глобальному объекту* — навряд ли это предполагалось его автором. +Хотя этот пример и будет работать — в связи со сложным поведением [`this`](#function.this) в JavaScript, значение будет присвоено *глобальному объекту* — навряд ли это то, что предполагалось автором. ### Фабрики @@ -70,7 +70,7 @@ ### Создание объектов с использованием фабрик -Многие **не** рекомендуют использовать оператор `new`, поскольку если вы забудете его написать, такое «необдуманное» действие может привести к ошибкам. +Многие рекомендуют **не** использовать оператор `new` вовсе — аргументируя это тем, что если вы забудете его написать, такое «необдуманное» действие может «неизбежно» привести к ошибкам. Чтобы создать новый объект, нам предлагают использовать фабрику и создать новый объект *внутри* этой фабрики. @@ -89,13 +89,13 @@ return obj; } -Хотя данный пример и сработает, если вы забыли ключевое слово `new`, и благодаря ему вам станет легче работать с [приватными переменными](#function.closures), у него есть несколько недостатков: +Хотя данный пример и сработает, когда вы забыли ключевое слово `new`, да и благодаря ему вам действительно станет легче работать с [приватными переменными](#function.closures), у него есть несколько недостатков: 1. Он использует больше памяти, поскольку созданные объекты **не** хранят методы в прототипе и соответственно для каждого нового объекта создаётся копия каждого метода; 2. Чтобы эмулировать наследование, фабрике нужно скопировать все методы из другого объекта или установить прототипом нового объекта старый; - 3. Разрыв цепочки прототипов, по надуманной необходимости избавиться от использования ключевого слова `new`, идёт вразрез с духом языка; + 3. Разрыв цепочки прототипов по надуманной необходимости избавиться от использования ключевого слова `new`, идёт вразрез с духом языка; ### Заключение -Хотя забытое ключевое слово `new` и может привести к багам, это точно **не** причина отказываться от использования прототипов. В конце концов, полезнее решить, какой из способов лучше совпадает с требованиями приложения: крайне важно выбрать один из стилей создания объектов и после этого **не изменять** ему. +Хотя забытое ключевое слово `new` и правда может привести к багам, это точно **не** причина отказываться от использования прототипов. В конце концов, полезнее решить, какой из способов лучше совпадает с требованиями приложения: крайне важно выбрать один из стилей создания объектов и после этого **не изменять** ему. diff --git a/doc/ru/function/general.md b/doc/ru/function/general.md index 251529e6..49b19c84 100644 --- a/doc/ru/function/general.md +++ b/doc/ru/function/general.md @@ -1,6 +1,6 @@ ## Про объявление функций и о выражениях с ними -Функции в JavaScript являются объектами. Следовательно, их можно передавать и присваивать точно так же, как и любой другой объект. Популярным сбособом использования этого свойства является передача *анонимной функции* в качестве функции обратного вызова в некую другую функцию — к примеру, при описании асинхронных вызовов. +Функции в JavaScript являются объектами. Следовательно, их можно передавать и присваивать точно так же, как и любой другой объект. Популярное использование этого замечательного свойства — передача *анонимной функции* в качестве функции обратного вызова в некую другую функцию — к примеру, при описании асинхронных вызовов. ### Объявление `function` @@ -10,7 +10,7 @@ В следующем примере, ещё перед запуском всего скрипта, для описанной функции [резервируется](#function.scopes) переменная; за счёт этого она становится доступна *в любом месте* кода, вне зависимости от того, где она *определена* — даже если она вызывается заранее, перед её фактическим объявлением в коде (и сколь угодно задолго до такого определения). - foo(); // сработает, т.к. функция будет создана до выполнения кода + foo(); // сработает, т.к. функция будет создана при компиляции, до выполнения кода function foo() {} ### `function` как выражение @@ -23,9 +23,9 @@ foo(); // вызовет TypeError var foo = function() {}; -Поскольку выражение с применением `var` *резервирует* имя переменной `foo` ещё до запуска кода, `foo` уже имеет некое значение во время его исполнения (отсутствует ошибка «`foo` is not defined»). +Поскольку выражение с применением `var` *резервирует* имя переменной `foo` ещё до запуска кода, `foo` уже имеет некое значение во время его исполнения (ошибка «`foo` is not defined» отсутствует). -Но поскольку сами *присвоения* исполняются только непосредственно во время работы кода, `foo` по умолчанию будет иметь лишь значение [`undefined`](#core.undefined) (до обработки строки с определением функции). +Но поскольку *сами присвоения* исполняются непосредственно во время работы кода, до выполнения строки с определением функции `foo` будет иметь значение [`undefined`](#core.undefined). ### Выражения с именованными функциями diff --git a/doc/ru/function/scopes.md b/doc/ru/function/scopes.md index 85fb57af..f43f6084 100644 --- a/doc/ru/function/scopes.md +++ b/doc/ru/function/scopes.md @@ -1,6 +1,6 @@ ## Области видимости и пространства имён -Хотя JavaScript вполне нормально воспринимает синтаксис двух сопоставимых фигурных скобок, окружающих блок, он **не** поддерживает блочную область видимости; всё что остаётся на этот случай в языке — *область видимости функций*. +Хотя JavaScript вполне нормально воспринимает синтаксис двух сопоставимых фигурных скобок, окружающих блок, он **не** поддерживает блочную область видимости; всё, что остаётся на этот случай в языке — *области видимости функций*. function test() { // область видимости for(var i = 0; i < 10; i++) { // не область видимости @@ -9,7 +9,7 @@ console.log(i); // 10 } -> **Замечание:** Нотация `{...}` будет интерпретирована как блочное выражение, а **не** как литерал объекта, если она не используется в присваивании, операторе `return` или в качестве функции. Это замечание, вкупе с [автоматической расстановкой точек с запятой](#core.semicolon), может привести к чрезвычайно изощрённым ошибкам. +> **Замечание:** Нотация `{...}` будет интерпретирована как блочное выражение, а **не** как литерал объекта, если она не используется в присваивании, операторе `return` или в качестве определения функции. Это замечание, вкупе с [автоматической расстановкой точек с запятой](#core.semicolon), может привести к чрезвычайно изощрённым ошибкам. Также JavaScript не различает пространств имён: всё определяется на том или ином уровне в единственном *глобально доступном* пространстве имён. @@ -25,7 +25,7 @@ Вышеприведённые два скрипта отнюдь **не** приводят к одинаковому результату. Скрипт A определяет переменную по имени `foo` в *глобальной* области видимости, а скрипт B определяет `foo` в текущей области видимости. -Повторимся, это **совсем не** *тот же самый эффект*. Если вы не используете `var` — то вы в большой опасности. +Повторимся, это **совсем не** *тот же самый эффект*. Если вы не используете `var` — вы в большой опасности. // глобальная область видимости var foo = 42; @@ -36,7 +36,7 @@ test(); foo; // 21 -Из-за того что оператор `var` был опущен внутри функции, функция `test` перезапишет значение `foo`. Это поначалу может показаться не такой уж и большой проблемой, но если у вас имеется тысяча строк JavaScript-кода и вы не используете `var`, то вам на пути встретятся самые страшные и трудноотлаживаемые ошибки — и это не шутка. +Из-за того, что оператор `var` был опущен внутри функции, функция `test` перезапишет значение `foo`. Это поначалу может показаться не такой уж и большой проблемой, но если у вас имеется тысяча строк JavaScript-кода и вы не используете `var`, то вам на пути встретятся самые страшные и трудноотлаживаемые ошибки — и это не шутка. // глобальная область видимости var items = [/* какой-то список */]; @@ -51,7 +51,7 @@ } } -Внешний цикл прекратит работу сразу после первого вызова `subLoop`, поскольку `subLoop` перезаписывает глобальное значение переменной `i`. Использование `var` во втором цикле `for` могло бы вас легко избавить от этой ошибки. **Никогда** не забывайте использовать `var`, если только вы не обладаете полностью *осознанным намерением* повлиять на внешнюю область видимости. +Внешний цикл прекратит работу сразу после первого вызова `subLoop`, поскольку `subLoop` перезаписывает глобальное значение переменной `i`. Использование `var` во втором цикле `for` могло бы легко избавить вас от этой ошибки. **Никогда** не забывайте использовать `var`, если только вы не *осознано намеренны* повлиять на внешнюю область видимости. ### Локальные переменные @@ -157,11 +157,11 @@ 3. Если функция сама называется `foo`, использовать её; 4. Перейти на одну область видимости выше и повторить, начиная с **п. 1**; -> **Замечание:** Наличие параметра функции с именем `arguments` **не позволит** движку создать объект `arguments`, создающийся, в других случаях, по умолчанию. +> **Замечание:** Наличие параметра функции с именем `arguments` **запрещает** движку создать объект `arguments`, создающийся, в других случаях, по умолчанию. ### Пространства имён -Нередко можно столкнуться с неприятным последствием единого глобального пространства имён — проблема с перекрытием имён переменных. В JavaScript эту проблему легко избежать, используя *анонимные обёртки*. +Нередко можно столкнуться с таким неприятным последствием единого глобального пространства имён, как проблема с перекрытием имён переменных. В JavaScript эту проблему легко избежать, используя *анонимные обёртки*. (function() { // самодостаточное «пространство имён» @@ -172,14 +172,14 @@ })(); // сразу же выполнить функцию -Безымянные функции являются отложенными [выражениями](#function.general) (_прим. перев._ — то есть они не разбираются по месту описания, а откладываются парсером напоследок); поэтому, чтобы сделать их исполняемыми, следует спровоцировать их разбор. +Безымянные функции являются отложенными [выражениями](#function.general) (_прим. перев._ — то есть они не выполняются по месту описания, а откладываются движком напоследок); поэтому, чтобы сделать их исполняемыми, сначала следует спровоцировать их разбор. ( // разобрать функцию внутри скобок function() {} ) // и вернуть объект функции () // вызвать результат разбора -Есть другие способы спровоцировать разбор и последующий вызов выражения с функцией; они, хоть и различаются в синтаксисе, действуют одинаково: +Есть другие способы спровоцировать разбор и последующий вызов выражения с функцией; они, хоть и различаются синтаксисом, действуют одинаково: // Два других способа +function(){}(); @@ -193,7 +193,7 @@ ### Заключение -Рекомендуется всегда использовать *анонимную обёртку* чтобы заключить код в собственное пространство имён. Это не только защищает код от совпадений имён, но и позволяет создавать модульные программы. +Рекомендуется всегда использовать *анонимную обёртку*, чтобы заключить код в собственное пространство имён. Это не только защищает ваш код от совпадений имён, но и позволяет создавать модульные программы. -Важно добавить, что использование глобальных переменных считается **плохой практикой**. **Любое** их использование демонстрирует плохое качество кода, предполагает его высокую подверженность ошибкам и сложность в его разборе. +Важно добавить, что использование глобальных переменных считается **плохой практикой**. **Любое** их использование демонстрирует плохое качество кода, предполагает его высокую подверженность ошибкам и сложность его разбора. diff --git a/doc/ru/function/this.md b/doc/ru/function/this.md index b13e3cb1..c9a90368 100644 --- a/doc/ru/function/this.md +++ b/doc/ru/function/this.md @@ -1,6 +1,6 @@ ## Как работает `this` -В JavaScript зона ответственности специальной переменной `this` концептуально отличается от тех, за которые отвечает `this` в других языках программирования. Различают ровно **пять** сущностей, к которым в этом языке может быть привязана переменная `this`. +В JavaScript зона ответственности специальной переменной `this` концептуально отличается от поведения `this` в других языках программирования. Различают ровно **пять** сущностей, к которым в этом языке может быть привязана переменная `this`. ### 1. Глобальная область видимости @@ -38,13 +38,13 @@ Когда мы используем методы `call` или `apply` из `Function.prototype`, то внутри вызываемой функции `this` **явным образом** будет присвоено значение первого передаваемого параметра. -Исходя из этого, в предыдущем примере (строка с `apply`), правило №3 *«вызов метода»* **не** будет применено, и `this` внутри `foo` будет присвоено `bar`. +Исходя из этого, в предыдущем примере (строка с `apply`), правило №3 *«вызов метода»* **не** применяется, и `this` внутри `foo` будет присвоено `bar`. -> **Замечание:** `this` **нельзя** использовать внутри литералов `{}` (`Object`) для ссылки на сам объект. Т.е. если мы напишем `var obj = {me: this}`, то `me` не будет ссылаться на `obj`, поскольку `this` присваивается только по одному из пяти описанных правил. +> **Замечание:** `this` **нельзя** использовать внутри литералов `{}` (`Object`) для создания ссылки на сам объект. Т.е. если мы напишем `var obj = {me: this}`, то `me` не будет ссылаться на `obj`, поскольку `this` присваивается только по одному из пяти описанных правил. ### Наиболее распространенные ловушки -Хотя большинство из примеров ниже имеют смысл, первый из них можно причислить к упущениям в самом языке, поскольку он **вообще** не имеет практических применений. +Хотя большинство из примеров ниже имеют смысл, первый из них можно причислить к упущениям в самом языке, поскольку он **вообще** не имеет практического применения. Foo.method = function() { function test() { @@ -88,3 +88,5 @@ В момент, когда будет вызван `method` нового экземпляра `Bar`, `this` будет ссылаться на этот самый экземпляр. +(_прим. перев._ — В случае, если вам необходимо передать `this` в функцию, вы можете использовать `.call`, `.apply` при непосредственно вызове или `.bind` при отложенном — для того, чтобы вызвать эту функцию с указанным `this` в другом месте кода.) + diff --git a/doc/ru/object/forinloop.md b/doc/ru/object/forinloop.md index 53633591..7e942471 100644 --- a/doc/ru/object/forinloop.md +++ b/doc/ru/object/forinloop.md @@ -25,7 +25,7 @@ } } -Это единственно правильная версия выполнения такого цикла. За счёт использования `hasOwnProperty` будет выведено одно **только** свойство `moo`. Если же вы уберёте проверку `hasOwnProperty`, код станет нестабилен и, если кто-то всё же позволил себе изменить прототипы встроенных типов, такие как `Object.prototype`, вам грозят непредвиденные сюрпризы. +Это единственно правильная версия выполнения цикла обхода ключей объекта. За счёт использования `hasOwnProperty` будет выведено одно **только** свойство `moo`. Если же вы уберёте проверку `hasOwnProperty`, код станет нестабилен и, если кто-то всё же позволил себе изменить прототипы встроенных типов, такие как `Object.prototype`, вам грозят непредвиденные сюрпризы. Один из самых популярных фреймворков [Prototype][1] использует упомянутое расширение `Object.prototype` — и если вы его подключаете — ни в коем случае не забывайте использовать `hasOwnProperty` внутри всех циклов `for in` — иначе у вас гарантированно возникнут проблемы. diff --git a/doc/ru/object/general.md b/doc/ru/object/general.md index e052ea4e..a12ef2f2 100644 --- a/doc/ru/object/general.md +++ b/doc/ru/object/general.md @@ -13,7 +13,7 @@ 2.toString(); // вызывает SyntaxError -Есть несколько способов обойти этот недостаток, и любой из них подойдёт, если от числового значения нужно добиться поведения объекта: +Есть несколько способов обойти этот недостаток, и любой из них подойдёт, когда вам действительно нужно добиться поведения объекта от числового значения: 2..toString(); // вторая точка распознаётся корректно 2 .toString(); // обратите внимание на пробел перед точкой @@ -21,7 +21,7 @@ ### Объекты как хранилища данных -Объекты в JavaScript могут использоваться и как [*хеш-таблицы*][1]: подавляющей частью они состоят из именованных свойств (ключей), привязанных к соответствующим значениям. +Объекты в JavaScript могут использоваться и как [*хеш-таблицы*][1]: большей частью они состоят из именованных свойств (ключей), привязанных к соответствующим значениям. Используя объектный литерал — нотацию `{}` — можно создать простой объект. Новый объект [наследуется](#object.prototype) от `Object.prototype` и не имеет [собственных свойств](#object.hasownproperty). @@ -67,7 +67,7 @@ } } -Приведённый код выведет две строки — `bar undefined` и `foo null`: на самом деле удалено было только свойство `baz` и посему лишь оно будет отсутствовать в выводе. +Приведённый код выведет две строки — `bar undefined` и `foo null`: на самом деле удалено было только свойство `baz` и поэтому лишь оно будет отсутствовать в выводе. ### Запись ключей diff --git a/doc/ru/object/hasownproperty.md b/doc/ru/object/hasownproperty.md index fca287ed..dc8b3d9a 100644 --- a/doc/ru/object/hasownproperty.md +++ b/doc/ru/object/hasownproperty.md @@ -20,7 +20,7 @@ ### `hasOwnProperty` как свойство -JavaScript **не** резервирует свойство с именем `hasOwnProperty`. Так что, если есть потенциальная возможность, что объект может содержать свойство с таким именем, чтобы получить ожидаемый результат, требуется использовать *внешний* вариант функции `hasOwnProperty`. +JavaScript **не** резервирует свойство с именем `hasOwnProperty`. Так что, если есть потенциальная возможность, что объект может содержать свойство с таким именем — чтобы получить гарантированно ожидаемый результат, требуется использовать *внешний* вариант функции `hasOwnProperty`. var foo = { hasOwnProperty: function() { diff --git a/doc/ru/object/prototype.md b/doc/ru/object/prototype.md index b53b714e..cab07941 100644 --- a/doc/ru/object/prototype.md +++ b/doc/ru/object/prototype.md @@ -2,7 +2,7 @@ В JavaScript отсутствует классическая модель наследования — вместо неё используется [*прототипная модель*][1]. -Хоть её и часто причисляют к недостаткам JavaScript, на самом деле прототипная модель наследования *мощнее* классической. К примеру, поверх неё можно предельно легко реализовать классическое наследование, а попытки совершить обратное непременно вынудят вас попотеть. +Хотя её и причисляют к недостаткам JavaScript, на самом деле прототипная модель наследования оказывается *мощнее* классической. К примеру, поверх неё можно предельно легко реализовать классическое наследование, а попытки совершить обратное вынудят вас попотеть. Из-за того, что JavaScript — практически единственный широко используемый язык с прототипным наследованием, придётся потратить некоторое время на осознание различий между этими двумя моделями. @@ -63,7 +63,7 @@ ### Производительность -Поиск свойств, располагающихся относительно высоко по цепочке прототипов, может негативно сказаться на производительности, особенно в критических к ней местах кода. Если же мы попытаемся найти несуществующее свойство, то поиск будет осуществлён вообще по всей цепочке, со всеми вытекающими последствиями. +Поиск свойств, располагающихся относительно высоко по цепочке прототипов, может негативно сказаться на производительности, особенно в критичных к ней местах кода. Если же мы попытаемся найти несуществующее свойство, поиск будет осуществлён по всей цепочке вообще, до самого глубокого конца — со всеми вытекающими последствиями. Вдобавок, при [циклическом переборе](#object.forinloop) свойств объекта, будет обработано **каждое** свойство, существующее в цепочке прототипов. diff --git a/doc/ru/other/timeouts.md b/doc/ru/other/timeouts.md index 8011467a..4a90c80c 100644 --- a/doc/ru/other/timeouts.md +++ b/doc/ru/other/timeouts.md @@ -1,6 +1,6 @@ ### `setTimeout` и `setInterval` -В виду того, что JavaScript умеет совершать асинхронные операции, есть возможность запланировать отложенное выполнение пользовательской функции, используя предназначенные для этого функции `setTimeout` и `setInterval`. +В виду того, что JavaScript умеет совершать асинхронные операции, есть возможность запланировать отложенное выполнение пользовательской функции с помощью предназначенных для этого функций `setTimeout` и `setInterval`. > **Замечание:** Таймауты **не** являются частью стандарта ECMAScript, они были разработаны будучи частью спецификации[DOM][1]. @@ -30,17 +30,19 @@ `setTimeout` вызывает функцию единожды; `setInterval` — как и предполагает название — вызывает функцию **каждые** `X` миллисекунд. И использовать его не рекомендуется. -В то время как, если применять `setTimeout`, исполняющийся в данный момент код будет блокировать запланированный — `setInterval` будет продолжать планировать последующие вызовы переданной функции. Это может, особенно при указании небольших интервалов, повлечь за собой выстраивание функций в ожидающую очередь. +В то время как, при использовании `setTimeout`, исполняющийся в данный момент код будет блокировать запланированный — `setInterval` продолжит планировать последующие вызовы переданной функции. При указании небольших интервалов это повлечь за собой выстраивание функций в ожидающую очередь. function foo(){ - // что-то, выполняющееся одну секунду или более + // что-то, выполняющееся десятую секунды или более } setInterval(foo, 100); -В приведённом примере `foo` в первый же раз заблокирует своим процессом главный поток на одну секунду. +В приведённом примере `foo` в первый же раз заблокирует своим процессом главный поток на десятую секунды. Пока `foo` блокирует код, `setInterval` продолжает планировать последующие её вызовы. Теперь, когда первая `foo` закончила выполнение, в очереди будет уже **десяток** ожидающих выполнения вызовов `foo`. +(_прим. перев._ — Во времена написания и перевода этой документации не существовало функции `requestAnimationFrame`, которая не гарантирует постоянный интервал во времени, но гарантирует свободные ресурсы процессора на каждый вызов — сейчас для некоторых повторяющихся задач, даже не связанных с анимацией, используют именно её). + ### Разбираемся с потенциальной блокировкой кода Самый простой и легко контролируемый способ — использовать `setTimeout` внутри такой функции. @@ -53,8 +55,6 @@ Такой способ не только инкапсулирует вызов `setTimeout`, но и предотвращает от очередей блокирующих вызовов и при этом обеспечивает дополнительный контроль: сама функция `foo` теперь принимает решение, хочет ли она запускаться ещё раз или нет. -(_прим. перев._ — такая техника сейчас активно используется для привязывания браузерного метода `requestAnimationFrame` к анимации, работающей на базе `canvas`). - ### Сброс таймаутов вручную Удалить таймаут или интервал можно посредством передачи соответствующего идентификатора либо в функцию `clearTimeout`, либо в функцию `clearInterval` — в зависимости от того, какая функция `set...` использовалась для его создания. @@ -71,9 +71,9 @@ clearTimeout(i); } -Впрочем, с таким кодом, вполне могут остаться «живыми» таймауты, которые не окажутся охвачены настолько произвольным числом. +Впрочем, с таким кодом, вполне могут остаться «в живых» таймауты, которые _настолько_ произвольное число не сможет охватить. -Есть и другой способ воплотить желаемое — условиться, что значения ID, выдающихся таймаутам, постоянно увеличиваются — с каждым новыми вызовом `setTimeout`. +Есть и другой способ воплотить желаемое — условиться, что значения ID, выдающихся таймаутам, постоянно увеличиваются — с каждым новым вызовом `setTimeout`. // сбрасываем «все» таймауты var biggestTimeoutId = window.setTimeout(function(){}, 1), @@ -86,7 +86,7 @@ ### Скрытое использование `eval` -`setTimeout` и `setInterval` могут принимать строку в качестве первого параметра. Эту возможность не стоит использовать **никогда**, поскольку изнутри, при этом, производится скрытый вызов `eval`. +`setTimeout` и `setInterval` могут принимать строку в качестве первого параметра. Эту возможность не следует использовать **никогда** — по той лишь причине, что изнутри, при этом, производится скрытый вызов `eval`. > **Замечание**: Поскольку функции работы с таймаутами **не** определены в стандарте ECMAScript, точная внутренняя механика их работы может различаться от движка к движку. Например, Microsoft JScript использует конструктор `Function` вместо `eval`. @@ -104,7 +104,7 @@ Поскольку `eval` в этом случае не вызывается [явно](#core.eval), переданная в `setTimeout` строка будет выполнена в *глобальной области видимости*; так что локальная функция `foo` из области видимости `bar` вообще не будет выполнена. -По этим же причинам **не рекомендуется** использовать строковое представление вызова функции для передачи аргументов в функцию, которая должна быть вызвана посредством одного из двух известных способов назначения таймаутов. +По этим же причинам **не рекомендуется** использовать строковое представление вызова функции для передачи аргументов в функцию, которая должна быть вызвана одним из двух известных способов назначения таймаутов. function foo(a, b, c) {} diff --git a/doc/ru/types/casting.md b/doc/ru/types/casting.md index 46f15aa7..7bd47f8f 100644 --- a/doc/ru/types/casting.md +++ b/doc/ru/types/casting.md @@ -17,9 +17,9 @@ JavaScript — язык, в котором господствует *слаба 10 == 010; 10 == '-10'; -> **ES5 Замечание:** Числовые литералы, которые начинаются с 0, интерпретируются как восьмеричные (Base 8). В ECMAScript 5 strict mode **удалена** поддержка восьмеричной системы. +> **Замечание по ES5:** Числовые литералы, которые начинаются с 0, интерпретируются как восьмеричные (Base 8). В ECMAScript 5 strict mode **удалена** поддержка восьмеричной системы. -Для того, чтобы избежать такого поведения, **настоятельно** рекомендуется использовать [оператор строгого равенства](#types.equality). Впрочем, хотя это и позволяет избежать многих распространенных ошибок, существует ещё много дополнительных проблем, возникающих по вине слабой типизации JavaScript. +Для того, чтобы избежать такого поведения, **настоятельно** рекомендуется использовать [оператор строгого равенства](#types.equality). Впрочем, хотя это и позволит избежать многих распространенных ошибок, существует ещё множество дополнительных проблем, возникающих по вине слабой типизации JavaScript. ### Конструкторы встроенных типов @@ -31,7 +31,7 @@ JavaScript — язык, в котором господствует *слаба Использование встроенных типов, таких как `Number`, с конструктором, создаёт новый экземпляр объекта `Number`, но использование их же без ключевого слова `new`, создаёт функцию `Number`, которая будет вести себя в равенствах в роли «преобразователя». -Кроме того, присутствие в равенствах дополнительных литералов или переменных, которые не являются объектами, повлечёт за собой лишь ещё больше ненужных преобразований типов. +Кроме того, присутствие в равенствах дополнительных литералов или переменных, которые не являются объектами, повлечёт за собой лишь ещё большее количество бессмысленных преобразований типов. Лучший вариант — это **явное** приведение к одному из трех возможных типов. diff --git a/doc/ru/types/equality.md b/doc/ru/types/equality.md index d0da4784..624ff851 100644 --- a/doc/ru/types/equality.md +++ b/doc/ru/types/equality.md @@ -18,7 +18,7 @@ JavaScript умеет сравнивать значения объектов н null == undefined // true " \t\r\n" == 0 // true -В таблице выше показаны результаты приведения типов в разных ситуациях и показана главная причина, по которой использование `==` повсеместно считается плохой практикой: благодаря непредсказуемости правил преобразования типов, оказывается трудно искать причины возникновения ошибок. +В таблице выше показаны результаты приведения типов в разных ситуациях и показана главная причина, по которой использование `==` повсеместно считается плохой практикой: «благодаря» непредсказуемости правил преобразования типов, становится очень трудно искать причины возникновения ошибок. Кроме того, приведение типов во время сравнения вынужденно влияет на производительность; например, строка должна быть преобразована в число перед сравнением с другим числом. @@ -50,7 +50,7 @@ JavaScript умеет сравнивать значения объектов н var foo = {}; foo === foo; // true -Здесь оба операнда сравниваются на **идентичность**, а **не** на равенство; то есть будет проверяться, являются ли операнды одним и тем же **экземпляром** объекта, так же как делает `is` в Python или сравниваются указатели в С. +Здесь оба операнда сравниваются на **идентичность**, а **не** на равенство; то есть будет проверяться, являются ли операнды одним и тем же **экземпляром** объекта — так же, как делает `is` в Python или сравниваются указатели в С. ### Заключение diff --git a/doc/ru/types/instanceof.md b/doc/ru/types/instanceof.md index bc1a1b90..1a6a26fc 100644 --- a/doc/ru/types/instanceof.md +++ b/doc/ru/types/instanceof.md @@ -1,6 +1,6 @@ ## Оператор `instanceof` -Оператор `instanceof` сравнивает конструкторы двух операндов. Он работает правильно только тогда, когда сравниваются пользовательские объекты. Использование же его на встроенных типах практически так же бесполезно, как и использование [оператора typeof](#types.typeof). +Оператор `instanceof` сравнивает конструкторы двух операндов. Он работает правильно только тогда, когда сравниваются пользовательские объекты. Использование его на встроенных типах практически так же бесполезно, как и использование [оператора typeof](#types.typeof). ### Сравнение пользовательских объектов @@ -11,8 +11,8 @@ new Bar() instanceof Bar; // true new Bar() instanceof Foo; // true - // Банально присваиваем Bar.prototype объект функции Foo, - // но не экземпляра Foo + // Всего-то лишь присваиваем Bar.prototype объект функции Foo, + // а не экземпляр Foo Bar.prototype = Foo; new Bar() instanceof Foo; // false @@ -24,7 +24,7 @@ 'foo' instanceof String; // false 'foo' instanceof Object; // false -Здесь необходимо отметить одну важную вещь: `instanceof` не работает с объектами, которые происходят из разных контекстов JavaScript (например, из различных документов в web-браузере), так как их конструкторы в действительности не будут конструкторами *тех же самых* объектов. +Здесь нужно отметить одну важную вещь: `instanceof` не работает с объектами, которые происходят из разных контекстов JavaScript (например, из различных документов в web-браузере), так как их конструкторы на самом деле не будут конструкторами *тех же самых* объектов, что справедливо. ### Заключение diff --git a/doc/ru/types/typeof.md b/doc/ru/types/typeof.md index dc474a0d..2b032e70 100644 --- a/doc/ru/types/typeof.md +++ b/doc/ru/types/typeof.md @@ -48,7 +48,7 @@ В примере выше `Object.prototype.toString` вызывается со значением [this](#function.this), ссылающимся на объект, значение `[[Class]]` которого требуется получить. -> **ES5 Замечание:** Для удобства, в ECMAScript 5 возвращаемое значение `Object.prototype.toString` для `null` и `undefined` было изменено с `Object` на `Null` и `Undefined` соответственно. +> **Замечание по ES5:** Для удобства, в ECMAScript 5 возвращаемое значение `Object.prototype.toString` для `null` и `undefined` было изменено с `Object` на `Null` и `Undefined` соответственно. ### Проверка переменных на определённость From 62d8d0b062a7c070c33c52a0c7303638f3d9156c Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Sun, 2 Jul 2017 16:53:24 +0200 Subject: [PATCH 40/41] fix setInterval again --- doc/ru/other/timeouts.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/ru/other/timeouts.md b/doc/ru/other/timeouts.md index 4a90c80c..79d63110 100644 --- a/doc/ru/other/timeouts.md +++ b/doc/ru/other/timeouts.md @@ -33,11 +33,11 @@ В то время как, при использовании `setTimeout`, исполняющийся в данный момент код будет блокировать запланированный — `setInterval` продолжит планировать последующие вызовы переданной функции. При указании небольших интервалов это повлечь за собой выстраивание функций в ожидающую очередь. function foo(){ - // что-то, выполняющееся десятую секунды или более + // что-то, выполняющееся секунду или более } - setInterval(foo, 100); + setInterval(foo, 1000); -В приведённом примере `foo` в первый же раз заблокирует своим процессом главный поток на десятую секунды. +В приведённом примере `foo` в первый же раз заблокирует своим процессом главный поток на секунду. Пока `foo` блокирует код, `setInterval` продолжает планировать последующие её вызовы. Теперь, когда первая `foo` закончила выполнение, в очереди будет уже **десяток** ожидающих выполнения вызовов `foo`. From 3e458abd55c28cffbfd198df71f07ddb5f686a1e Mon Sep 17 00:00:00 2001 From: Ulric Wilfred Date: Thu, 6 Jul 2017 19:02:50 +0200 Subject: [PATCH 41/41] some minor fixes in Array section --- doc/ru/array/constructor.md | 6 +++--- doc/ru/array/general.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/ru/array/constructor.md b/doc/ru/array/constructor.md index 4a45b0e8..500e0252 100644 --- a/doc/ru/array/constructor.md +++ b/doc/ru/array/constructor.md @@ -9,17 +9,17 @@ new Array(3); // Результат: [] new Array('3') // Результат: ['3'] -В ситуации, когда в конструктор `Array` передаётся только один аргумент, и этот аргумент имеет тип `Number` — конструктор возвращает новый, *разреженный* (_прим. перев._ — *заполненный случайными значениями*) массив, имеющий длину, равную значению переданного аргумента. Стоит заметить, что в этом случае будет установлено лишь свойство `length` нового массива, а реальные индексы массива не будут инициализированы. +В случае, когда в конструктор `Array` передаётся только один аргумент, и этот аргумент имеет тип `Number` — конструктор возвращает новый, *разреженный* (_прим. перев._ — *заполненный случайными значениями*) массив, имеющий длину, равную значению переданного аргумента. Стоит заметить, что в этом случае будет установлено лишь свойство `length` нового массива, а реальные индексы массива не будут инициализированы. var arr = new Array(3); arr[1]; // не определён, undefined 1 in arr; // false, индекс не был установлен -Поведение, позволяющее заранее установить размер массива, может пригодиться лишь в некоторых случаях — например, для повторения строки — так вы сможете не использовать цикл `for`. +Возможность заранее установить размер массива может пригодиться лишь в некоторых случаях — например, для повторения строки — так вы сможете обойтись без использования цикла `for`. new Array(count + 1).join(stringToRepeat); ### Заключение -Использования конструктора `Array` нужно избегать. Литералы, безусловно, намного предпочтительнее — это краткая запись, её синтаксис «чище» — а это, в свою очередь повышает, читабельность кода. +Использования конструктора `Array` следует избегать. Литералы, безусловно, намного предпочтительнее — это краткая запись, её синтаксис «чище» — а это, в свою очередь, повышает читабельность кода. diff --git a/doc/ru/array/general.md b/doc/ru/array/general.md index ac1b0f18..2eabc201 100644 --- a/doc/ru/array/general.md +++ b/doc/ru/array/general.md @@ -1,6 +1,6 @@ ## Перебор массивов и свойств объектов -Несмотря на то, что массивы в JavaScript являются объектами, **не существует** достаточных оснований использовать [цикл `for in`](#object.forinloop) для перебора элементов массива. Наоборот, существует множество весомых причин **против** использования циклов `for in` при переборе массивов. +Несмотря на то, что массивы в JavaScript являются объектами, **нельзя найти** весомых аргументов использовать [цикл `for in`](#object.forinloop) для перебора элементов массива. Наоборот, есть множество убедительных причин **против** использования циклов `for in` при переборе массивов. > **Замечание:** Массивы в JavaScript **не** являются *ассоциативными массивами*. Для группировки ключей и значений по парам в JavaScript есть только [объекты](#object.general). При этом, ассоциативные массивы по определению **сохраняют** заданный порядок свойств, объекты JavaScript этого **не** делают.