6. Литералы var obj = {object: "literal" }; // === new Object(); var str = "string literal" ; // === new String(); var arr = [10, 20, 30]; // === new Array(); var num = 10; // === new Number(); var boo = true ; // === new Boolean(); var reg = /regexp literal/i ; // === new RegExp(); var fun = function (){ return true ;} // === new Function(); var dat = new Date(2010, 11, 30); // no literal Object() String() Number() Boolean() ... etc 5
7. Объекты cat [ "do" ]( "eat" ); //do - is reserved word assert( cat .status === "eating" ); cat [ "do" ]( "clean_wc" ); >>> Uncaught #<an Object> var cat = { actions:{ sleep: function (){ cat .status = "sleeping" ; }, eat: function (){ cat .status = "eating" ; }, clean_wc: function (){ cat .status = "cleaning wc" ; } }, loves: [ "sleep" , "eat" ], "do" : function ( action ){ if ( this .loves.has( action ) ){ this .actions[ action ](); } else { throw {name: "Cat Exception" , message: "Br-r-r!" }; } } }; 6
8. for ... in var budget = { beer : 1250, sandwich : 500, pizza: 670 }; var sum = 0; for (item in budget ){ if ( budget .hasOwnProperty(item)){ sum += budget [item]; } } assert( sum === 2420); 7
9.
10. Функции - создание var twiceTen = getTwice(10); //Can use it before declaration // - Function as Expression function getTwice ( value ){ return value * 2; }; assert( twiceTen === 20); // - Function as statement var pub = function priv ( param ){ //param, and priv are visible only here. }; pub(111); //Can use it after declaration. 9
11. Анонимная функц. var callme = function ( func ){ return func(); //calling passed function }; var res = callme( function (){ //I am anonymous function return "Thank you" ; }); assert( res == "Thank you" ); 10
12. arguments var argArr = function ( args ){ return Array.prototype.slice.apply( args ); }; var argSum = function (){ var sum = 0; var argArray = argArr(arguments); argArray .push(5); for ( var i = 0; i < argArray .length; i ++){ sum += argArray [ i ]; } return sum ; }; assert(argSum(1,2,3,4) === 15); 11
13. Вызов функции простой и метод function simpleFunction (){ //this => global object return "simple value" ; }; assert(simpleFunction() === "simple value" ); var obj = { value: "simple value" , method: function (){ //this => parent object return this .value; } }; assert( obj .method() === "simple value" ); 12
14. Вызов функции псевдо-конструктор var juice = function ( type ){ return { make: function (){ //this - parent object this .ready = true ; }, drink: function (){ if ( this .ready){ return "Drinking " + type + " juice!" ; } } }; }; var juice1 = juice( "pineapple" ); juice1 .make(); assert( juice1 .drink() === "Drinking pineapple juice!" ); 13
15. Вызов функции конструктор var Jazz = function ( artist ){ //this - is newly created object (if "new" was used) this .music = "on" ; this .play = function (){ if ( this .music === "on" ){ return artist + " is playing" ; } } return undefined ; //for demo only }; var jazz = new Jazz ( "Louis Armstrong" ); assert( jazz .play() === "Louis Armstrong is playing" ); 14
16.
17. Scope //No C style block scopes var outside = 10; for (;;){ var inside = 10; break ; } assert( outside === inside ); //Global Scope is Bad, but necessary 16
18. Scope var globalVar = 10; function one (){ var innerVar = 10; function two (){ var innerInnerVar = 10; noVarVar = 10; assert( globalVar === innerVar && innerVar === innerInnerVar ); } assert( globalVar === innerVar ); //innerInnerVar - not in this scope two(); } one(); //Only global variables is in this scope assert( globalVar === noVarVar); 17
19. (function(){})(); var letters = [ "D" , "E" , "V" , "C" , "L" , "U" , "B" ]; var sayArr = []; for ( var i = 0; i < letters .length; i ++){ sayArr .push( function (){ return "Say " + letter[ i ] + "!" ; }); } for ( var j = 0; j < sayArr .length; j ++){ console.log( sayArr [ j ]()); } //Say undefined! //Say undefined! //Say undefined! //... 18
20. (function(){})(); var letters = [ "D" , "E" , "V" , "C" , "L" , "U" , "B" ]; var sayArr = []; for ( var i = 0; i < letters .length; i ++){ sayArr .push( function (){ return "Say " + i + "!" ; }); } for ( var j = 0; j < sayArr .length; j ++){ console.log( sayArr [ j ]()); } //Say 7 //Say 7 //Say 7 //... 19
21. (function(){})(); var letters = [ "D" , "E" , "V" , "C" , "L" , "U" , "B" ]; var sayArr = []; for ( var i = 0; i < letters .length; i ++){ ( function ( k ){ sayArr .push( function (){ return "Say amp;quot;" + letters [ k ] + "amp;quot; !" ; }); })( i ); } for ( var j = 0; j < sayArr .length; j ++){ console.log( sayArr [ j ]()); } //Say "D" ! //Say "E" ! //Say "V" ! //... 20
22. (function(){})(); 22 var letters = [ "D" , "E" , "V" , "C" , "L" , "U" , "B" ]; var sayArr = []; for ( var i = 0; i < letters .length; i ++){ sayArr .push( ( function ( i ){ return "Say amp;quot;" + letters [ i ] + "amp;quot; !" ; })( i ) ); } for ( var j = 0; j < sayArr .length; j ++){ console.log( sayArr [ j ]()); }
23. (function(){})(); var yourLib = ( function (){ var i = 10; var b = 20; //your scoped code here function innerLib ( c ){ return c + i + b ; }; return innerLib; })(); //i, b not visible here assert(yourLib(30) === 60); 23
24. Closure I’m gonna build my own amusement park. With ... var RudeRobot = function (){ var beerCans = 0; //Private variable this .drinkBeer = function (){ beerCans ++; return this ; }; }; var bender = new RudeRobot (); bender .drinkBeer().drinkBeer(); //Can't find out how many beers Bender drunk 24
25.
26. Closure - fibonacci var count = 0; var fibonacci = function fib ( n ){ count ++; return n < 2 ? n : fib( n - 1) + fib( n - 2); }; for ( var i = 0; i <= 10; i += 1){ console.log( i + " -> " + fibonacci( i )); } assert( count === 453); //453 calls 26
27. Closure - fibonacci var count = 0; var fibonacci = ( function (){ var memo = [0, 1]; var fib = function ( n ){ count ++; var result = memo [ n ]; if ( typeof result !== 'number' ){ result = fib( n - 1) + fib( n - 2); memo [ n ] = result ; } return result ; }; return fib ; })(); for ( var i = 0; i <= 10; i ++){ console.log( i + " -> " + fibonacci( i )); } assert( count === 29); 27
28. Curry - friends function friends ( boy , girl ){ return boy + " and " + girl + " are friends." ; } var boysFriends = function (){ var thatArgs = argArr(arguments); return function (){ var thisArgs = argArr(arguments); return friends.apply( null , thatArgs .concat( thisArgs )); }; }; var johnsFriends = boysFriends( "John" ); assert(johnsFriends( "Jully" ) === "John and Jully are friends." ); assert(johnsFriends( "Marta" ) === "John and Marta are friends." ); 28
29.
30.
31.
32. Дополнения к примитивам Array.prototype.map = function ( fn ){ for ( var i = 0, size = this .length; i < size ; i ++){ this [ i ] = fn .call( this [ i ], i , this ); } return this ; }; var arr = [1,2,3,4].map( function ( i , array ){ if ( this % 2 == 0){ return this * 3; } return this ; }); assert( arr == "1,6,3,12" ); // == using for casting 32
33. Кэширование метода Function.prototype.cached = function (){ var _cache = {}; var fun = this ; return function (){ var args = argArr(arguments); var result = _cache [ args ]; if (! result ){ result = fun .apply( null , args ); _cache [ args ] = result ; } return result ; }; }; 33
34. Кэширование метода Function.prototype.cached = function (){ ... var count = 0; var fibo = function ( n ){ count ++; return n < 2 ? n : fibo( n - 1) + fibo( n - 2); }.cached(); for ( var i = 0; i <= 10; i += 1){ console.log( i + " -> " + fibo( i )); } assert( count === 12); 34
35. Вкусненькое scope var var APP = { constants: { MAX_BUK: 10, MIN_BUK: 20 }, messages: { hello_world: "Hello World" , cancel: "Cancel" }, sayHello: function (){ return this .messages.hello_world; } }; 35
36. Вкусненькое использование && и || в выр а жениях var action = function (){ return work && work .doing && work .doing() || "stay home" ; }; assert(action() === "stay home" ); var work = { doing: function (){ return "hard working" ; } }; assert(action() === "hard working" ); 36
37. Вкусненькое falsy values if (0 || NaN || '' || false || null || undefined ){ //All those values are falsy assert( false ); } else { //All other are truthy assert( true ); } 37
Представиться. Будут номера – вопросы в конце. Вас ждёт куча примеров =)
Моя задача сегодня сделать так, что бы и те и другие засамневались =)
JavaScript – это очень обширная тема и за 45 минут обо всём не расскажешь. По-этому вот об этом я говорить НЕ буду. (Перечислить) И о многом другом
вкусности
Прежде всего – не путайте ЖС с Жавой. Между ними совершенно ничего общего, кроме названия и чем-то схожево синтаксиса!! ЖаваСкрипт – скорее Лисп в одежде Си. ДжаваСкрипт - Это прототипно-ореентированный язык с динамической типизацией. Прототипное наследование является фишкой, которой нету во многих других языках. ЖС – один из самых популярных языков программирования на земле. В то же время это один из самых ненавистных и непонятых языков =) Часто на ЖС клевещат не по делу, путая ЖС с ДОМ-ом, который реализована просто ужасно. Т.е. ЖС – является деФакто языком программирования в вебе, то у людей, знающих другие языки попросту нет права выбора, а по-этому часто и желания изучать ЖС, что ведёт к непониманию и нелюбви. =) Удивительная особенность ЖС заключается в том, что можно написать что-то работающее и нужное на ЖС без особых знаний самого языка, или даже программирования в целом.
В языке есть несколько основных или примитивных типом. Все или почти все они приведены на экране. Все наследуются от прородителя Обжект, и все они могут быть созданы с помощью соответствующих конструкторов, но так делать НЕ НАДО! В каждом из случаев за исключением Даты необходимо использовать литералы.
В ЖС практически всё является объектом, а он представляет из себя простой МАП, с ключами и значениями. Ключами может быть ЧТО угодно и значениями тоже. (Описать что на экране) (сказать о зарезервированных словах)
Ключи можно итерировать вот таким образом. Как я скажу ещё раз позже объекты в ЖС могут наследовать свойства от других объектов. У любого объекта есть вот такой метод, который подтверждает что такой ключи есть у данного объекта.
Функция – это обычный объект. Т.е. к самой функции можно прицепить какое-то свойство.
Функцию можно создать несколькими способами. Обычный способ . Так называемый «выражение» при поможи литералов. При этом способе дикларации функция как бы всплывает в начало скоупа и её можно использовать до её появления в коде Второй способ. Так называемый «утверждение». Т.к. Это обычное присвоение к переменной, то использовать можно только после появления в коде. Можно назвать (прив) и присвоить к переменной (пуб), при этом (прив) будет видна только внутри метода.
Функцию не обязательно называть. Тогда она является анонимной. В данном случае мы посылаем анонимную функцию (показать) в качестве аргумента. А потом её вызываем (показать).
Внутри любой функции есть магическая переменная arguments, в которой .... Это Массиво-подобный объект, т.е. ... С помощью вот такой операции из него можно сделать обычный массиов. Этот метод делает сл. ...
Внутри каждого метода есть ещё одна магическая переменная this – в зависимости от того как вы вызываете функцию, this ссылается на разные вещи. Вызывать функции можно так же несколькими способами: – обычный вызов (показать). Тут this – ссылается на глобальный объетк. (об этом позже) - если функция является свойством объекта, то это вызов функции как метода. this - ссылка на объект от которого вызывается метод.
3) Вызов как конструктор, но псевдо. Конструктор, потому что он на выходе выдает объект. Псевдо, потому-что это обычный объект.
4) Вызов метода как конструктор. Для этого при вызове надо добавить ключевое слово new и тогда эта функция возвращает новый объект, который создаёт сама функция. Внутри таких функций this ссылается на новый объект, который создат сама функция. (показать) Если эту функцию вызвать без new то случиться страшное. ... Для того, что бы этого не случалось есть конвеншн, по которому методы конструктуры начинаются с большой буквы.
У каждой функции есть два метода apply и call. С помощью них можно вызвать сам метод послав им в качестве аргументов то, на что внутри самой функции будет ссылаться this , а так же можно заслать аргументы.
ЖС не Си. Тут операторский скобки и различные блоки не делают нового скоупа. В ЖС скоуп создаёт метод! В ЖС есть понятие глобального скоупа, мало того, для написания в ЖС кода его необходимо использовать. Но делать это надо как можно реже. Далее будут показаны пару способов как это сделать. (Объяснить код)
Для того, что бы задекларировать свойство внутри ближайшего скоупа надо использовать ключевое слово var (показать) . Если это опустить, то переменная уйдёт в глобальный скоуп.
Объяснить код. И что я хочу что бы случилось. Но что-то не так.
Заменим массив на индекс. И wtf – почему везде 7. Потому-что тут i является ссылкой на этот i . А к моменту вызова в этой переменной лежит 7. (т.к. Список пробежал) Как обойти?
Использовать вот такую конструкцию. Т.е. Мы делаем анонимную функцию, и тут же её вызываем. Теперь уже и ссылается на аргумент этой функции. И всё работает.
Эту конструкцию можно пихнуть даже в качестве аргумента в метод. В этом случае эта анонимная функция возвращает нашу функцию ,которая потом вернёт нужную нам фразу.
Многие либы используют эту конструкцию что бы не засорять глобальный скоуп разными переменными. Т.е. Мы делаем анонимную функцию, пихаем в неё всё что нам нужно. Всё то, что создаёт саму либу – и на выходе выдаём объект в котором всё есть. Таким образом в глобальном скоупе лежит только один объект – наша либа.
Кложеры. Когда функция имеет доступ к контексту в виде скоупа другой функции, в которой она была создана. В данном случае beerCons видна только внутри конструктора. Т.е. Метод drinkBeer находиться тоже внутри конструктора, он тоже видит эту переменную и может её использовать.
Более интересный пример. Описать что делает программа.
Классическая задача вычисления радов фибоначи. 453 вызова.
С помощью такой конструкции можно сделать функцию вычисляющий рады фибоначи, но при этом у неё есть доступ к массиву внутри кложера, в который при каждов вызове мы кладём вычесленное значение, и если оно уже было вычислено – то возвращаем его. 29 вызовов.
Карринг – популярная тема. Т.е. Мы может сделать функцию, которая является другой функцией, у которой уже определена часть аргументов.
1) 2) У каждого есть свойство protoype, которая ссылается на прорадителя.
Описать код.
Можно дополнять примитивные типа. Например так.
Можно сделать вот такое вот переопределение. Которое я назвал кэшем. Эта конструкция делает нечто подобное, что я делал с фибоначи. Но! Это можно прицепить к любой функции. Например.
Если применить это к тому же фибоначи, то получается даже 12 вызовов.
Итак. А теперь на последок. Всякие вкусненькие мелочи. Тут мы видим некую переменную, в которой есть всё, что нам надо в нашей аппликации. Опять таки для того, что бы не засорять глобальный скоуп,
В ЖС существуют два дьявольских близнеца в виде двух операторов сравнения. С помощью дьявольского брата == можно получить такие вот чудеса.
С === всё так как надо. От сюда правило!!! Всегда используйте ===
Особый тип нул Использование parseInt Сложение двух чисел с плавающей точкой Особая штука NaN
Тут две проблемы – фугурные скобки и отсутствие точки с запятой. WTF – почему тут undefined.
ЖС сам проставляет точки с запятой. И тогда всё становиться понятно.
Ставте скобки ТАК! И ставте точку с запятой после определения функций
В ЖС есть очно много плохих мест, которые надо знать в лицо и стараться избегать их, но так же в нём есть много такого, чего нет вдругих языках, чето-то такого, что делает его очень клёвым! =)