Javascript
Объектно-ориентированный язык
с утиной типизацией,
прототипным наследованием
и наследуемой областью видимости
Slide 3
Slide 3 text
Javascript
Объектно-ориентированный язык
Slide 4
Slide 4 text
Javascript
Объектно-ориентированный язык
var myArray = new Array();
myArray[0] = 1;
myArray.push(2);
console.log(myArray.length); // 2
Slide 5
Slide 5 text
Свойства
var myArray = new Array();
myArray[0] = 1;
myArray.push(2);
console.log(myArray.length); // 2
Slide 6
Slide 6 text
Свойства
Методы — тоже свойства.
var myArray = new Array();
myArray[0] = 1;
myArray.push(2);
console.log(myArray.length); // 2
Slide 7
Slide 7 text
Свойства
Методы — тоже свойства.
И элементы массива — тоже.
var myArray = new Array();
myArray[0] = 1;
myArray.push(2);
console.log(myArray.length); // 2
Slide 8
Slide 8 text
Аксессоры
var myArray = new Array();
myArray[0] = 1;
myArray.push(2);
console.log(myArray.length); // 2
Slide 9
Slide 9 text
Аксессоры
[ ] и . равноправны
var myArray = new Array();
myArray[0] = 1;
myArray.push(2);
console.log(myArray.length); // 2
Slide 10
Slide 10 text
Аксессоры
[ ] и . равноправны
var myArray = new Array();
myArray[0] = 1;
myArray.push(2);
console.log(myArray.length); // 2
var myArray = new Array();
myArray[0] = 1;
myArray["push"](2);
console["log"](myArray["length"]); // 2
Slide 11
Slide 11 text
Лирическое отступление
< >
Slide 12
Slide 12 text
var myObject = {
foo: 42;
};
var propertyName = "foo";
/* ... */
eval("myObject." + foo); // 42
Свойства
[1,2,3].length; // 3
"abc".length; // 3
/regExp/.source; // "regExp"
Методы
[1,2,3].push(4);
"abc".toUpperCase();
/regExp/.exec("str");
Slide 16
Slide 16 text
Свойства
[1,2,3].length; // 3
"abc".length; // 3
/regExp/.source; // "regExp"
Методы
[1,2,3].push(4);
"abc".toUpperCase();
/regExp/.exec("str");
Методы — это тоже свойства, только функции,
больше никаких отличий нет.
Slide 17
Slide 17 text
Постойте, если свойства есть у всего, то
В JavaScript всё — объекты
Slide 18
Slide 18 text
В JavaScript всё — объекты
Slide 19
Slide 19 text
Типы
Object
объекты
Array
Function
RegExp
Arguments
string
примитивы
number
boolean
undefined
null
Slide 20
Slide 20 text
При необходимости примитивы преобразуются
в объекты.
var str = "Hello world!";
str.length; // 12
Slide 21
Slide 21 text
При необходимости примитивы преобразуются
в объекты.
var str = "Hello world!";
str.length; // 12
string s — Cвойство «length»?
Slide 22
Slide 22 text
При необходимости примитивы преобразуются
в объекты.
var str = "Hello world!";
str.length; // 12
string s — Cвойство «length»?
— Это примитив, у них
не бывает свойств.
Slide 23
Slide 23 text
При необходимости примитивы преобразуются
в объекты.
var str = "Hello world!";
str.length; // 12
string s — Cвойство «length»?
— Это примитив, у них
не бывает свойств.
— Тогда преобразуй
в объект!
Slide 24
Slide 24 text
При необходимости примитивы преобразуются
в объекты.
var str = "Hello world!";
str.length; // 12
string s
[object String]
Slide 25
Slide 25 text
При необходимости примитивы преобразуются
в объекты.
var str = "Hello world!";
str.length; // 12
string s
[object String] — Cвойство «length»?
Slide 26
Slide 26 text
При необходимости примитивы преобразуются
в объекты.
var str = "Hello world!";
str.length; // 12
string s
[object String] — Cвойство «length»?
— 12
Slide 27
Slide 27 text
При необходимости примитивы преобразуются
в объекты.
var str = "Hello world!";
str.length; // 12
string s
Slide 28
Slide 28 text
Присваивать примитивам свойства
бесполезно.
var str = "Hello world!";
str.foo = 42;
str.foo; // undefined ???
Slide 29
Slide 29 text
Присваивать примитивам свойства
бесполезно.
var str = "Hello world!";
str.foo = 42;
str.foo; // undefined
string s — Установи свойство
«foo» равное 42!
Slide 30
Slide 30 text
Присваивать примитивам свойства
бесполезно.
var str = "Hello world!";
str.foo = 42;
str.foo; // undefined
string s — Установи свойство
«foo» равное 42!
— Это примитив, у них
не бывает свойств.
Slide 31
Slide 31 text
Присваивать примитивам свойства
бесполезно.
var str = "Hello world!";
str.foo = 42;
str.foo; // undefined
string s — Установи свойство
«foo» равное 42!
— Это примитив, у них
не бывает свойств.
— Преобразуй в объект!
Slide 32
Slide 32 text
Присваивать примитивам свойства
бесполезно.
var str = "Hello world!";
str.foo = 42;
str.foo; // undefined
string s
[object String]
Slide 33
Slide 33 text
Присваивать примитивам свойства
бесполезно.
var str = "Hello world!";
str.foo = 42;
str.foo; // undefined
string s
[object String]
foo: 42
— Установи свойство
«foo» равное 42!
— OK
Slide 34
Slide 34 text
Присваивать примитивам свойства
бесполезно.
var str = "Hello world!";
str.foo = 42;
str.foo; // undefined
string s
[object String]
foo: 42
— Свойство «foo»?
— Это примитив.
— Преобразуй в объект!
Slide 35
Slide 35 text
Присваивать примитивам свойства
бесполезно.
var str = "Hello world!";
str.foo = 42;
str.foo; // undefined
string s
[object String]
foo: 42
— Свойство «foo»?
— Нет такого.
[object String]
Slide 36
Slide 36 text
Присваивать примитивам свойства
бесполезно.
var str = "Hello world!";
str.foo = 42;
str.foo; // undefined
string s
Slide 37
Slide 37 text
Преобразования в объект
Object
объекты
Object
Array Array
Function Function
RegExp RegExp
Arguments Arguments
string
примитивы
String
number Number
boolean Boolean
undefined —
null —
Slide 38
Slide 38 text
Преобразования в объект
Undefined и Null не преобразуются в объекты
null.foo; // [TypeError]
undefined.foo; // [TypeError]
Slide 39
Slide 39 text
Преобразования в объект
Можно преобразовать вручную
new String("foo"); // [object String]
new Number(42); // [object Number]
new Boolean(true); // [object Boolean]
Slide 40
Slide 40 text
< >
Slide 41
Slide 41 text
Без маньячеств!
Не стоит использовать примитивы в качестве
объектов для ускорения работы.
Slide 42
Slide 42 text
Slide 43
Slide 43 text
Примитивы присваиваются
по значению
var myNumber = 42;
var myOtherNumber = myNumber;
myOtherNumber++;
myOtherNumber; // 43
myNumber; // 42
Slide 44
Slide 44 text
Примитивы передаются
по значению
function increment(n){
n++;
};
var myNumber = 42;
increment(myNumber);
myNumber; // 42
Slide 45
Slide 45 text
Объекты присваиваются
по ссылке
var myObject = {};
var myOtherObject = myObject;
myOtherObject.foo = 42;
myOtherObject.foo; // 42
myObject.foo; // 42
Slide 46
Slide 46 text
Объекты передаются
по ссылке
function fooize(o){
o.foo = 42;
};
var myObject = {};
fooize(myObject);
myObject.foo; // 42
Slide 47
Slide 47 text
this
var o = {};
o.setFoo = function(fooValue){
this.foo = fooValue;
};
o.setFoo(42);
o.foo; // 42
Slide 48
Slide 48 text
this
В JavaScript this указывает на тот объект,
на котором метод был вызван, а не тот,
на котором определен.
Slide 49
Slide 49 text
this
var array1 = [];
var array2 = [];
array1.add = function(value){
this.push(value);
};
array2.add = array1.add;
array2.add(42);
array1; // []
array2; // [42]
Slide 50
Slide 50 text
this
Чтобы применить функцию (метод), не
обязательно её присваивать объекту.
var array1 = [];
var array2 = [];
array1.add = function(value){
this.push(value);
};
array1.add.call(array2, 42);
array1; // []
array2; // [42]
Slide 51
Slide 51 text
this
Чтобы применить функцию (метод), не
обязательно её присваивать объекту.
var array1 = [];
var array2 = [];
array1.add = function(value){
this.push(value);
};
array1.add.apply(array2, [42]);
array1; // []
array2; // [42]
Slide 52
Slide 52 text
[[class]]
У каждого объекта есть внутреннее свойство
[[class]].
({}).toString(); // "[object Object]"
({}).toString.call([]); // "[object Array]"
({}).toString.call(
function(){}
); // "[object Function]"
({}).toString.call(
document.createElement("div")
); // "[object HTMLDivElement]"
Slide 53
Slide 53 text
Javascript
Объектно-ориентированный язык
с утиной типизацией,
прототипным наследованием
и наследуемой областью видимости
Slide 54
Slide 54 text
Утиная типизация
Slide 55
Slide 55 text
Утиная типизация
Значения автоматически приводятся
к нужному типу, когда это необходимо.
Только когда необходимо, сама по себе,
внезапно, переменная тип поменять не может.
Slide 56
Slide 56 text
Приведение к boolean
var foo = Boolean(bar);
var foo = !!bar;
Slide 57
Slide 57 text
Приведение к boolean
Любой объект всегда приводится к true.
Число приводится к false если равно ±0
или NaN. В остальных случаях — true.
Пустая строка приводится к false.
Остальные — к true.
undefined и null приводятся к false.
Slide 58
Slide 58 text
Приведение к boolean
Любой объект всегда приводится к true.
var foo = new Boolean(false);
foo; // [object Boolean]
Boolean(foo); // true
if (new Boolean(false)){
console.log("truthy"); // "truthy"
}
Slide 59
Slide 59 text
Приведение к string
var foo = String(bar);
var foo = "" + bar;
Slide 60
Slide 60 text
Приведение к string
У объектов вызывается метод valueOf().
Если valueOf() вернул не примитив,
вызывается toString().
({valueOf: function(){
return "foo";
}}) + "bar"; // "foobar"
Slide 61
Slide 61 text
Приведение к number
var foo = Number(bar);
var foo = +bar;
Slide 62
Slide 62 text
Приведение к number
У объекта сначала вызывается valueOf(),
иначе toString().
true приводится к 1.
false приводится к 0.
null приводится к 0.
undefined приводится к NaN
Slide 63
Slide 63 text
Приведение к number
Пустая строка приводится к 0.
"Infinity", "+Infinity", "-Infinity" к ±∞.
Строки по регулярке
^\s*[+-]?(\d*\.)?\d+([eE][+-]?\d+)?\s*$
к значению в десятеричной нотации.
Строки по регулярке
^\s[+-]?*0[Xx][\dA-Fa-f]+\s*$
к значению в шестнадцатеричной нотации.
Остальные строки — к NaN.
Slide 64
Slide 64 text
Из number в string
(number).toString(n);
Преобразовать в строку по базису n.
(n по умолчанию 10)
(32).toString(); // 32
(32).toString(10); // 32
(32).toString(16); // 20
(32).toString(2); // 100000
(32).toString(36); // w
Math.random().toString(36);
Slide 65
Slide 65 text
Из number в string
(number).toPrecision(n);
Отображает только n значащих цифр в числе.
Math.PI.toPrecision(3); // "3.14"
(42).toPrecision(1); // "4e+1"
Slide 66
Slide 66 text
Из number в string
(number).toFixed(n);
Отображает с n цифр после запятой.
0.1 + 0.2; // "0.30000000000000004"
(0.1 + 0.2).toFixed(2); // "0.30"
Slide 67
Slide 67 text
Из string в number
parseInt(s, b);
Разбирает строку как целое число по
основанию b.
Number("12 негритят"); // NaN
parseInt("12 негритят"); // 12
parseInt(""); // NaN
Slide 68
Slide 68 text
Из string в number
parseInt(s, b);
В ECMA-262-3 если b не указано, оно
определяется автоматически.
parseInt("10"); // 10
parseInt("010"); // 8
parseInt("0x10"); // 16
parseInt("10", 10); // 10
parseInt("010", 10); // 10
parseInt("0x10", 10); // 0
Slide 69
Slide 69 text
Из string в number
parseFloat(s);
Разбирает строку как float.
parseFloat("12 негритят"); // 12
parseFloat("9.5"); // 9.5
parseFloat("0x10"); // 0
parseFloat(""); // NaN
parseFloat("Infinity"); // Infinity
Slide 70
Slide 70 text
< >
Slide 71
Slide 71 text
Из number в int32
Побитовые операторы требуют
преобразования number (double) в int32.
12.5 | 0; // 12
~~12.5; // 12
~~NaN; // 0
~~undefined; // 0
Из int32 в uint32
Оператор >>> очищает знаковый флаг
~~0xF0000000; // -268435456
-268435456 >>> 0; // 4026531840
(4026531840).toString(16); // f0000000
Slide 74
Slide 74 text
Slide 75
Slide 75 text
Логические операторы
a && b
a || b
!a
Оба операнда приводятся к boolean.
Slide 76
Slide 76 text
Арифметические операторы
a * b
a / b
a % b
a - b
-a
+a
a++
a--
++a
--a
Оба операнда приводятся к number
Slide 77
Slide 77 text
Сложение
a + b
Если хотя бы один из операндов string,
оба приводятся к string и складываются
как строки.
Иначе — оба к number и складываются
как числа.
Slide 78
Slide 78 text
Побитовые операторы
a & b
a ^ b
a | b
a >> b
a << b
a >>> b
Оба операнда приводятся к int32
Slide 79
Slide 79 text
NaN
Любое сравнение с NaN возвращает false.
NaN никогда ничему не равен.
Даже самому себе.
NaN === NaN; // false
NaN > NaN; // false
NaN < NaN; // false
Slide 80
Slide 80 text
Операторы > и <
Операнды приводятся к примитивам.
Если оба операнда — строки, они
сравниваются лексикографически.
Иначе — приводятся к number.
"99" > "100"; // true
"99" > 100; // false
Slide 81
Slide 81 text
Оператор ===
Не приводит типы.
Если операнды — ссылки на один и тот же
объект, true.
Если операнды примитивы и равны по
значению, true.
В остальных случаях false;
Slide 82
Slide 82 text
Оператор ===
var a = [];
var b = [];
a === b; // false
var a = [];
var b = a;
a === b; // true
42 === "42"; // false
Slide 83
Slide 83 text
Оператор ==
Сравнение с приведением операндов.
Поведение не всегда очевидно
и предсказуемо.
Slide 84
Slide 84 text
==
1. Одинаковый тип?
Если типы операндов одинаковые,
== работает как ===:
Если оба операнда — объекты, они
сравниваются по ссылке, иначе — по
значению.
Slide 85
Slide 85 text
==
1. Одинаковый тип?
2. null или undefined?
Если хотя бы один из операндов null или
undefined:
null равен null.
undefined равен undefined.
null равен undefined.
В остальных случаях false.
Slide 86
Slide 86 text
==
1. Одинаковый тип?
2. null или undefined?
3. Объект в примитив
Если один из операндов объект, он
приводится к примитиву.
Slide 87
Slide 87 text
==
1. Одинаковый тип?
2. null или undefined?
3. Объект в примитив
4. Оба операнда строки?
Если оба операнда строки, сравнить их по
значению.
Slide 88
Slide 88 text
==
1. Одинаковый тип?
2. null или undefined?
3. Объект в примитив
4. Оба операнда строки?
5. Привести к number
Наконец, оба значения приводятся к number и
сравниваются по значению.
Операторы >= и <=
1. Привести оба операнда к примитивам.
2. Сравнить a < b (или a > b).
3. Сравнить a == b.
[] == []; // false
[] <= []; // true ???
[] >= []; // true ???
Slide 91
Slide 91 text
Напоследок,
ради приличия
a += b;
a !== b;
a = a + b;
!(a === b)
Slide 92
Slide 92 text
Javascript
Объектно-ориентированный язык
с утиной типизацией,
прототипным наследованием
и наследуемой областью видимости