Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Основы JS по Флэнэгану; (https://javascript.ru/forum/misc/13989-osnovy-js-po-flehnehganu%3B.html)

JSTalker 23.12.2010 04:25

Основы JS по Флэнэгану;
 
Изучаю ща основы по Флэнэгану.
Многое непонятно. Сухо написано. Но подробно :)
Может перевод еще добавляет.

Тут буду постить возникшие по ходу изучения вопросы.
Чтоб не засирать весь форум мелкими темками :)
Прошу ответить, кто понял :) Ну или отправить по ссылке.
Постараюсь структурировано спрашивать.

Заранее всем спасибо! :)

зы. сейчас нахожусь на регулярных выражениях (отэта Тема!) но многое было непонятно еще раньше. Я в тетрадку записал :)

JSTalker 23.12.2010 05:12

Ну к примеру в программах часто применяется спецификатор var при объявлении переменной, однако javascript, как было сказано достаточно лояльный язык и не ругнется и если мы будем использовать сразу переменную (без var-а). Так зачем его ставить?

exec 23.12.2010 05:28

var создаёт переменную в локальной области видимости, а так она создаётся в глобальной (window).

(function () {
a = 0;
var x = 0;
})();
alert(a); // 0
alert(x); // нету

Kolyaj 24.12.2010 09:51

var, строго говоря, создаёт переменную вообще, да ещё и в текущей области видимости. Без него будет не переменная, а свойство объекта window.

Не надо надеяться на лояльность языка, ногу себе отстрелите в самый неподходящий момент.

x-yuri 24.12.2010 10:42

а чем отличается локальная область видимости от текущей, и глобальная область видимости от свойств объекта window?

Kolyaj 24.12.2010 10:46

Посыл был, что без var переменная не создаётся вообще. Но это теоретическая сторона вопроса.

monolithed 24.12.2010 16:07

Инструкция var определяет каждую из перечисленных переменных путем создания свойства с этим именем в объекте вызова функции, в которой она находится, или в глобальном объекте, если объявление находится не в теле функции.

Kolyaj 24.12.2010 16:13

Отличия между var и без var:
<script type="text/javascript">
try {
    var a = 1;
    b = 1;
    delete a;
    delete b;
    alert(a);
    alert(b);
} catch (e) {
    alert('Error: ' + e.message);
}
</script>

monolithed 24.12.2010 16:58

Цитата:

Сообщение от Kolyaj
Отличия между var и без var:

кстати, хороший пример на предыдущий ответ, т.к. одно из существенных отличий:)
Цитата:

Сообщение от Kolyaj
Без него будет не переменная, а свойство объекта window.


monolithed 24.12.2010 17:09

--offtop: --
upd: Kolyaj вы теперь в Yandex'e?

Kolyaj 24.12.2010 17:49

Да.

x-yuri 24.12.2010 23:32

прикольно :)

JSTalker 03.01.2011 06:50

Цитата:

Сообщение от Kolyaj (Сообщение 85091)
Отличия между var и без var:
<script type="text/javascript">
try {
    var a = 1;
    b = 1;
    delete a;
    delete b;
    alert(a);
    alert(b);
} catch (e) {
    alert('Error: ' + e.message);
}
</script>

хм..
получается б толком не удалилась?
как это соотносится с отличиями в создании переменной?
хм, ну теоретически я понял впрочем.:)

x-yuri 03.01.2011 09:37

как раз b удалилась
var a = 1;
b = 2;
alert([window['a'], window['b']]);

без var в window создается соответствующее свойство

JSTalker 03.01.2011 22:44

x-yuri,
а теперь понял. Т.е. с варом получается этакая независимая (от глобального объекта) переменная?

monolithed 04.01.2011 11:16

Цитата:

Сообщение от JSTalker
а теперь понял. Т.е. с варом получается этакая независимая (от глобального объекта) переменная?

ключевое слово var позволяет объявить переменную в текущей области видимости, без него - свойство глобального объекта window, которое можно удалить в отличии от объвленной переменной с var

Kepa 05.01.2011 10:16

Всем привет, всех с прошедшим! (:

Тоже недавно начал изучать Флэнагана, поэтому решил втиснуться с вопросами в эту темку, надеюсь автор топика не будет против. ;)

К сути:

Прочитал про разницу в работе с переменными "по значению" и "по ссылке" и возник вопрос по строкам - для "иллюстрации" передачи элементарных типов по значению Флэнаган применяет такой код:
var a = 3;
var b = a;
a = 4;
alert(b); // показывает 3

Но он говорит что строки в js неизменяемы и поэтому проверить как они передаются (по ссылке или по значению) невозможно, т.к. аналогичный код для строк не будет работать, хотя можно установить что сравниваются они по значению:
var s1 = "text";
var s2 = "tex" + "t";
alert(s1 == s2); // true

Но у меня возник вопрос, а что все-таки мешает сделать для строк такую проверку:
var str1 = "bunny";
var str2 = str1;
str1 = "rabbid";
alert(str2);// показывает bunny

По идее это показывает что строки копируются по значению, в чем тут тогда загвостка?

P.S. Кстати, почему во втором отрывке кода нет нумерации строк? Тот же тэг JS использовал...

P.P.S. Подумал, посидел, еще подумал, почитал немного дальше и пришла в голову такая мысль - получается что в описанном мною примере в str1 содержится не строка bunny, а ссылка на неё, а при "присваивании" ей новой строки "rabbid" мы создаем эту новую строку и в str1 записываем ссылку на неё, а в str2 у нас просто ссылка на первую строку, которая не удалилась, т.к. на неё еще есть "активная" ссылка. Что-то в этом роде?

Kolyaj 05.01.2011 11:38

Kepa,
все переменные в JS передаются по значению. Просто в случае объектов значением является ссылка на объект. Это сначала трудно осознать, но потом всё встаёт на свои места.

http://dmitrysoshnikov.com/ecmascrip...tion-strategy/

monolithed 05.01.2011 11:43

Числа и строки - элементарный тип данных и передаются они по значению.
А происходит это потому, что ссылочные типы данных не имеют фиксировнного размера и не могут храниться в выделенных 8 байтах памяти.
var a = '10', b = '10';
alert(a*b); //100 выполняем операцию умножения со строковыми операндами, результат которых будет преобразован в числовое значение.

var a = '10', b = '10';
alert(parseInt(a)+parseInt(b)); //20 выполняем операцию сложения со строковыми операндами, результат которых будет преобразован в числовое значение. Метод parseInt() преобразует значение в числовое, т.к. опрератор + может работать как со строками так и с числами



Цитата:

Сообщение от Kepa
P.S. Кстати, почему во втором отрывке кода нет нумерации строк? Тот же тэг JS использовал...

меньше 4 строк

Kolyaj 05.01.2011 11:45

Цитата:

Сообщение от monolithed
var a = '10', b = '10';
alert(a+b); //20 выполняем операцию сложения со строковыми операндами, результат которых будет преобразован в числовое значение.

var a = '10', b = '10';
alert(a+b); //20 выполняем операцию сложения со строковыми операндами, результат которых будет преобразован в числовое значение.

monolithed 05.01.2011 11:47

Kolyaj я думал знак умножение поставил, а 20 вроде стер, т.к. из другого примера (поторопился, забыл parseInt) :D
upd: поправил

Kepa 05.01.2011 11:57

Ок, спасибо за ответы (:

P.S.
Цитата:

Сообщение от monolithed
alert(parseInt(a)+parseInt(b));

вариант который мне больше нравится, вроде в учебнике на этом сайте подсмотрел такое применение оператора "+" :) :
var a = '10', b = '10';
alert(+a+(+b));

monolithed 05.01.2011 12:00

Цитата:

Сообщение от Kepa
вариант который мне больше нравится, вроде в учебнике на этом сайте подсмотрел такое применение оператора "+"

не стоит рано списывать со счетов parseInt()
alert(parseInt('1число')+parseInt('2число'));

Цитата:

Сообщение от Kepa
alert(+a+(+b));

var a = '10', b = '10';
alert(+a+~~b);

Kepa 05.01.2011 12:11

Цитата:

Сообщение от monolithed (Сообщение 86319)
var a = '10', b = '10';
alert(+a+~~b);

...Тили-тили трали-вали,
Это мы не проходили,
это нам не задавали...

monolithed 05.01.2011 12:15

Kepa в книжке, о которой идет речь, есть раздел "Побитовые операторы"

Kepa 05.01.2011 12:27

Я пока на 78-ой странице из 950, потихонечку доберемся и до них. (:

x-yuri 05.01.2011 14:38

Цитата:

Сообщение от monolithed
А происходит это потому, что ссылочные типы данных не имеют фиксировнного размера и не могут храниться в выделенных 8 байтах памяти.

а откуда взяты 8 байтов? Стандарт требует, чтобы нессылочные типы, в частности булевский, хранились в 8 байтах?

и непонятно, какое отношение имеют твои примеры к передаче параметров в функции...

Цитата:

Сообщение от Kepa
вариант который мне больше нравится, вроде в учебнике на этом сайте подсмотрел такое применение оператора "+": ... alert(+a+(+b));

ага, всем по началу нравится писать шифрованный код. Со временем начинаешь компенсировать лаконичность кода длинными комментариями. Некоторые даже привыкают и говорят, что это круто... ;)

monolithed 05.01.2011 17:58

Цитата:

Сообщение от x-yuri
а откуда взяты 8 байтов?

На сколько я помню, то под переменные содержащие значение элементарных типов данных выделяется (это кстати где-то написано в книге Фленагана) 16 бит (строковой литерал), в тоже время для целых чисел 32 бита, а чисел с плавающей точкой 64 бита, с юникодом отдельная история.
Цитата:

Сообщение от x-yuri
и непонятно, какое отношение имеют твои примеры к передаче параметров в функции...

ТС привел пример конкатенации строк, от него я и отталкивался, возможно не так понял.

x-yuri 05.01.2011 19:37

в первую очередь, я имел в виду, что про 8 байт - это не причина:
Цитата:

Сообщение от monolithed
А происходит это потому, что ссылочные типы данных не имеют фиксировнного размера и не могут храниться в выделенных 8 байтах памяти.

во-вторых, реализация сама решает, как ей хранить переменную
в-третьих, не важно, как она это делает
в-четвертых, отдельная история уже не актуальна

Kepa 06.01.2011 06:41

Пока вы спорите у меня возник новый вопрос :)

Прочитал про поразрядное НЕ (~) и у меня возникло недопонимание - как именно представляются отрицательные целые числа (http://javascript.ru/bitwise-operators - эту статью я тоже читал, но все равно до конца так и не понял), поясню:

Число у нас представляется 32 разрядами, при этом старший (левый) разряд - знаковый, т.е. у нас диапазон чисел, если я правильно понял, от (2^31 - 1) до -(2^31). Далее, как представляются целые положительные числа в двоичной системе мне понятно, 1=1; 2=10; 3=11; 4=100; и т.д., при этом все разряды левее старшей единицы равны 0, а вот как представляются отрицательные мне уже непонятно, ну за тем исключением что старший бит равен 1. Возьмем пример из статьи:

314 = 00000000000000000000000100111010

-314 = 11111111111111111111111011000110

Так вот, что мне здесь непонятно - по какому алгоритму во втором случае мы "получаем" из этой последовательности -314, например мне было бы понятен такой вариант:

-314 = 10000000000000000000000100111010

Но насколько я понимаю он понятен человеку, но очень неудобен для "компьютера" в вычислениях (а может и вообще непригоден), в таком случае мне был бы еще понятен вариант такой:

-314 = 11111111111111111111111011000101

Т.е. это ~314, без "дополнения до двойки" - здесь я бы понимал что мы "получаем" -314 как разность максимального числа (все разряды равны 1) и 314, а старший бит указывает что число отрицательное, но в статье говорится что надо еще прибавить единицу, и вот тут я не понимаю, откуда берется эта единица и почему полученный после "дополнения до двойки" результат будет -314. В целом я подозреваю что тут что-то завязано с арифметикой целых чисел (например, если знаковый бит считать за обычный, то (0-1) будет равно максимальному числу, скажем для 8-ми разрядного без знакового представления 0-1 = 255. Будет здорово если кто-нибудь разжует данный момент (:

P.S. Пока писал еще пришла мысль что это может быть связано с тем что у нас нет "отрицательного" нуля и поэтому у нас отрицательных чисел на одно больше чем положительных, может дело в этом? В любом случае хочется точно знать. :)

monolithed 06.01.2011 11:49

~ - унарный оператор, который выполняет порязрядное инвертирование, в т.е. ~1 == 0, ~0 == 1.

Цитата:

Сообщение от Kepa
Но насколько я понимаю он понятен человеку, но очень неудобен для "компьютера" в вычислениях (а может и вообще непригоден)

с точностью наоборот (если не не брать в рачет особенности отдельных индивидуумов)

Kepa 06.01.2011 12:12

Цитата:

Сообщение от monolithed (Сообщение 86460)
~ - унарный оператор, который выполняет порязрядное инвертирование, в т.е. ~1 == 0, ~0 == 1.

Как работает поразрядное отрицание я понимаю, вопрос был совсем не об этом, а о представлении целых отрицательных.

Цитата:

Сообщение от monolithed (Сообщение 86460)
"Но насколько я понимаю он понятен человеку, но очень неудобен для "компьютера" в вычислениях (а может и вообще непригоден)"

с точностью наоборот (если не не брать в рачет особенности отдельных индивидуумов)

Данная цитата относилась к такому представлению отрицательных чисел, где изменяется лишь старший разряд:

-314 = 10000000000000000000000100111010

Как такое может быть менее понятно для человека, чем порязрядное отрицание с дополнением до двойки

-314 = 11111111111111111111111011000110

я не понимаю, может я вхожу в число тех нескольких индивидуумов? ;)

x-yuri 06.01.2011 20:15

Цитата:

Сообщение от Kepa
Пока вы спорите у меня возник новый вопрос

Прочитал про поразрядное НЕ (~) и у меня возникло недопонимание - как именно представляются отрицательные целые числа (http://javascript.ru/bitwise-operators - эту статью я тоже читал, но все равно до конца так и не понял), поясню:

Число у нас представляется 32 разрядами, при этом старший (левый) разряд - знаковый, т.е. у нас диапазон чисел, если я правильно понял, от (2^31 - 1) до -(2^31). Далее, как представляются целые положительные числа в двоичной системе мне понятно, 1=1; 2=10; 3=11; 4=100; и т.д., при этом все разряды левее старшей единицы равны 0, а вот как представляются отрицательные мне уже непонятно, ну за тем исключением что старший бит равен 1. Возьмем пример из статьи:

314 = 00000000000000000000000100111010

-314 = 11111111111111111111111011000110

Так вот, что мне здесь непонятно - по какому алгоритму во втором случае мы "получаем" из этой последовательности -314, например мне было бы понятен такой вариант (http://en.wikipedia.org/wiki/Signed_...gnitude_method):

-314 = 10000000000000000000000100111010

Но насколько я понимаю он понятен человеку, но очень неудобен для "компьютера" в вычислениях (а может и вообще непригоден), в таком случае мне был бы еще понятен вариант такой (http://en.wikipedia.org/wiki/Signed_....27_complement):

-314 = 11111111111111111111111011000101

Т.е. это ~314, без "дополнения до двойки" - здесь я бы понимал что мы "получаем" -314 как разность максимального числа (все разряды равны 1) и 314, а старший бит указывает что число отрицательное, но в статье говорится что надо еще прибавить единицу, и вот тут я не понимаю, откуда берется эта единица и почему полученный после "дополнения до двойки" результат будет -314. В целом я подозреваю что тут что-то завязано с арифметикой целых чисел (например, если знаковый бит считать за обычный, то (0-1) будет равно максимальному числу, скажем для 8-ми разрядного без знакового представления 0-1 = 255. Будет здорово если кто-нибудь разжует данный момент (:

P.S. Пока писал еще пришла мысль что это может быть связано с тем что у нас нет "отрицательного" нуля и поэтому у нас отрицательных чисел на одно больше чем положительных, может дело в этом? В любом случае хочется точно знать.

(добавил ссылки на википедию)

откуда берется единица:
-0010 = 10000 - 0010 = 1111 - 0010 + 0001 = ~0010 + 0001
фактически, в случае ones' complement мы выбираем в качестве нуля 01111, а в случае two's complement - 10000, т.е. на единицу большее число. В результате (two's complement): у нас один ноль, не надо добавлять к результату бит переноса

x-yuri 06.01.2011 20:29

а объяснить все это можно, думаю, так:

нам надо вычесть 0001 (1) из 0010 (2), но мы хотим избавиться от вычитания, т.е. сделать это используя операцию сложения. Отметим, что xxxx + 10000 = xxxx. Тогда 0010 - 0001 = 0010 + 10000 - 0001 = 0010 + <two's complement of 0001>

p.s. это бытовое объяснение на пальцах, и я не в курсе как оно видится с точки зрения представителей академической науки

JSTalker 07.01.2011 07:55

Цитата:

Пример15.5. Сортировка элементов в алфавитном порядке
<script>
function sortkids(e) {
    // Это элемент, потомки которого должны быть отсортированы
    if (typeof e == "string") e = document.getElementById(e);
    // Скопировать дочерние элементы (не текстовые узлы) в массив
    var kids = [];
    for(var x = e.firstChild; x != null; x = x.nextSibling)
        if (x.nodeType == 1 /* Node.ELEMENT_NODE */) kids.push(x);
    // Выполнить сортировку массива на основе текстового содержимого
    // каждого дочернего элемента. Здесь предполагается, что каждый
    // потомок имеет единственный вложенный элемент – узел Text 
    kids.sort(function(n, m) {     // Функция сравнения для сортировки
        var s = n.firstChild.data; // Текстовое содержимое узла n
        var t = m.firstChild.data; // Текстовое содержимое узла m
        if (s < t) return  1;      // Узел n должен быть выше узла m
        else if (s > t) return 1;  // Узел n должен быть ниже узла m
        else return 0;             // Узлы n и m эквивалентны
    });
    
    // Теперь нужно перенести узлыыпотомки обратно в родительский элемент
    // в отсортированном порядке. Когда в документ вставляется уже 
    // существующий элемент, он автоматически удаляется из текущей позиции,
    // в результате операция добавления этих копий элементов автоматически
    // перемещает их из старой позиции. Примечательно, что все текстовые узлы, 
    // которые были пропущены, останутся на месте.
    for(var i = 0; i < kids.length; i++) e.appendChild(kids[i]);
}
</script>
<ul id="list"> <!—Этот список будет отсортирован   >
<li>один<li>два<li>три<li>четыре<li>пять 
<!!! элементы не в алфавитном порядке   >
</ul>
<!!! кнопка, щелчок на которой запускает сортировку списка   >
<button onclick="sortkids('list')">Сортировать</button>

просьба прокомментировать:
1. Ситуацию с циклом for: видимо есть какой то шаблон (каркас), на котором можно реализовывать различные варианты циклов for: ( in )? (firstChild, !=null, nextSibling). В частности как работает вариант с firstChild, nextSibling?
2. Все таки ситуацию с sort()-ом, не понять:
2.1 Сравнивающая функция может иметь только 2 аргумента?
2.2 Эти m и n ни что иное как l и r в QuickSort?
Как вообще лучше читать такие сорты?
А то у меня мозг перегревается их анализировать :)

Kepa 07.01.2011 09:00

x-yuri,

Спасибо, более-менее разобрался (:

monolithed 07.01.2011 13:48

Цитата:

Сообщение от JSTalker
Ситуацию с циклом for: видимо есть какой то шаблон (каркас)

не знаю насколько корректно получилось, но как-то так:
for(<инициализация>;<условие>;<корректирование>){
//тело цикла
}

Цикл начинает работу (ищит следущий дочерний элемент e) с выражения x = e.firstChild, и работает до тех пор пока не получит значение null (как доберется до несущестующего элемента - e.lastChild+1)

Может этот вариант поможет понять:
<script type="text/javascript">
window.onload = function(){
    var element = document.getElementById('div'), //родительский элемент
        children = element.childNodes, //дочернии элементы
        i = children.length, array = []; //получаем количество элементов и создаем пустой массив
    if(element.hasChildNodes()) { //проверяем есть ли дочернии элементы
        while(i--){
            if(children[i].tagName != undefined) { //отбираем, только те которые не имеют значение undefined
                array.push(children[i].tagName + ': ' +children[i].innerHTML + '\n'); //добавляем в массив
            }
        }
    }
    alert(array.join(''));
};
</script>

<div id="div">
    <div>0</div>
    <div>1</div>
    <div>2</div>
</div>


тоже самое (без линих проверок), только пошустрей:
var element = document.getElementById('div').childNodes, i = element.length, array = [];

while(i--){
    array.push(element[i].nodeType == 1 ? element[i].innerHTML + '\n' : '');
}

alert(array.join(''));

x-yuri 07.01.2011 17:32

<!DOCTYPE HTML>
<html>
  <head>
      <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/mootools/1.3.0/mootools-yui-compressed.js"></script>
  </head>
  <body>   

  <ul id="list">
      <li>один<li>два<li>три<li>четыре<li>пять
  </ul>
  <button>Сортировать</button>

  <script>

    $$('button').addEvent('click', function(){
        $('list').getChildren()
            .sort(function(a, b){
                if( a.get('text') == b.get('text') )
                    return 0;
                return   a.get('text') < b.get('text')
                    ? -1
                    : 1;
            })
            .inject( $('list') );
    });

  </script>

  </body>
</html>

---
var element = document.getElementById('div'), //родительский элемент
        children = element.childNodes, //дочернии элементы
        i = children.length, array = []; //получаем количество элементов и создаем пустой массив
    if(element.hasChildNodes()) { //проверяем есть ли дочернии элементы
        while(i--){
            if(children[i].tagName != undefined) { //отбираем, только те которые не имеют значение undefined
                array.push(children[i].tagName + ': ' +children[i].innerHTML + '\n'); //добавляем в массив
            }
        }
    }

может в каких-нибудь фреймворках такой код и имеет смысл, но только не в real life...

Цитата:

Сообщение от JSTalker
1. Ситуацию с циклом for: видимо есть какой то шаблон (каркас), на котором можно реализовывать различные варианты циклов for: ( in )? (firstChild, !=null, nextSibling). В частности как работает вариант с firstChild, nextSibling?

ты не знаешь, как работает for? http://javascript.ru/for

Цитата:

Сообщение от JSTalker
2. Все таки ситуацию с sort()-ом, не понять:
2.1 Сравнивающая функция может иметь только 2 аргумента?
2.2 Эти m и n ни что иное как l и r в QuickSort?
Как вообще лучше читать такие сорты?

да, 2 аргумента и не важно как сортировка реализована. Твоя задача: вернуть -1, 0 или 1

Цитата:

Сообщение от Kepa
Спасибо, более-менее разобрался (:

и все же не до конца?

Kepa 07.01.2011 17:38

Цитата:

Сообщение от x-yuri
и все же не до конца?

Нет, вполне разобрался - суть в том что у нас нет отрицательного нуля, поэтому при поразрядном отрицании мы получаем отрицательное число, модуль которого на 1 больше изначального, и чтобы его привести к соответствию мы добавляем единицу. Просто чтобы "привыкнуть" к этому надо немного времени и практики (:

Kolyaj 07.01.2011 18:02

Цитата:

Сообщение от Kepa
суть в том что у нас нет отрицательного нуля

В JS есть.
http://javascript.ru/ecma/part8#a-8.5
Цитата:

Заметим, что существуют как положительный ноль, так и отрицательный ноль.Для краткости и в пояснительных целях эти значения также могут обозначаться +0 и -0 соответственно. (Заметим, что эти два нулевых числовых значения получаются при помощи выражений +0 (или просто 0) и -0.)


Часовой пояс GMT +3, время: 08:19.