Вы находитесь на странице: 1из 46

JavaScript

Подзаголовок

Александр Мочёнов
Вопросы

• Кто считает, что он знает JavaScript?


• Кто считает, что JavaScript - какашко?

1
Я не буду говорить о
• DOM
• Истории JS и его будущем
• Регулярных выражениях, Таймерах
• Подробно о Массивах
• Конвеншенах
• И многом другом ...
2
А лучше раскажу о

• О feature’ах
• О том, о чём кто-то может не знать
• О том почему JavaScript - клёвый

3
Факты и мысли

• JavaScript - is NOT Java!


• JavaScript has prototypal inheritance
• Популярность
• Один для веба
• The amazing thing about JS is …
4
Литералы
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

String()

Number()
Object()
Boolean()

... etc
5
Объекты
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!"};
}
}
};

cat["do"]("eat"); //do - is reserved word


assert(cat.status === "eating");

cat["do"]("clean_wc");
>>> Uncaught #<an Object>

6
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
Функции
обычные объекты

function talk(buddy){
return "I talk with " + buddy + " for " +
talk.long + " minutes";
};

talk.long = 5;

assert(talk("John") === "I talk with John for 5 minutes");

8
Функции - создание
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
Анонимная функц.

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
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
Вызов функции
простой и метод

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
Вызов функции
псевдо-конструктор

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
Вызов функции
конструктор

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
Вызов функции
var DeathStar = function (){
this.enemy = "Rebel Alliance";
this.shoot = function(){
return "Shoot " + this.enemy + " with superlaser";
};
};

var deathStar = new DeathStar();


assert(deathStar.shoot() ===
"Shoot Rebel Alliance with superlaser");

//!!! Rebels captured the Death Star ...


assert(
deathStar.shoot.apply({enemy:"Dark Side"}) ===
"Shoot Dark Side with superlaser"
);
15
Scope

//No C style block scopes


var outside = 10;
for(;;){
var inside = 10;
break;
}
assert(outside === inside);

//Global Scope is Bad, but necessary

16
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
(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
(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
(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 \"" + letters[k] + "\" !";
});
})(i);
}
for(var j = 0; j < sayArr.length; j++){
console.log(sayArr[j]());
}
//Say "D" !
//Say "E" !
//Say "V" !
//...
20
(function(){})();
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 \"" + letters[i] + "\" !";
})(i)
);
}
for(var j = 0; j < sayArr.length; j++){
console.log(sayArr[j]());
}

22
(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
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
Closure - guess number
function makeGame(){
var theNumber = Math.round(Math.random() * 10);
var numberOfGuesses = 0;
return function(guess){
numberOfGuesses++;
if(guess == theNumber){
return "You did it in " + numberOfGuesses + " tries";
}else{
return "No. My number is " +
(guess < theNumber ? "bigger" : "smaller");
}
};
};
var tryToGuess = makeGame();
tryToGuess(3); // --> No. My number is bigger
tryToGuess(7); // --> No. My number is smaller
tryToGuess(5); // --> You did it in 3 tries
25
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
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
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
Наследование

• Наследование от объекта к объекту


• Prototype - ссылка на родителя
• Всё идёт от Object

29
Prototype
function Monkey(){};
var codeMonkey = new Monkey();

Monkey.prototype.code = function(){ return "Code, code!"; };


assert( codeMonkey.code() === "Code, code!");

function Vasja(){};
Vasja.prototype = new Monkey();

var progerVasja = new Vasja();


Vasja.prototype.decide = function(){
return "Shut-up lemons, I know what to do!"; };

assert( progerVasja.decide() === "Shut-up lemons, I know what to do!");


assert( progerVasja.code() === "Code, code!");

30
Наследование

• Прототипное наследование
• Классическое, типа Классы и всё такое
• Функциональное
• Подробнее расскажет Вася.

31
Дополнения к примитивам

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
Кэширование метода
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
Кэширование метода
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
Вкусненькое
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
Вкусненькое
использование && и || в выражениях

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
Вкусненькое
falsy values

if(0 || NaN || '' || false || null || undefined){


//All those values are falsy
assert(false);
}else{
//All other are truthy
assert(true);
}

37
Вкусненькое
evil twins == и ===

assertFalse('' == '0'); //false


assertTrue( 0 == '' ); //true
assertTrue( 0 == '0'); //true

assertFalse(false == 'false'); //false


assertTrue( false == 0); //true

assertFalse(false == undefined); //false


assertFalse(false == null); //false
assertTrue( null == undefined); //true

assertTrue(' \t\r\n' == 0); //true

38
Вкусненькое
evil twins

assertFalse('' === '0');


assertFalse( 0 === '' );
assertFalse( 0 === '0');

assertFalse(false === 'false');


assertFalse(false === 0);

assertFalse(false === undefined);


assertFalse(false === null);
assertFalse( null === undefined);

assertFalse(' \t\r\n' === 0);

39
Вкусненькое
null, parseInt, IEEE 754, NaN

//null
var nullable = null;
assert(typeof nullable === 'object');
assert(nullable === null);

//pasreInt
assert(parseInt("08") === 0); //Octal
assert(parseInt("08", 10) === 8); //Decimal

//IEEE 754
assert(0.1 + 0.2 !== 0.3);

//NaN
var notANum = NaN;
assert(typeof notANum === 'number');
assert(notANum !== notANum);
assert(isNaN(notANum));
40
Вкусненькое
brackets style

function iLikeCStyleBrackets()
{
return
{
word:"boo-gaga"
}
}

var s = iLikeCStyleBrackets();
//assert(s.word === "boo-gaga"); //Makes error
assert(s === undefined);

41
Вкусненькое
brackets style

function iLikeCStyleBrackets()
{
return;
{
word:"boo-gaga"
};
};

42
Вкусненькое
brackets style

function iUseGoodBrackets(){
return {
word:"good boy"
};
};
var s = iUseGoodBrackets();
assert(s.word === "good boy");

43
Книги

Douglas Crockford John Resig David Flanagan

JavaScript: JavaScript:
JavaScript Ninja The Definitive Guide
The Good Parts
JavaScript – это клёва!
Спасибо!

Александр Мочёнов
soswow@gmail.com

Вам также может понравиться