javascript oop

100
JavaScript

Upload: constantin-kichinsky

Post on 13-May-2015

3.241 views

Category:

Technology


0 download

DESCRIPTION

Лекция Константина Кичинского по ООП в JavaScript в рамках курса по ООП. Каф. Вычислительная математика и программирование, МАИ

TRANSCRIPT

Page 1: JavaScript OOP

JavaScript

Page 2: JavaScript OOP

Общие сведения o JavaScript

Page 3: JavaScript OOP

JavaScript: The World's Most Misunderstood Programming Language

— Douglas Crockford,senior JavaScript Architect at

Yahoo!

Page 4: JavaScript OOP

JavaScript != Java

Page 5: JavaScript OOP

JavaScript ~ ECMAScriptJavaScript 1.5 ~ ECMAScript 3

JavaScript 2.0 ~ ECMAScript 5

Page 6: JavaScript OOP

Реализации JavaScript

— V8, Google Chrome— TraceMonkey, SpiderMonkey, Gecko,

Mozilla Firefox— Jscript, Trident, IE— Futhark, Presto, Opera— KJS, KHTML, Konqueror— JavaScriptCore, SquirreFish, WebKit,

Safari, Adobe AIR

Page 7: JavaScript OOP

Инструменты для работы

— Firebug, Firefox— DevTools (F12), IE8— Dragonfly, Opera

— Visual Studio, Expression Web— Aptana— Dreamweaver— …

Page 8: JavaScript OOP

Библиотеки на JavaScript

— Prototype— jQuery— Mootools— Dojo— Ext— Qooxdoo— YUI— ASP.NET Ajax— …

Page 9: JavaScript OOP

Nearly all of the books about JavaScript are quite awful. They contain errors, poor examples, and promote bad practices.

— Douglas Crockford,senior JavaScript Architect at

Yahoo!http://javascript.crockford.com/

Page 10: JavaScript OOP

OOP в JavaScript

Page 11: JavaScript OOP

Типы данных: примитивы + объекты. Примитивы в общем-то тоже объекты.

Page 12: JavaScript OOP

Примитивы

— Number — 1, 3, 1011, 11.12, 2e+3— String — “a”, “bla-bla-bla”, “0”— Boolean — true | false— null— undefined

Page 13: JavaScript OOP

Ссылочные типы

— Date — new Date(1211623944453);— Error — new Error(“Oops!”);— RegExp — /^web.*$/i;— Array — [ “apple”, “banana” ]— Function — function(x) { return

x*x; }

Page 14: JavaScript OOP

Boolean

Number

String

null

undefined

Date

Error

RegExp

Array

Function

Object

Примитивы Ссылочные типы

Page 15: JavaScript OOP

Объекты

— ассоциативные массивы, хеш-таблицы

— Ключ: Значение

Page 16: JavaScript OOP
Page 17: JavaScript OOP

Простой объект

var ufo= {};ufo.name = ‘Mars UFO’;ufo.stealsCows = true;

Page 18: JavaScript OOP

Простой объект

var ufo= {stealsCows: true,isCowsStealer: function() {

return this. stealsCows;}

};

ufo.isCowsStealer(); //true

Page 19: JavaScript OOP

Объекты как хеш

o.name = “Moon UFO”;

o[“name”] = “Moon UFO”;

for ( var key in o ) {alert( key + “: “ + o[key] );

}

Page 20: JavaScript OOP

Object literal notation

{ a: 1, b: “js” }

Page 21: JavaScript OOP

Массивы тоже объекты [, ]

typeof [ 1, 2, 3 ];// “object”

Page 22: JavaScript OOP

Array literal notation

[ 1, “js” ]

Page 23: JavaScript OOP

JavaScript Object Notation (JSON )

{ num: 1, str: “abc”, arr: [ 1, 2, 3 ] }

Page 24: JavaScript OOP

Функции

Функции являются объектами!—Имеют свойства—Имеют методы—Могут копироваться, удаляться, …—Особенность: их можно

вызвать/выполнить

Page 25: JavaScript OOP

Функции

function steal(what) {return what;

}

Page 26: JavaScript OOP

Функции

var steal = function (what) {return what;

};

* Здесь используется анонимная функция, об этом позже

Page 27: JavaScript OOP

Функции

var steal = function steal(what) {return what;

};

Page 28: JavaScript OOP

Функции являются объектами

steal.length// 1steal.name//”steal”

Page 29: JavaScript OOP

Функции являются объектами

var snaffle = steal;snaffle(“Cow”);//”Cow”snaffle.call(null, “Calf”);//”Calf”snaffle.apply(null, [ “Calf” ]);//”Calf”

Page 30: JavaScript OOP

Возвращаемое значение

• Все функции возвращают значение

• Если функция ничего не возвращает явным образом, возвращается undefined

• Функции могут возвращать объекты, включая другие функции

Page 31: JavaScript OOP

Вызов метода с нужной областью видимости

При вызове moo this ссылается на указанную область видимости scopefunction moo() {

this.BigSaucerEyes();};moo.call( scope, arg1, arg2, …);moo.apply( scope, [arg1, arg2, …] );

Page 32: JavaScript OOP

Тут начинается магия

Область видимости «по умолчанию» — Window

var UFO = function UFO() {this.name = “FO”;return this; // посмотрим, что это за this

};UFO // UFO()UFO() // Window… Oops!!! Window.name is “FO”new UFO() // Object name=“FO”

Page 33: JavaScript OOP

Тут продолжается магия

var ufo = new UFO() эквивалентно

var ufo = {};UFO.call(ufo, null)

ufo // Object name=“FO”

Если this возвращается вручную внутри конструктора (return this), тогда можно писатьvar ufo = UFO.call({}, null);

Page 34: JavaScript OOP

Замыкания (Closures)

• Соседние функции• Вложенные функции имеют

доступ к локальным переменным даже после выполнения внешней функции

Page 35: JavaScript OOP

Замыкания (Closures)

function outer(){

var count = 1;function inner() { count++; };return inner;

}var myClosure = outer();myClosure(); // count == 2myClosure(); // count == 3

Page 36: JavaScript OOP

Функции-конструкторы

• При вызове с оператором new функции возвращают объект, обозначаемый как this

• Этот объект можно изменять перед передачей из фунции

Page 37: JavaScript OOP

Функции-конструкторы

function UFO(name){this.name = name;this.getName = function() {

return this.name;};

};

Page 38: JavaScript OOP

Вызов функции-конструктора

var ufo = new UFO(“Mars UFO”);ufo.getName();//”Mars UFO”

Page 39: JavaScript OOP

instanceof

var ufo= new UFO(“Moon UFO”);ufo instanceof UFO;// true

Page 40: JavaScript OOP

Конструкторы — всего лишь функции

Page 41: JavaScript OOP

Свойство constructor

function UFO() {};var ufo = new UFO();ufo.constructor;// function();ufo.constructor === UFO;// true

UFO | function

ufo | object constructor

Page 42: JavaScript OOP

Свойство constructor

var o = {};o.constructor === Object// true[1, 2].constructor === Array;// true

Page 43: JavaScript OOP

Встроенные конструкторы

• Object• Array• Function• RegExp• Number• String• Boolean• Date• Error, SyntaxError, ReferenceError, …

Page 44: JavaScript OOP

Эффективность использования

Хорошо Плохо

var o = {}; var o = new Object();

var a = []; var a = new Array();

var re = /[a-z]/gmi; var re = new RegExp(‘[a-z]’, ‘gmi’);

var fn = function(a, b) {return a+b;

}

var fn = new Function(‘a, b’, ‘return a+b’);

Page 45: JavaScript OOP

Статические свойства и методы

Функции — объекты. Свойства и методы конструктора — работают как статические.

UFO.COUNT = “100500”;UFO.getCount = function() {

return UFO.COUNT;};

Page 46: JavaScript OOP

Private-члены

function UFO(name) {var _name = name; // private variablethis.getName = function() {

return _name;};

};

var ufo= new UFO(“Mars UFO”);alert( ufo.getName() );

Page 47: JavaScript OOP

Private-члены

function UFO(name) {var _name = name;// private methodvar _fixName = function() {return _name.toUpperCase();};this.getName = function() {return _fixName();};

};

Page 48: JavaScript OOP

Namespace

if (typeof FlyingObjects== “undefined”) { FlyingObjects = {};

}if (typeof FlyingObjects.Undefined ==

“undefined”) { FlyingObjects.Undefined = {};

}FlyingObjects.Undefined.UFO = function() {};var smallUFO = new

FlyingObjects.Undefined.UFO;

Page 49: JavaScript OOP

В JavaScript нет классов.

Page 50: JavaScript OOP

Наследование копированием

(примеси)

Page 51: JavaScript OOP

Два объекта

var roundShinyObject= { shiny: true, round: true

};

var ufo = {name: “UFO”,getName: function() {

return this.name;}

};

Page 52: JavaScript OOP

extend()

function extend(parent, child) {for (var key in parent) {

child[key] = parent[key];}

}

extend(roundShinyObject, ufo);ufo.round; // true

Page 53: JavaScript OOP

Прототипное наследование

Page 54: JavaScript OOP

Prototype

Специальное свойство функциональных объектов. prototype – это объект!var UFO = function () {};typeof UFO.prototype;//”object”

Page 55: JavaScript OOP

Изменение prototype

UFO.prototype.name = “UFO”;UFO.prototype.stealCow = function()

{};

Page 56: JavaScript OOP

Перезапись prototype

UFO.prototype= {name: “UFO”, cows: 2};

Page 57: JavaScript OOP

prototype используется при вызове функции-

конструктора

Page 58: JavaScript OOP

Использование prototype

var UFO = function(name) {this.name = name;

};UFO.prototype.stealCow = function() {

// steal a cow};

Page 59: JavaScript OOP

Использование prototype

var ufo= new UFO(“Mars UFO”);ufo.name;// “Mars UFO”ufo.stealCow();// Cows--

Page 60: JavaScript OOP

Использование prototype

stealCow() — метод объекта prototype, но ведет себя так, как будто является методом самого объекта ufo

ufo.hasOwnProperty(‘name’);// trueufo.hasOwnProperty(‘stealCow’);// falseufo.prototype.hasOwnProperty(‘stealCow’);// true

Page 61: JavaScript OOP

Привязка свойств и методов

// к объекту thisfunction Cow(name) {

this.moo = function() { alert(“Moo”) };};// к объекту prototypefunction Cow(name) {};Cow.prototype.moo =

function () { alert(“Moo”) };};

Page 62: JavaScript OOP

prototype используется при поиске метода или

свойства

Page 63: JavaScript OOP

ufo: UFO

FO

UFO

Поиск свойств и методов

ufo.stealCow

found?

found?

found?

undefined

no

no

no

yes

yes

yes

Page 64: JavaScript OOP

isPrototypeOf()

UFO.prototype.isPrototypeOf(ufo);// trueObject.prototype.isPrototypeOf(ufo);// true

Page 65: JavaScript OOP

__proto__

Объекты имеют «секретную» ссылку на прототип конструктора, который их создал

__proto__ может не поддерживаться в некоторых браузерах

var UFO = function(){};var ufo = new UFO;ufo.__proto__ == UFO.prototype //true

Page 66: JavaScript OOP

__proto__

ufo.__proto__.hasOwnProperty(‘stealCow’)// true

ufo. __proto__. __proto__.hasOwnProperty(‘toString’)

// true

Page 67: JavaScript OOP

prototype наследуются

Page 68: JavaScript OOP

«Живые» prototype

typeof ufo.isCowsStealer;// “undefined”UFO.prototype.isCowsStealer = true;ufo. isCowsStealer;// true

Page 69: JavaScript OOP

Наращивание prototype

• Затрагивает все новые объекты• Затрагивает все созданные объекты(!)• Позволяет модифицировать

существующие объекты

String.prototype.trim = function() {return this.replace(/^\s+/, “”);

};alert(“ ufo”.trim());

Page 70: JavaScript OOP

Наращивание prototype

Number.prototype.times = function(f) {for (var i = 0; i < this; i++)

f();};(5).times(function(){ alert(“Moo”); });

Page 71: JavaScript OOP

Родительский конструктор

function FlyingObject() {this.name = “Flying Object”;this.getName = function() {

return this.name;};

};

Page 72: JavaScript OOP

«Детский» конструктор

function UFO() {this.shiny = true;this.round = true;

};

Page 73: JavaScript OOP

Замена prototype

UFO.prototype = new FlyingObject;

var ufo = new UFO();ufo.name = “Mars UFO”;

ufo.round; // trueufo.getName(); // “Mars UFO”

Page 74: JavaScript OOP

Вызов «superclass»-конструктора

function FlyingObject(name) {this.name = name;

}function UFO(name) {

// super(name)FlyingObject.call( this, name );this.stealCow = function() {};

};UFO.prototype = new FlyingObject;

Page 75: JavaScript OOP

Переопределение методов

function UFO(){};UFO.prototype.stealCow = function() { /*Steal a

Cow*/ };

function MegaUFO(){};MegaUFO.prototype = new Dow;

MegaUFO.prototype. stealCow = function() {// super.stealCow();UFO.prototype.stealCow.call(this);alert(“Yahoo!”);

};

Page 76: JavaScript OOP

Абстрактные «классы»

function UFO() {if (this._id == UFO._id) {

throw new Error(“No UFOs, please!”);}

}UFO._id = “UFO”;UFO.prototype._id = “UFO”;var ufo = new UFO(); // Error

Page 77: JavaScript OOP

Улучшение наследования

При использовании абстрактного класса появляется ошибкаMegaUFO.prototype = new UFO; // Error

Решение: использовать пустой порождающий объект для создания наследования

Page 78: JavaScript OOP

Порождающий объект

function inherit(o) {function Dummy(){};Dummy.prototype = o.prototype;return new Dummy();

}

MegaUFO.prototype = inherit(UFO);

Page 79: JavaScript OOP

FP в JavaScript

Page 80: JavaScript OOP

Nested Functions: Globals

function stealCow(cow) {// steal a cow

}function stealCows() {

this.radar(“foundCow”, stealCow); }

stealCows();

Page 81: JavaScript OOP

Nested Functions: Variables

var stealCow = function(cow) {// steal a cow

}var stealCows = function() {

this.radar(“foundCow”, stealCow); }

stealCows();

Page 82: JavaScript OOP

Nested Functions: Function First-style

function stealCows() {function stealCow(cow) {

// steal a cow}this.radar(“foundCow”, stealCow);

}

stealCows();

Page 83: JavaScript OOP

Nested Functions: Pyramid Order

Переменная stealCow создается до инициализации конкретной функцией

function stealCows() {this.radar(“foundCow”, stealCow); function stealCow(cow) {

// steal a cow}

}

stealCows();

Page 84: JavaScript OOP

Nested Functions: Inline function

function stealCows() {this.radar(“foundCow”, function stealCow(cow) {

// steal a cow});

}

stealCows();

Page 85: JavaScript OOP

Nested Functions: Amomymous

function stealCows() {this.radar(“foundCow”, function(cow) {

// steal a cow});

}

stealCows();

Page 86: JavaScript OOP

Передача функций как параметров

function moo(m) {return m + “moo”;

}function twice(fn) {

return function(x) {return fn(fn(x));

}}

var moomoo = twice(moo);moomoo(“Save your bodies”);

Page 87: JavaScript OOP

Хранение функций в таблице

var mooTable = {“+moo”: function(x) { return x + “Moo!”; },“+mo2”: function(x) { return x + “Moo-Moo!”; }

};mooTable[“+moo”](“UFOs!”);mooTable[“+mo2”](“Fresh Grass!”);

Page 88: JavaScript OOP

Построение реестра

var mooTable = {};function register(name, fn) { FnTable[name] = fn; }function makeMoomer(moo) {

return function(x) { return x + moo; }}register(“+moo”, makeMoomer(“Moo!”));register(“+mo2”, makeMoomer(“Moo-Moo!”));

mooTable[“+moo”](“UFOs!”);mooTable[“+mo2”](“Fresh Grass!”);

Page 89: JavaScript OOP

Ручные стражи

for (var cow in cows) steal(cow);

function callIfFat(fn) {return function(x) {

return isFat(x) ? fn(x) : undefined;}

}var stealFat = callIfFat(steal);

for (var cow in cows) stealFat(cow);

Page 90: JavaScript OOP

Guard Construction

function guard(fn ,g) {return function(x) {return g(x) ? fn(x) : undefined;}

}

var stealFat = guard(steal, isFat);

for (var cow in cows) stealFat(cow);

Page 91: JavaScript OOP

Замыкания

function callLater(o, property, value){ return function(){

o[property] = value; };

}

var shine = callLater(ufo, “shiny”, false);

wowEffect=setTimeout(shine, 500);

Page 92: JavaScript OOP

«Кража» методов

var ufo = { shine: function() {

this.shiny = true; }

};var cow = {};

ufo.shine(); // ufo is shinyufo.shine.call(cow); // cow is shiny!ufo.shine.apply(cow, []); // cow is shiny!

Это лучше, чем cow.shine = ufo.shine; cow.shine();

Page 93: JavaScript OOP

argumentsarguments – специальное свойство внутри функции, но это не Array!

// не работает!function joinInHerd() {

var herd = arguments.join(“, “);}

// «кража» метода у Arrayfunction joinInHerd() {

var herd = [].join.call(arguments, “, “);}

// вытаскивание метода из prototypefunction joinInHerd() {

var herd = Array.prototype.join.call(arguments, “, “);}

Page 94: JavaScript OOP

Наращивание prototype

Function.prototype.twice = function() {var fn = this;return function() {

return fn.call(this, fn.apply(this, arguments));};

}

function moo(x) { return x + “Moo!”; }var mo2 = moo.twice();mo2(“Ufos!!!”);

Page 95: JavaScript OOP

Анонимные функции

var UFO = function(name){this.name = name;this.getName = function() {

return this.name;};

};UFO.name // “”

Анонимная функция

$&*# | function

UFO | function

Page 96: JavaScript OOP

Анонимные функции

function guard(fn ,g) {return function(x) {

return g(x) ? fn(x) : undefined;}

}

Анонимная функция

Page 97: JavaScript OOP

Анонимные функции

Анонимные функции позволяют ограничить область видимости и область выполнения — idempotent function

function() {var cow = { name: “Cow” };stealCow (cow);

}();

Page 98: JavaScript OOP

bind

function shine() {this.shiny = true;

}shine(); // Window is shinyy = shine.bind(cow);y(); // cow is shiny

Page 99: JavaScript OOP

bind (prototypejs)

function bind(context) { if (arguments.length < 2 &&

Object.isUndefined(arguments[0])) return this;

var __method = this, args = slice.call(arguments, 1);

return function() { var a = merge(args, arguments); return __method.apply(context, a); }

}

Page 100: JavaScript OOP

Слайд #100