renovations
This commit is contained in:
parent
4b8b168fd2
commit
c7d4c7e3ff
172 changed files with 869 additions and 244 deletions
|
@ -0,0 +1,6 @@
|
|||
function isEmpty(obj) {
|
||||
for(var key in obj) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
describe("isEmpty", function() {
|
||||
it("если объект пустой - возвращает true", function() {
|
||||
assert.isTrue( isEmpty({}) );
|
||||
});
|
||||
|
||||
it("если у объекта есть любое свойство, не важно какое - возвращает false", function() {
|
||||
assert.isFalse( isEmpty({ anything: false }) );
|
||||
});
|
||||
});
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
|
||||
```js
|
||||
//+ run
|
||||
function isEmpty(obj) {
|
||||
for(var key in obj) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
var schedule = {};
|
||||
|
||||
alert( isEmpty( schedule ) ); // true
|
||||
|
||||
schedule["8:30"] = "подъём";
|
||||
|
||||
alert( isEmpty( schedule ) ); // false
|
||||
```
|
||||
|
22
1-js/4-data-structures/5-object-for-in/1-is-empty/task.md
Normal file
22
1-js/4-data-structures/5-object-for-in/1-is-empty/task.md
Normal file
|
@ -0,0 +1,22 @@
|
|||
# Определите, пуст ли объект
|
||||
|
||||
[importance 5]
|
||||
|
||||
Создайте функцию `isEmpty(obj)`, которая возвращает `true`, если в объекте нет свойств и `false` -- если хоть одно свойство есть.
|
||||
|
||||
Работать должно так:
|
||||
|
||||
```js
|
||||
function isEmpty(obj) {
|
||||
/* ваш код */
|
||||
}
|
||||
|
||||
var schedule = {};
|
||||
|
||||
alert( isEmpty( schedule ) ); // true
|
||||
|
||||
schedule["8:30"] = "подъём";
|
||||
|
||||
alert( isEmpty( schedule ) ); // false
|
||||
```
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
|
||||
```js
|
||||
//+ run
|
||||
"use strict";
|
||||
|
||||
var salaries = {
|
||||
"Вася": 100,
|
||||
"Петя": 300,
|
||||
"Даша": 250
|
||||
};
|
||||
|
||||
var sum = 0;
|
||||
for(var name in salaries) {
|
||||
sum += salaries[name];
|
||||
}
|
||||
|
||||
alert(sum);
|
||||
```
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
# Сумма свойств
|
||||
|
||||
[importance 5]
|
||||
|
||||
Есть объект `salaries` с зарплатами. Напишите код, который выведет сумму всех зарплат.
|
||||
|
||||
Если объект пустой, то результат должен быть `0`.
|
||||
|
||||
Например:
|
||||
|
||||
```js
|
||||
"use strict";
|
||||
|
||||
var salaries = {
|
||||
"Вася": 100,
|
||||
"Петя": 300,
|
||||
"Даша": 250
|
||||
};
|
||||
|
||||
//... ваш код выведет 650
|
||||
```
|
||||
|
||||
P.S. Сверху стоит `use strict`, чтобы не забыть объявить переменные.
|
|
@ -0,0 +1,24 @@
|
|||
|
||||
|
||||
```js
|
||||
//+ run
|
||||
"use strict";
|
||||
|
||||
var salaries = {
|
||||
"Вася": 100,
|
||||
"Петя": 300,
|
||||
"Даша": 250
|
||||
};
|
||||
|
||||
var max = 0;
|
||||
var maxName = "";
|
||||
for(var name in salaries) {
|
||||
if (max < salaries[name]) {
|
||||
max = salaries[name];
|
||||
maxName = name;
|
||||
}
|
||||
}
|
||||
|
||||
alert(maxName || "нет сотрудников");
|
||||
```
|
||||
|
22
1-js/4-data-structures/5-object-for-in/3-max-salary/task.md
Normal file
22
1-js/4-data-structures/5-object-for-in/3-max-salary/task.md
Normal file
|
@ -0,0 +1,22 @@
|
|||
# Свойство с наибольшим значением
|
||||
|
||||
[importance 5]
|
||||
|
||||
Есть объект `salaries` с зарплатами. Напишите код, который выведет имя сотрудника, у которого самая большая зарплата.
|
||||
|
||||
Если объект пустой, то пусть он выводит "нет сотрудников".
|
||||
|
||||
Например:
|
||||
|
||||
```js
|
||||
"use strict";
|
||||
|
||||
var salaries = {
|
||||
"Вася": 100,
|
||||
"Петя": 300,
|
||||
"Даша": 250
|
||||
};
|
||||
|
||||
// ... ваш код выведет "Петя"
|
||||
```
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
function isNumeric(n) {
|
||||
return !isNaN(parseFloat(n)) && isFinite(n)
|
||||
}
|
||||
|
||||
function multiplyNumeric(obj) {
|
||||
for(var key in obj) {
|
||||
if (isNumeric( obj[key] )) {
|
||||
obj[key] *= 2;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
function isNumeric(n) {
|
||||
return !isNaN(parseFloat(n)) && isFinite(n)
|
||||
}
|
||||
|
||||
// ... ваш код ...
|
|
@ -0,0 +1,13 @@
|
|||
describe("multiplyNumeric", function() {
|
||||
it("умножает численные свойства на 2", function() {
|
||||
var menu = {
|
||||
width: 200,
|
||||
height: "300",
|
||||
title: "Моё меню"
|
||||
};
|
||||
multiplyNumeric(menu);
|
||||
assert.equal( menu.width, 400 );
|
||||
assert.equal( menu.height, 600 );
|
||||
assert.equal( menu.title, "Моё меню" );
|
||||
});
|
||||
});
|
|
@ -0,0 +1,27 @@
|
|||
|
||||
|
||||
```js
|
||||
//+ run
|
||||
var menu = {
|
||||
width: 200,
|
||||
height: 300,
|
||||
title: "My menu"
|
||||
};
|
||||
|
||||
function isNumeric(n) {
|
||||
return !isNaN(parseFloat(n)) && isFinite(n);
|
||||
}
|
||||
|
||||
function multiplyNumeric(obj) {
|
||||
for(var key in obj) {
|
||||
if (isNumeric( obj[key] )) {
|
||||
obj[key] *= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
multiplyNumeric(menu);
|
||||
|
||||
alert("menu width="+menu.width+" height="+menu.height+" title="+menu.title);
|
||||
```
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
# Умножьте численные свойства на 2
|
||||
|
||||
[importance 3]
|
||||
|
||||
Создайте функцию `multiplyNumeric`, которая получает объект и умножает все численные свойства на 2. Например:
|
||||
|
||||
```js
|
||||
// до вызова
|
||||
var menu = {
|
||||
width: 200,
|
||||
height: 300,
|
||||
title: "My menu"
|
||||
};
|
||||
|
||||
multiplyNumeric(menu);
|
||||
|
||||
// после вызова
|
||||
menu = {
|
||||
width: 400,
|
||||
height: 600,
|
||||
title: "My menu"
|
||||
};
|
||||
```
|
||||
|
||||
P.S. Для проверки на число используйте функцию:
|
||||
|
||||
```js
|
||||
function isNumeric(n) {
|
||||
return !isNaN(parseFloat(n)) && isFinite(n)
|
||||
}
|
||||
```
|
||||
|
171
1-js/4-data-structures/5-object-for-in/article.md
Normal file
171
1-js/4-data-structures/5-object-for-in/article.md
Normal file
|
@ -0,0 +1,171 @@
|
|||
# Объекты: перебор свойств
|
||||
|
||||
Для перебора всех свойств из объекта используется цикл по свойствам `for..in`. Эта синтаксическая конструкция отличается от рассмотренного ранее цикла `for(;;)`.
|
||||
|
||||
[cut]
|
||||
|
||||
## for..in [#for..in]
|
||||
|
||||
Синтаксис:
|
||||
|
||||
```js
|
||||
for (key in obj) {
|
||||
/* ... делать что-то с obj[key] ... */
|
||||
}
|
||||
```
|
||||
|
||||
При этом `for..in` последовательно переберёт свойства объекта `obj`, имя каждого свойства будет записано в `key` и вызвано тело цикла.
|
||||
|
||||
[smart header="Объявление переменной в цикле `for (var key in obj)`"]
|
||||
Вспомогательную переменную `key` можно объявить прямо в цикле:
|
||||
|
||||
```js
|
||||
for (*!*var key*/!* in menu) {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
Так иногда пишут для краткости кода. Можно использовать и любое другое название, кроме `key`, например `for(var propName in menu)`.
|
||||
[/smart]
|
||||
|
||||
Пример итерации по свойствам:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
var menu = {
|
||||
width: 300,
|
||||
height: 200,
|
||||
title: "Menu"
|
||||
};
|
||||
|
||||
for (var key in menu) {
|
||||
// этот код будет вызван для каждого свойства объекта
|
||||
// ..и выведет имя свойства и его значение
|
||||
|
||||
*!*
|
||||
alert("Ключ: " + key + " значение:" + menu[key]);
|
||||
*/!*
|
||||
}
|
||||
```
|
||||
|
||||
Обратите внимание, мы использовали квадратные скобки `menu[key]`. Как уже говорилось, если имя свойства хранится в переменной, то обратиться к нему можно только так, не через точку.
|
||||
|
||||
## Количество свойств в объекте
|
||||
|
||||
Как узнать, сколько свойств хранит объект?
|
||||
|
||||
Готового метода для этого нет.
|
||||
|
||||
Самый кросс-браузерный способ -- это сделать цикл по свойствам и посчитать, вот так:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
var menu = {
|
||||
width: 300,
|
||||
height: 200,
|
||||
title: "Menu"
|
||||
};
|
||||
|
||||
*!*
|
||||
var counter = 0;
|
||||
|
||||
for (var key in menu) {
|
||||
counter++;
|
||||
}
|
||||
*/!*
|
||||
|
||||
alert("Всего свойств: " + counter);
|
||||
```
|
||||
|
||||
В следующих главах мы пройдём массивы и познакомимся с другим, более коротким, вызовом: `Object.keys(menu).length`.
|
||||
|
||||
## В каком порядке перебираются свойства?
|
||||
|
||||
Для примера, рассмотрим объект, который задаёт список опций для выбора страны:
|
||||
|
||||
```js
|
||||
var codes = {
|
||||
// телефонные коды в формате "код страны": "название"
|
||||
"7": "Россия",
|
||||
"38": "Украина",
|
||||
// ..,
|
||||
"1": "США"
|
||||
};
|
||||
```
|
||||
|
||||
Здесь мы предполагаем, что большинство посетителей из России, и поэтому начинаем с `7`, это зависит от проекта.
|
||||
|
||||
При выборе телефонного кода мы хотели бы предлагать варианты, начиная с первого. Обычно на основе списка генерируется `select`, но здесь нам важно не это, а важно другое.
|
||||
|
||||
**Правда ли, что при переборе `for(key in codes)` ключи `key` будут перечислены именно в том порядке, в котором заданы?**
|
||||
|
||||
**По стандарту -- нет. Но некоторое соглашение об этом, всё же, есть.**
|
||||
|
||||
Соглашение говорит, что если имя свойства -- нечисловая строка, то такие ключи всегда перебираются в том же порядке. Так получилось по историческим причинам и изменить это сложно: поломается много готового кода.
|
||||
|
||||
С другой стороны, если имя свойства -- число, то все современные браузеры сортируют такие свойства в целях внутренней оптимизации.
|
||||
|
||||
К примеру, рассмотрим объект с заведомо нечисловыми свойствами:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
var user = {
|
||||
name: "Вася",
|
||||
surname: "Петров"
|
||||
};
|
||||
user.age = 25;
|
||||
|
||||
*!*
|
||||
// порядок перебора соответствует порядку присвоения свойства
|
||||
*/!*
|
||||
for (var prop in user) {
|
||||
alert(prop); // name, surname, age
|
||||
}
|
||||
```
|
||||
|
||||
А теперь -- что будет, если перебрать объект с кодами?
|
||||
|
||||
```js
|
||||
//+ run
|
||||
var codes = {
|
||||
// телефонные коды в формате "код страны": "название"
|
||||
"7": "Россия",
|
||||
"38": "Украина",
|
||||
"1": "США"
|
||||
};
|
||||
|
||||
for(var code in codes) alert(code); // 1, 7, 38
|
||||
```
|
||||
|
||||
При запуске этого кода в современном браузере мы увидим, что на первое место попал код США!
|
||||
|
||||
Нарушение порядка возникло, потому что ключи численные. Интерпретатор JavaScript видит, что строка на самом деле является числом и преобразует ключ в немного другой внутренний формат. Дополнительным эффектом внутренних оптимизаций является сортировка.
|
||||
|
||||
**А что, если мы хотим, чтобы порядок был именно таким, какой мы задали?**
|
||||
|
||||
Это возможно. Можно применить небольшой хак, который заключается в том, чтобы сделать все ключи нечисловыми, например, добавим в начало дополнительный символ `'+'`:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
var codes = {
|
||||
"+7": "Россия",
|
||||
"+38": "Украина",
|
||||
"+1": "США"
|
||||
};
|
||||
|
||||
for (var code in codes ) {
|
||||
var value = codes[code];
|
||||
code = +code; // ..если нам нужно именно число, преобразуем: "+7" -> 7
|
||||
|
||||
alert( code + ": " + value ); // 7, 38, 1 во всех браузерах
|
||||
}
|
||||
```
|
||||
|
||||
## Итого
|
||||
|
||||
<ul>
|
||||
<li>Цикл по ключам: `for (key in obj)`.</li>
|
||||
<li>Порядок перебора соответствует порядку объявления для нечисловых ключей, а числовые -- сортируются (в современных браузерах).</li>
|
||||
<li>Для того, чтобы гарантировать перебор ключей в нужном порядке, их делают "нечисловыми", например добавляя в начало `+`, а потом, в процессе обработки, преобразуют ключи в числа.</li>
|
||||
</ul>
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue