Organizacja ucząca się Javascript - wprowadzenie

Podobne dokumenty
PHP 5 język obiektowy

Tworzenie stron internetowych z wykorzystaniem HTM5, JavaScript, CSS3 i jquery. Łukasz Bartczuk

10. Programowanie obiektowe w PHP5

Kurs WWW. Paweł Rajba.

JavaScript funkcyjność

Singleton. Cel: Przykład: Zastosowanie: Zapewnienie, że klasa ma tylko jedną instancję i dostarczenie globalnego dostępu do niej.

1. Które składowe klasa posiada zawsze, niezależnie od tego czy je zdefiniujemy, czy nie?

Programowanie obiektowe

Test przykładowy 2 PAI WSB Wrocław /06/2018

JavaScript - korzenie

Oracle PL/SQL. Paweł Rajba.

Klasy Obiekty Dziedziczenie i zaawansowane cechy Objective-C

Projektowanie obiektowe oprogramowania Wykład 4 wzorce projektowe cz.i. wzorce podstawowe i kreacyjne Wiktor Zychla 2015

Typy metod: konstruktory, destruktory, selektory, zapytania, iteratory.

Zaawansowane programowanie w języku C++ Programowanie obiektowe

Podstawy Programowania Obiektowego

Projektowanie obiektowe oprogramowania Wykład 4 wzorce projektowe cz.i. wzorce podstawowe i kreacyjne Wiktor Zychla 2017

Programowanie obiektowe

Inne podejścia obiektowe. Referat na seminarium magisterskie Zagadnienia Programowania Obiektowego Dymitr Pszenicyn

Programowanie współbieżne Wykład 8 Podstawy programowania obiektowego. Iwona Kochaoska

JavaScript. Wstęp do podstaw elementów. dr inż. Paweł Boiński, Politechnika Poznańska

Programowanie obiektowe

Programowanie obiektowe. Wykład 4

Materiały do zajęć VII

Programowanie 2. Język C++. Wykład 3.

Zaawansowane programowanie w języku C++ Klasy w C++

Aplikacje w środowisku Java

Wykład 5: Klasy cz. 3

Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 3. Karol Tarnowski A-1 p.

Typy klasowe (klasy) 1. Programowanie obiektowe. 2. Założenia paradygmatu obiektowego:

PARADYGMATY PROGRAMOWANIA Wykład 4

Common Lisp - funkcje i zmienne

Prototype (prototyp) Cel: Przykład: Określenie rodzaju tworzonych obiektów poprzez wskazanie ich prototypu. Nowe instancje tworzymy kopiując prototyp.

Metaprogramowanie w Ruby

IMIĘ i NAZWISKO: Pytania i (przykładowe) Odpowiedzi

Programowanie obiektowe

Programowanie obiektowe

PROE wykład 2 operacje na wskaźnikach. dr inż. Jacek Naruniec

Pola i metody statyczne. Klasy zawierające pola i metody statyczne

Wykład 8: klasy cz. 4

Wstęp. Ale po co? Implementacja

Sieciowe Technologie Mobilne. Laboratorium 2

Podstawy programowania. Wykład PASCAL. Wstęp do programowania obiektowego. dr Artur Bartoszewski - Podstawy programowania, sem.

Zaawansowane programowanie w C++ (PCP)

Java: kilka brakujących szczegółów i uniwersalna nadklasa Object

Programowanie obiektowe - 1.

Wykład 3 Składnia języka C# (cz. 2)

Laboratorium nr 12. Temat: Struktury, klasy. Zakres laboratorium:

.NET Klasy, obiekty. ciąg dalszy

TECHNOLOGIE INTERNETOWE WYKŁAD 6. JavaScript Funkcje i obiekty

Obiektowy PHP. Czym jest obiekt? Definicja klasy. Składowe klasy pola i metody

Typy zmiennych proste i złożone. Programowanie komputerów. Tablica. Złożone typy zmiennych. Klasa. Struktura

Enkapsulacja, dziedziczenie, polimorfizm

Klasy. dr Anna Łazińska, WMiI UŁ Podstawy języka Java 1 / 13

Informatyka I. Dziedziczenie. Nadpisanie metod. Klasy abstrakcyjne. Wskaźnik this. Metody i pola statyczne. dr inż. Andrzej Czerepicki

Aplikacje w środowisku Java

Informacje ogólne. Karol Trybulec p-programowanie.pl 1. 2 // cialo klasy. class osoba { string imie; string nazwisko; int wiek; int wzrost;

Java - tablice, konstruktory, dziedziczenie i hermetyzacja

Swift (pol. jerzyk) nowy język programowania zaprezentowany latem 2014 r. (prace od 2010 r.)

C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018

Programowanie obiektowe

Patryk Jar Meet.js, Gdańsk 11 marca 2013 r. MODULARNY JAVASCRIPT

Wyrażenie include(sciezka_do_pliku) pozwala na załadowanie (wnętrza) pliku do skryptu php. Plik ten może zawierać wszystko, co może się znaleźć w

Dokumentacja do API Javy.

Przykład 1: Funkcja jest obiektem, przypisanie funkcji o nazwie function() do zmiennej o nazwie funkcja1

Swift (pol. jerzyk) nowy język programowania zaprezentowany latem 2014 r. (prace od 2010 r.)

Instrukcja 3 PROGRAMOWANIE OBIEKTOWE

Kurs programowania. Wykład 2. Wojciech Macyna. 17 marca 2016

Programowanie obiektowe w VB cz 2

Co to jest NODE.JS? Nowoczesne środowisko programistyczne

Programowanie obiektowe

C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy INNE SPOSOBY INICJALIZACJI SKŁADOWYCH OBIEKTU

Obiekt klasy jest definiowany poprzez jej składniki. Składnikami są różne zmienne oraz funkcje. Składniki opisują rzeczywisty stan obiektu.

Rozdział 4 KLASY, OBIEKTY, METODY

Tworzenie Stron Internetowych. odcinek 10

Wstęp do programowania INP001213Wcl rok akademicki 2017/18 semestr zimowy. Wykład 6. Karol Tarnowski A-1 p.

Instrukcja do pracowni specjalistycznej z przedmiotu. Obiektowe programowanie aplikacji

Programowanie obiektowe

2. Klasy cz. 2 - Konstruktor kopiujący. Pola tworzone statycznie i dynamicznie - Funkcje zaprzyjaźnione - Składowe statyczne

Język C++ Programowanie obiektowe

Builder (budowniczy) Cel: Przykład:

PHP: bloki kodu, tablice, obiekty i formularze

Polimorfizm, metody wirtualne i klasy abstrakcyjne

Współbieżność w środowisku Java

Podstawy programowania III

Programowanie obiektowe, wykład nr 6. Klasy i obiekty

Konstruktory. Streszczenie Celem wykładu jest zaprezentowanie konstruktorów w Javie, syntaktyki oraz zalet ich stosowania. Czas wykładu 45 minut.

Dziedziczenie. Streszczenie Celem wykładu jest omówienie tematyki dziedziczenia klas. Czas wykładu 45 minut.

Na przykładzie języków Java, C# i odrobiny C++ Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki

Programowanie obiektowe Wykład 3. Dariusz Wardowski. dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/21

Technologie cyfrowe semestr letni 2018/2019

Język C++ wykład VII. uzupełnienie notatek: dr Jerzy Białkowski. Programowanie C/C++ Język C++ wykład VII. dr Jarosław Mederski. Spis.

Dziedziczenie. Tomasz Borzyszkowski

Klasy abstrakcyjne, interfejsy i polimorfizm

Modelowanie i Programowanie Obiektowe

Szablony klas, zastosowanie szablonów w programach

TEMAT : KLASY DZIEDZICZENIE

Klasa jest nowym typem danych zdefiniowanym przez użytkownika. Najprostsza klasa jest po prostu strukturą, np

JĘZYKI PROGRAMOWANIA Z PROGRAMOWANIEM OBIEKTOWYM. Wykład 6

Transkrypt:

Organizacja ucząca się Javascript - wprowadzenie 07-03-2014 Wiktor Zychla

Agenda Wprowadzenie Funkcje/domknięcia Obiekty this Dziedziczenie Enkapsulacja Perspektywy Egzamin

Wprowadzenie - historia 1995 Brendan Eich dla Netscape 1996 ECMA 262 1996 Microsoft wprowadza do IE3 1998 ES2 1999 ES3 2009 ES5 2011 ES5.1 201? ES6 http://kangax.github.io/es5-compat-table/

Host Kod Javascript wykonuje się w ramach hosta, typowo jest to przeglądarka. Do obiektu hosta jest dostęp jawny: window.x = 3; x = 3; // równoważne, zmienna globalna Zmienne lokalne var x = 3;

Host Host daje dostęp do struktury dokumentu który jest aktualnie załadowany (DOM). Javascript może tę strukturę dynamicznie modyfikować. Obecnie większość przeglądarek ma silniki kompilujące Javascript do kodu natywnego przed wykonaniem. Javascript nie tylko jest więc coraz bardziej zgodny, ale też jest bardzo szybki. http://www.wiktorzychla.com/2014/02/animated-javascript-juliafractals.html http://jsdosbox.appspot.com/

Funkcje Funkcje nazwane/nienazwane function() { function f() {

Funkcje Funkcje zdefiniowane w compile-time vs run-time f(); function f() { vs f(); var f = function() {

Zasięg widoczności zmiennych Globalny var x = 5; var f = function() { console.log('x='+x); f();

Zasięg widoczności zmiennych Lokalny var x = 5; var f = function() { var x = 1; console.log('x='+x); f();

Zasięg widoczności zmiennych Uwaga na hoisting var x = 5; var f = function() { console.log('x='+x); var x = 3; f();

Zasięg widoczności zmiennych Hoisting polega na tym, że w zasięgu bloku wszystkie zmienne są wirtualnie zdefiniowane na początku bloku. var x = 5; var f = function() { var x; console.log('x='+x); x = 3; f();

Funkcje Javascript jest językiem funkcyjnym funkcje mogą być przekazywane do funkcji jako argumenty i zwracane jako wyniki.

Funkcje Funkcja przekazywana jako argument function f(g) { return g(); f(function() { return 1; );

Funkcje Funkcja zwracana jako wartość function f() { function g() { return 1; return g; f()();

Domknięcia Domknięcie to ukryty parametr funkcji, który łapie wszystkie zmienne z których funkcja korzysta, ale nie definiuje ich. function sum1(x,y) { return x + y; console.log( sum1(2,3) );

Domknięcia To samo z domknięciem function sum2(x) { function helper(y) { return x + y; return helper; console.log(sum2(2)(3)); Kontekst funkcji wewnętrznej helper domyka zmienną x.

Domknięcia Ekstremalnie: function sum3(x) { var _s = x; function helper(y) { _s += y; return helper; helper.tostring = function() { return _s; return helper; var result = sum3(1)(2)(3)(4); // dowolna liczba parametrów console.log(result);

Domknięcia Kontekst jest obiektem, więc może być modyfikowany: function f(person) { function g(message) { console.log( 'message [' + message + '] to ' + person.name ); return g; var p = { name : 'jan' var messenger = f(p); messenger('witaj!'); // witaj to jan p.name = 'tomasz'; messenger('ukłony'); // ukłony to tomasz

Domknięcia Co czasem bywa nieoczekiwane function createfs(n) { // tworzy tablicę n funkcji var fs = []; // i-ta funkcja z tablicy ma zwrócić i var i; for ( i=0; i<n; i++ ) { fs[i] = function() { return i; ; // <- funkcja się nie wykonuje, jest obiekt kontekstu do którego trafia i // ale wartość i się zmienia zanim funkcje zaczną się wykonywać ; return fs; var myfs = createfs(10); console.log( myfs[0]() ); // zerowa funkcja miała zwrócić 0 console.log( myfs[2]() ); // druga miała zwrócić 2 console.log( myfs[7]() ); // output : 10,10,10, oops, wszystkie zwracają 10!

Domknięcia Ale nietrudno to naprawić function createfs(n) { var fs = []; var i; for ( i=0; i<n; i++ ) { fs[i] = function(x) { return function() { return x; ; (i); // <- funkcja od razu się wykonuje i za każdym razem tworzy nowy kontekst // (n różnych kontekstów vs jeden i ten sam) ; return fs; var myfs = createfs(10); console.log( myfs[0]() ); console.log( myfs[2]() ); console.log( myfs[7]() ); // output: 0, 2, 7

Obiekty Najprościej var p = {; p.name = 'jan'; console.log(p.name); // albo new Object(); Notacja. vs [] var p = { p.name = 'jan'; p['name'] = 'tomasz'; console.log(p.name); Notacja [] jest bardziej ogólna bo parametr może być wyrażeniem var p = { p.name = 'jan'; p['na'+'me'] = 'tomasz'; console.log(p.name);

Obiekty Składnia literalna (literal syntax) var p = { name : 'jan', age : 15 console.log( p.name ); Drzewa obiektów (obiekty kompozytowe) var p = { name : 'jan', address : { city : 'wrocław' console.log( p.address.city );

Obiekty - dygresja Iteracja po tablicy vs iteracja po polach obiektu var a = []; a.push(1); a.push(2); for ( var i=0; i<a.length; i++ ) console.log( a[i] ); vs var p = { name : 'jan', age : 17 for ( var key in p ) { console.log( key + ' : ' + p[key] );

Obiekty - dygresja Parametry są przekazywane przez wartość function f( x ) { x = 123; var a = 1; f(a); console.log(a); // 1. funkcja nie modyfikuje wartości czyli w przypadku obiektów przez wartość referencji function f( x ) { x.age = 123; var p = { age : 1 ; f(p); console.log(p.age); // 123. // referencja nie jest modyfikowana ale pole za nią tak

This v.1 W funkcjach instancji obiektu this odnosi się do instancji obiektu var person = { name : 'jan', say : function() { return this.name; console.log( person.say() );

This v.2 W funkcjach spoza obiektów this odnosi się domyślnie do hosta (window) var name = 'jan'; say = function() { return this.name; console.log( say() );

This v.2 ale można wywołać funkcję nie wprost, tylko przez call, które jako pierwszy parametr przyjmuje obiekt dowiązywany to this wewnątrz funkcji p = { name : 'jan' ; say = function() { return this.name; console.log( say.call( p ) );

This v.2 - dygresja Wywołania przez call a apply p = { name : 'jan' ; say = function(m1, m2) { return this.name + ' has ' + m1 + ' and ' + m2; console.log( say.call( p, 'a', 'b' ) ); // lista parametrów p = { name : 'jan' ; say = function(m1, m2) { return this.name + ' has ' + m1 + ' and ' + m2; console.log( say.apply( p, ['a', 'b'] ) ); // tablica parametrów

Dziedziczenie W Javascript nie ma klas. Tyle że w języku obiektowym nie potrzeba klas potrzeba obiektów. Nowe obiekty tworzy się albo ad-hoc albo klonując istniejące wzorcowe obiekty mówimy o nich prototypy. var personproto = { name : 'jan', say : function() { return this.name; // prototyp var p1 = Object.create( personproto ); // klonowanie prototypu p1.name = 'tomasz'; var p2 = Object.create( personproto ); p2.name = 'janusz'; console.log( p1.say() ); console.log( p2.say() );

Dziedziczenie Nieoczekiwany problem - obiekt kompozytowy w prototypie var personproto = { name : 'jan', address : { city : 'wrocław', say : function() { return this.address.city; var p1 = Object.create( personproto ); p1.address.city = 'kraków'; var p2 = Object.create( personproto ); p2.address.city = 'łódź'; console.log( p1.say() ); console.log( p2.say() ); // output : łódź, łódź zamiast kraków, łódź Jak to obejść?

Dziedziczenie Można tak var personproto = { name : 'jan', address : { city : 'wrocław', say : function() { return this.address.city; var p1 = Object.create( personproto ); p1.address = { city : 'kraków' ; // za każdym razem twórz nowy podobiekt var p2 = Object.create( personproto ); p2.address = { city : 'łódź' ; console.log( p1.say() ); console.log( p2.say() ); Ale to nie wygląda dobrze, bo trzeba o tym pamiętać.

Dziedziczenie Rozwiązaniem jest taki prototyp, który klonuje się dedykowaną metodą tworzącą (factory function): var person = { create : function(name, city) { var _ = Object.create( this ); _.name = name; _.address = { city : city ; return _;, say : function() { return this.address.city; var p1 = person.create( 'jan', 'kraków' ); var p2 = person.create( 'tomasz', 'łódź' ); console.log( p1.say() ); console.log( p2.say() );

Dziedziczenie W ten sposób można zaimplementować dziedziczenie var person = { create : function(name, city) { var _ = Object.create( this ); _.name = name; _.address = { city : city ; return _;, say : function() { return this.address.city; var pupil = { create : function(name, city, school) { var _ = person.create.call( this, name, city ); _.school = school; return _;, say : function() { var _ = person.say.call( this ); return _ + ' ' + this.school; var p1 = person.create( 'jan', 'kraków' ); var p2 = pupil.create( 'tomasz', 'łódź', 'sp1' ); console.log( p1.say() ); console.log( p2.say() );

Dziedziczenie Wszystko pięknie tylko co się stanie jeśli pupil nie ma dostarczonej implementacji metody say, a zamiast tego oczekujemy że zawoła się metoda z prototypu (mówiąc żargonem obiektowym: z klasy bazowej)? Zakomentowanie metody say w pupil pokazuje że całość przestaje działać. pupil jako prototyp nie ma metody say! Można próbować to ratować: var person = { create : function(name, city) { var _ = Object.create( person ); _.name = name; _.address = { city : city ; return _;, say : function() { return this.address.city; ale wtedy przestaje działać przeciążanie metody say w pupil

Dziedziczenie Prawdziwym źródłem problemu jest to, że pupil nie powstał z person w taki sam sposób w jaki konstruujemy pozostałe obiekty przez sklonowanie. Zamiast tego zarówno pupil jak i person powstały w sposób literalny. Niestety, dostęp do prototypu obiektu nie jest jawny (jeśli się da to nie jest to standard). Nie można więc tego łatwo naprawić. Jedyny uniwersalny sposób to wprowadzić nieładną funkcję do klonowania prototypów i rozszerzania ich o dodatkowe właściwości: var extend = function(base, extension) { // klonuj prototyp var object = Object.create(base); // wkopiuj mu rozszerzone właściwości var hasownproperty = Object.hasOwnProperty; for (var property in extension) if (hasownproperty.call(extension, property) typeof object[property] === "undefined") object[property] = extension[property]; ; return object;

Dziedziczenie W takim środowisku rozszerzanie obiektów (dziedziczenie) działa tak jak powinno: var pupil = extend( person, { create : function(name, city, school) { var _ = person.create.call( this, name, city ); _.school = school; return _; //, //say : function() { // var _ = person.say.call( this ); // return _ + ' ' + this.school; // ); Metodę say można zakomentować (i wtedy działa implementacja z prototypu, z person) albo odkomentować (i wtedy działa implementacja z pupil). Wiele frameworków mimo to podąża tą ścieżką.

Dziedziczenie Ale dziedziczenie można osiągnąć inaczej, przez funkcje konstruktorowe (constructor function) function Foo() {... var f = new Foo(); to jest równoważne var f = new Object(); f.[[prototype]] = Foo.prototype; f.foo(); // binduje this gdzie Foo.prototype to prototyp który funkcja konstruktorowa przypina jako prototyp do nowo tworzonego obiektu. W przeciwieństwie do poprzedniego podejścia, prototyp ten jest jawny i można go modyfikować.

Dziedziczenie Mamy wtedy function Person(name, city) { this.name = name; this.address = { city : city ; this.say = function() { return this.name + ' ' + this.address.city; ; object Prototype1 p1 name = name say = function Person.prototype p2 name = name say = function var p1 = new Person('jan', 'wrocław'); console.log( p1.say() );

Dziedziczenie albo (uwaga!) function Person(name, city) { this.name = name; this.address = { city : city ; Person.prototype.say = function() { return this.name + ' ' + this.address.city; ; object Prototype2 Person.prototype say = function p1 p2 name = name name = name var p1 = new Person('jan', 'wrocław'); console.log( p1.say() );

Dziedziczenie Dziedziczenie jest łatwiejsze: function Person(name, city) { this.name = name; this.address = { city : city ; Person.prototype.say = function() { return this.name + ' ' + this.address.city; ; function Pupil(name, city, school) { Person.call( this, name, city ); this.school = school; var p1 = new Person('jan', 'wrocław'); console.log( p1.say() ); var p2 = new Pupil('tomasz', 'łódź', 'sp1'); console.log( p2.say() ); // problem! Oops, nie działa say w pupil!

Dziedziczenie Tym razem obrona jest łatwa: class Javascript Person.prototype Pupil.prototype p2 function Person(name, city) { this.name = name; this.address = { city : city ; Person.prototype.say = function() { return this.name + ' ' + this.address.city; ; function Pupil(name, city, school) { Person.call( this, name, city ); this.school = school; Pupil.prototype = new Person(); // lub Pupil.prototype = Person.prototype jeżeli metody są ustawiane tylko w prototypie var p1 = new Person('jan', 'wrocław'); console.log( p1.say() ); var p2 = new Pupil('tomasz', 'łódź', 'sp1'); console.log( p2.say() );

Dziedziczenie Wywołanie metody z klasy bazowej jest łatwe: function Person(name, city) { this.name = name; this.address = { city : city ; Person.prototype.say = function() { return this.name + ' ' + this.address.city; ; function Pupil(name, city, school) { Person.call( this, name, city ); this.school = school; Pupil.prototype = new Person(); Pupil.prototype.say = function() { var _ = Person.prototype.say.call( this ); return _ + ' ' + this.school; var p1 = new Person('jan', 'wrocław'); console.log( p1.say() ); var p2 = new Pupil('tomasz', 'łódź', 'sp1'); console.log( p2.say() );

Enkapsulacja Składowe prywatne w klasie przez domknięcie function Person(name) { var _private = 5; this.name = name; this.say = function() { return this.name + ' ' + _private; var p = new Person('jan'); console.log( p.say() ); console.log( p._private ); // niedostępne

Enkapsulacja Moduły zagnieżdżone obiekty function CreateNamespace( modulename ) { var parent = window; var seg = modulename.split('.'); for ( var part=0; part<seg.length; part++ ) { var segname = seg[part]; if ( typeof parent[segname] === 'undefined' ) parent[segname] = {; parent = parent[segname]; CreateNamespace( 'Vulcan.Architekt.CentralneSlowniki' );

Enkapsulacja I teraz Vulcan.Architekt.CentralneSlowniki = { // klasa publiczna Person : function(name) { this.name = name; this.say = function() { return name; var p = new Vulcan.Architekt.CentralneSlowniki.Person('jan'); console.log( p.say() );

Enkapsulacja Można nawet mieć w module prywatną klasę: Vulcan.Architekt.CentralneSlowniki = (function() { // klasa prywatna bo w domknięciu funkcji która się od razu wykonuje function Private() { this.helper = function(s) { return s + ' from helper!'; return { // klasa publiczna Person : function(name) { this.name = name; this.say = function() { var _pr = new Private(); return _pr.helper(this.name); ()); var p = new Vulcan.Architekt.CentralneSlowniki.Person('jan'); console.log( p.say() ); var q = new Vulcan.Architekt.CentralneSlowniki.Private(); // nie

ECMAScript 6 Wiele fajnych nowych rzeczy, m.in. lambda wyrażenia: var a = [ "Wlazł kotek na płotek", "I mruga" ]; // po staremu var a2 = a.map(function(s){ return s.length ); // po nowemu var a3 = a.map( s => s.length );

Podsumowanie Javascript to nowoczesny i wydajny język tworzenia aplikacji. Jedynym minusem jest uboga biblioteka standardowa, co oznacza, że trzeba wspierać się zewnętrznymi frameworkami.

Dziękuję za uwagę