Uwaga, ponieważ zestaw 2 ma termin 25-10-2016 to zestaw 1 ma sugerowany termin 18-10 (i to jest zmiana w stosunku do pierwotnej propozycji), jednak z uwagi na to że prawo nie może działać wstecz, zestaw 1 będzie również przyjmowany w terminie 25-10-2016 razem z zestawem 2. Proszę dobrze zaplanować pracę i skorzystać z jednej lub drugiej możliwości.
var foo = { _i : 0, get bar() { return foo._i; }, set bar(i) { foo._i = i; } } console.log( foo.bar ); foo.bar = 5; console.log( foo.bar );
var foo = { _i : 0, get bar() { return foo._i; }, set bar(i) { foo._i = i; } } Object.defineProperty( foo, 'qux', { get : function() { return 17; } }); console.log( foo.qux );
function createGenerator() { var _state = 0; return { next : function() { return { value : _state, done : _state++ >= 10 } } } } // enumerowanie przez while var it = createGenerator(); var _result; while ( _result = it.next(), !_result.done ) console.log( _result.value ); // enumerowanie przez for var it = createGenerator(); for ( var _result; _result = it.next(), !_result.done; ) console.log( _result.value );
var foo = { [Symbol.iterator] : createGenerator }; for ( var f of foo ) console.log(f);
function* createGenerator() { for ( var _state = 0; _state<10; _state++ ) yield _state; }
var q = 1; var p = "qwe"; var s = `ala ${q} ma ${p} kota ${2*q+1}`;
function create(n,s) { return { name : n, surname : s, say : function() { return `${this.name} ${this.surname}`; } } } var p = create('jan', 'kowalski'); console.log( p.say() );
var p = { name : 'jan', say : function() { return this.name; } }; var q = Object.create( p ); q.name = 'tomasz'; console.log( q.say() );
var person = { init : function(name, surname) { this.name = name; this.surname = surname; }, say : function() { return `${this.name} ${this.surname}`; } } var p = Object.create( person ); p.init( 'jan', 'kowalski' ); console.log( p.say() );
var worker = Object.create( person ); worker.init = function( name, surname, age ) { // "wywołanie konstruktora klasy bazowej" person.init.call( this, name, surname ); this.age = age; } worker.say = function() { // "wywołanie metody z klasy bazowej" var _ = person.say.call( this ); return `${_} ${this.age}`; } var w = Object.create( worker ); w.init('tomasz','malinowski',48); console.log( w.say() );
var Person = function(name, surname) { this.name = name; this.surname = surname; } Person.prototype.say = function() { return `${this.name} ${this.surname}`; } var p = new Person('jan', 'kowalski'); console.log( p.say() );
var Worker = function(name, surname, age) { // wywołanie bazowej funkcji konstruktorowej Person.call( this, name, surname ); this.age = age; } // powiązanie łańcucha prototypów Worker.prototype = Object.create( Person.prototype ); Worker.prototype.say = function() { // "wywołanie metody z klasy bazowej" var _ = Person.prototype.say.call( this ); return `${_} ${this.age}`; } var w = new Worker('jan', 'kowalski', 48); console.log( w.say() );
// alternatywa dla new f() // wyrażona przy pomocy Object.create function New( f ) { var _ = Object.create( f.prototype ); // arguments nie jest tablicą więc "pożyczamy" metodę slice od tablicy var o = f.apply( _, [].slice.call( arguments, 1 ) ); if ( o ) return o; else return _; } var p = New( Person, 'jan', 'kowalski' ); console.log( p.say() );
// alternatywa dla Object.create( p ) // wyrażona przy pomocy "new" function ObjectCreate( p ) { var f = function() { }; f.prototype = p; return new f(); } var p = ObjectCreate( person ); p.init('jan', 'kowalski'); console.log( p.say() );
class Person { constructor(name, surname) { this.name = name; this.surname = surname; } say() { return `${this.name} ${this.surname}`; } } class Worker extends Person { constructor(name, surname, age ) { super(name, surname); this.age = age; } say() { // "wywołanie metody z klasy bazowej" var _ = super.say(); return `${_} ${this.age}`; } } var w = new Worker('tomasz', 'malinowski', 48); console.log( w.say() );
C++/Java/C# | Javascript |
---|---|
Klasy | Funkcje konstruktorowe |
Przestrzenie nazw | Obiekty z polami które są referencjami do innych obiektów |
Składowe prywatne | Umieszczanie elementów w domknięciach funkcji |
Modularność include/import/using | Modularność require |
npm install typings --global typings install dt~node --global --save
var fs = require('fs'); function read1Sync() { var content = fs.readFileSync( './test.txt', 'utf-8' ); console.log( content ); } read1Sync();
var fs = require('fs'); function read1Async() { fs.readFile( './test.txt', 'utf-8', function( err, data ) { console.log( data ); } ); } read1Async();
var fs = require('fs'); function read1Stream() { var buf =''; var s = fs.createReadStream( './test.txt', { encoding :'utf-8' } ); s.on( 'data', function(data) { buf += data.toString(); }); s.on('end', function() { console.log( buf ); }); } read1Stream();
var fs = require('fs'); function read1Stream() { var buf =''; var s = fs.createReadStream( './test.txt', { encoding :'utf-8' } ); s.pipe( process.stdout ); } read1Stream();
function fspromise(path) { return new Promise( function( res, rej ) { fs.readFile(path, function(err, data) { if ( err ) rej(err ); res( data.toString() ); }); } ); } var f1 = fspromise('./alamakota.txt'); var f2 = fspromise('./alamakota2.txt'); var f3 = Promise.all([f1,f2]) .then(function(results) { console.log( results ) } );
function promiseall(p1, p2) { return p1.then(function(p1r) { return p2.then(function(p2r) { return new Promise( function(res, rej) { res([p1r,p2r]); }); }); }); }
// poniższy kod dziś jeszcze nie wykona się poprawnie // funkcja oznakowana jako async // zwraca Promise async function promisedGet(url) { return new Promise(function (resolve, reject) { var client = http.get(url, function (res) { var buffer = ''; res .on('data', function (data) { buffer += data.toString(); }) .on('end', function () { resolve(buffer); }); }); }); } // funkcja oznakowana jako async, // wolno w niej wywoływać inną funkcję zwracającą Promise przez await async function foo() { // await ___ ... var result = await promisedGet('http://www.google.pl'); console.log( result ); // jest równoważne dzisiejszemu // // promistedGet('http://www.google.pl') // .then( function(result) { console.log( result );} ); // // a umieszczeniem całego kodu napisanego "pod" await w kontynuacji // doczepionej do Promise przez then zajmuje się już sam kompilator } foo();
npm init -y npm install express --save npm install ejs --save
var http = require('http'); var express = require('express'); var app = express(); app.set('view engine', 'ejs'); app.set('views', './views'); // tu dodajemy middleware ... // tu uruchamiamy serwer var server = http.createServer(app).listen(3000); console.log( 'serwer started' );
<html> <body> <% var foo = 'bar' %> <% for ( var i=0; i<5; i++ ) { %> <input value='<%= i %>' /> <% } %> </body> </html>
app.get('/', (req, res) => { var model = { user : 'jan' }; res.render('user', model); }); // user.ejs <html> <body> Użytkownik : <%= user %> </body> </html>
app.get('/przelewy', (req, res) => { var przelewy = [ { kwota : 123, data : '2016-01-03', id = 1 }, { kwota : 124, data : '2016-01-02', id = 2 }, { kwota : 125, data : '2016-01-01', id = 3 }, ]; res.render('przelewy', { przelewy : przelewy } ); }); // przelewy.ejs <html> <body> <table> <tr> <th>Data</th> <th>Kwota</th> <th></th> </tr> <% przelewy.forEach( przelew => { %> <tr> <td><%= przelew.data %></td> <td><%= przelew.kwota %></td> <td><a href='/przelew/<%= przelew.id %>'>Więcej</a></td> </tr> <% }) %> </table> </body> </html>
app.use((req,res,next) => { res.render('404.ejs', { url : req.url }); }); // 404.ejs <html> <body> Strona <%= url %> nie została znaleziona. </body> </html>
res.redirect('innastrona');
żądanie do http://localhost:3000/strona?p1=v1&p2=v2 app.get('/strona', (req, res) => { var p1 = req.query.p1; var p2 = req.query.p2; });Uwaga na możliwy atak Querystring Tamepring
app.get('/przelew/:id', (req, res) => { var id = req.params.id; res.render('przelew', { id : id } ); });
app.get('/plik', (req, res) => { // proszę zaremować i odremować tę linijkę i porównać wynik res.setHeader('Content-disposition', 'attachment; filename=plik.txt'); res.write('123'); res.end(); });
npm install body-parser --save var bodyParser = require('body-parser'); app.use( bodyParser.urlencoded({extended:true}) ) ; app.get('/login', (req, res) => { res.render('login'); }); app.post('/login', (req, res) => { var username = req.body.username; var pwd = req.body.pwd; }); // login.ejs <html> <body> <form method="POST"> <div> Login: <input type='text' name='username' /> </div> <div> Password: <input type='password' name='pwd' /> </div> <div> <button>Login</button> </div> </form> </body> </html>
// instalacja middleware app.use( express.static('./static'));Od tego momentu wszystkie pliki w folderze '/static' są serwowane na żądania adresowane przez '/', np. do pliku '/static/app.css' odwołamy się przez
<link rel='stylesheet' href='/app.css'>
// instalacja middleware npm install cookie-parser --save // w aplikacji var cookieParser = require('cookie-parser'); app.use( cookieParser() ); // wydanie ciastka res.cookie('foo', 'bar'); // sprawdzenie ciastka req.cookies.foo;
// wydanie ciastka res.cookie('foo', 'bar', { maxAge : 60 * 1000 } ); // 60 sekund // usunięcie ciastka z przeglądarki res.cookie('foo', '', { maxAge : -1 } );
// w aplikacji var cookieParser = require('cookie-parser'); app.use( cookieParser('9877dg9fb8sd79b87sdt9b87ds98b') ); // secret // wydanie ciastka res.cookie('foo', 'bar', { signed : true }); // sprawdzenie ciastka req.signedCookies.foo;
// instalacja middleware npm install express-session --save // dodawanie danych do sesji req.session.foo = 'bar'; // odczyt danych z sesji var foo = req.session.foo;
app.get('/', (req, res) => { if ( !req.cookie.user ) res.redirect('/login'); else ... });
// middleware logowania function authorize(req, res, next) { if ( req.cookies.user ) { // użytkownik jest zalogowany // "przepisanie" danych użytkownika żeby dostęp był jednolity req.user = req.cookies.user; next(); } else { // użytkownik niezalogowany // przekierowanie z zapamiętaniem strony która spowodowała przekierowanie res.redirect( '/login?returnUrl='+req.url); } } // wymuszenie logowania na konkretnym zasobie app.get('/', authorize, (req, res) => { // to wykona się tylko jeśli middleware authorize przejdzie przez ścieżkę zalogowanego użytkownika // w przeciwnym przypadku żądanie zostanie tam przekierowane na /login?returnUrl=/ }); // logowanie app.get('/login', (req, res) => { // wyrenderuj stronę logowania res.render('login'); }); app.post('/login', (req, res) => { // użytkownik kliknął przycisk "zaloguj" na stronie logowania (POST) var username = req.body.txtUser; // na stronie jest <input type='text' name='txtUser' ... var pwd = req.body.txtPwd; // na stronie jest <input type='password' name='txtPwd' ... if ( username == pwd ) { // w rzeczywistości - sprawdzenie w bazie danych res.cookie('user', username); // wydanie ciastka, od tego momentu użytkownik jest zalogowany var returnUrl = req.query.returnUrl; res.redirect( returnUrl ); // powrót do miejsca z którego nastąpiło przekierowanie tutaj } else { // nie udało się zalogować, trzeba znów pokazać stronę logowania z komunikatem res.render('login', { message : 'Zła nazwa logowania lub hasło' }); } });
npm installżeby dociągnąć wszystkie pakiety wymienione w package.json.
// select.ejs <select name='<%= name %>'> <% options.forEach( option => { %> <option value='<%= option.value %>'><%= option.text %></option> <% }) %> </select> // wywołanie szablonu z innego szablonu <% var name='combo1' %> <% var options= [ { value : 1, text : 'element 1' }, { value : 2, text : 'element 2' }, { value : 3, text : 'element 3' } ] %> <% include select %>
git init git add . git commit -m “initial commit” heroku login heroku create git push heroku master
CREATE TABLE [dbo].[Child]( [ID] [int] IDENTITY(1,1) NOT NULL, [ChildName] [nvarchar](150) NOT NULL, [ID_PARENT] [int] NOT NULL, CONSTRAINT [PK_Child] PRIMARY KEY CLUSTERED ( [ID] ASC ) ) ON [PRIMARY] GO CREATE TABLE [dbo].[Parent]( [ID] [int] IDENTITY(1,1) NOT NULL, [ParentName] [nvarchar](150) NOT NULL, CONSTRAINT [PK_Parent] PRIMARY KEY CLUSTERED ( [ID] ASC ) ) ON [PRIMARY] ALTER TABLE [dbo].[Child] WITH CHECK ADD CONSTRAINT [FK_Child_Parent] FOREIGN KEY([ID_PARENT]) REFERENCES [dbo].[Parent] ([ID])
var conn = new sql.Connection('server=localhost,1433;database=database2;user id=foo;password=foo'); conn.connect() .then( () => { var request = new sql.Request(conn); request.query('select * from Parent') .then( recordset => { res.contentType('text/html'); recordset.forEach( r => { res.write( `${r.ID} ${r.ParentName}<br/>`); }); conn.close(); res.end(); }) .catch( err => { console.log( err ); }); }) .catch( err => { console.log(err); });
try { var conn = new sql.Connection('server=localhost,1433;database=database2;user id=foo;password=foo'); await conn.connect(); var request = new sql.Request(conn); var recordset = await request.query('select * from Parent') res.contentType('text/html'); recordset.forEach( r => { res.write( `${r.ID} ${r.ParentName}<br/>`); }); conn.close(); res.end(); } catch ( err ) { console.log( err ); }Proszę zwrócić uwagę na to że te kilka tygodni ciężko pracowaliśmy na to żeby móc w końcu pisać taki "liniowy", normalny kod, bez asynchronicznych callbacków i bez zamykania kodu kontynuacji w Promise().then(...) - wszędzie tam gdzie pojawia się
promise().then( result => { });można aktualnie napisać
var result = await promise();
// /repo/parentRepo module.exports.insert = async function(conn, parent) { try { var req = new sql.Request(conn); req.input("ParentName", parent.parentName); var recordset = await req.query( "insert into Parent (ParentName) values (@ParentName) select scope_identity() as id"); return recordset[0].id; } catch ( err ) { // cokolwiek, włącznie z throw err; } }
var assert = require('assert'); describe('Top level', function() { describe('Sub level', function() { it( 'Unit test function definition', function() { assert.equal( -1, [1,2,3].indexOf(4) ); }); }); });
var webdriverio = require('webdriverio'); var options = { desiredCapabilities: { browserName: 'chrome' } }; var client = webdriverio.remote(options); client .init() .url('https://duckduckgo.com/') .setValue('#search_form_input_homepage', 'WebdriverIO') .click('#search_button_homepage') .getTitle().then(function(title) { console.log('Title is: ' + title); // outputs: "Title is: WebdriverIO (Software) at DuckDuckGo" }) .end();