ผลต่างระหว่างรุ่นของ "01204435/javascript"

จาก Theory Wiki
ไปยังการนำทาง ไปยังการค้นหา
 
(ไม่แสดง 12 รุ่นระหว่างกลางโดยผู้ใช้คนเดียวกัน)
แถว 118: แถว 118:
 
จากเอกสารข้างต้น ลองพยายามหาเหตุผลว่าทำไมผลที่ได้จึงเป็นตามที่เราทดลอง
 
จากเอกสารข้างต้น ลองพยายามหาเหตุผลว่าทำไมผลที่ได้จึงเป็นตามที่เราทดลอง
  
=== higher-order functions ===
+
=== higher-order functions 1 ===
  
 
ใน JavaScript นั้น function เป็นพลเมืองชั้นหนึ่ง นอกจากนี้ การที่เราสามารถประกาศฟังก์ชันโดยไม่ระบุชื่อได้ด้วย ทำให้เราเขียนฟังก์ชันที่คืนฟังกชั่นได้ง่าย เช่น
 
ใน JavaScript นั้น function เป็นพลเมืองชั้นหนึ่ง นอกจากนี้ การที่เราสามารถประกาศฟังก์ชันโดยไม่ระบุชื่อได้ด้วย ทำให้เราเขียนฟังก์ชันที่คืนฟังกชั่นได้ง่าย เช่น
แถว 148: แถว 148:
 
แล้ว tower(f)(1,9) มีค่า 4 และ tower(f)(1,200) มีค่า 8
 
แล้ว tower(f)(1,9) มีค่า 4 และ tower(f)(1,200) มีค่า 8
  
=== closures ===
+
=== higher-order functions 2 ===
 +
 
 +
พิจารณาโปรแกรมต่อไปนี้
 +
 
 +
var z = 1;
 +
if(a < b)
 +
  z++;
 +
else
 +
  z*=10;
 +
 
 +
ถ้าเราต้องการเขียนฟังก์ชันที่ทำงานเหมือน statement if นั้น ถ้าเราเขียนแบบตรง ๆ ดังนี้
 +
 
 +
function myif(condition,yesresult,noresult) {
 +
  if(condition)
 +
    return yesresult;
 +
  else
 +
    return noresult;
 +
 
 +
ในการเรียกใช้ ถ้าโค้ดเรามี side-effect เช่นตัวอย่างข้างต้น ผลที่ได้จะไม่เหมือนกับการสั่งคำสั่ง if ตรง ๆ  เช่นลองพิจารณาการเรียกด้านล่าง
 +
 
 +
myif(a<b,z++,z*=10);
 +
 
 +
อย่างไรก็ตามในภาษาที่ส่งฟังก์ชั่นได้ เราสามารถเขียนฟังก์ชันที่ทำงานในรูปแบบเดียวกับฟังก์ชัน if ข้างต้นได้  ลองเขียนฟังก์ชัน myif และแสดงวิธีการเรียกใช้ให้ผลลัพธ์เหมือนกับโปรแกรมตั้งต้นที่เขียนด้วย if statement
 +
 
 +
=== closures 0 ===
  
 
พิจารณาโปรแกรมด้านล่างนี้
 
พิจารณาโปรแกรมด้านล่างนี้
แถว 165: แถว 189:
 
  console.log(b());
 
  console.log(b());
 
  console.log(a());
 
  console.log(a());
 +
 +
อธิบายการทำงานของโปรแกรมดังกล่าว
  
 
== javascript: objects ==
 
== javascript: objects ==
แถว 170: แถว 196:
 
ในส่วนนี้ให้อ่าน [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects?redirectlocale=en-US&redirectslug=JavaScript%2FGuide%2FWorking_with_Objects Working with objects] และ [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Details_of_the_Object_Model?redirectlocale=en-US&redirectslug=JavaScript%2FGuide%2FDetails_of_the_Object_Model Details of the object model] ประกอบได้
 
ในส่วนนี้ให้อ่าน [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects?redirectlocale=en-US&redirectslug=JavaScript%2FGuide%2FWorking_with_Objects Working with objects] และ [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Details_of_the_Object_Model?redirectlocale=en-US&redirectslug=JavaScript%2FGuide%2FDetails_of_the_Object_Model Details of the object model] ประกอบได้
  
=== Objects และ properties ===
+
=== Objects, properties, และ methods ===
  
 
ใน JavaScript นั้น object ก็คือ associative array นี่เอง
 
ใน JavaScript นั้น object ก็คือ associative array นี่เอง
แถว 180: แถว 206:
 
  console.log(o1);
 
  console.log(o1);
 
  console.log(o2);
 
  console.log(o2);
 +
 +
method ก็คือฟังก์ชันที่เป็น property ของ object
 +
 +
พิจารณาตัวอย่างด้านล่าง
 +
 +
var g = function() { console.log(this.a); };
 +
o1.printA = g;
 +
o1.printA();
 +
 +
เราสามารถกำหนดค่า method ให้กับ object อื่นได้ด้วย เช่น
 +
 +
o2.a = 100;
 +
o2.pp = o1.printA;
 +
o2.pp();
 +
 +
สังเกตว่าฟังก์ชัน g ถูกเรียกเมื่อเราเรียก o1.printA และ o2.pp  ในการเรียกดังกล่าว this หมายถึงอะไร?
 +
 +
ให้เรียก
 +
 +
g();
 +
 +
ผลลัพธ์ที่ได้เป็นอย่างไร?  ถ้าเราต้องการให้ผลลัพธ์เท่ากับ 1000000 จะต้องทำอย่างไร?  ในกรณีนี้ this ในฟังก์ชัน g หมายถึงอะไร?
 +
 +
=== prototypes 1 ===
 +
 +
ทดลองโปรแกรมต่อไปนี้  โดยพิมพ์ทีละบรรทัดและสังเกต
 +
 +
x = {a:10, b:10}
 +
x.f();
 +
y = {f:function() { return 10; }}
 +
x.__proto__ = y;
 +
x.f();
 +
x.g();
 +
z = {g:function() { return this.a + 10; }};
 +
y.__proto__ = z;
 +
x.g();
 +
 +
อธิบายบทบาทของ property __proto__
 +
 +
=== prototypes 2 ===
 +
 +
เรามีอีกวิธีในการสร้าง object โดยใช้ operator new  พิจารณาฟังก์ชันต่อไปนี้
 +
 +
function Car(speed, color) {
 +
  this.speed = speed;
 +
  this.color = color;
 +
  this.run = function() { console.log('Running at '+this.speed); };
 +
}
 +
 +
ในการสร้าง object ด้วยฟังก์ชันดังกล่าว เราจะเรียก
 +
 +
var c1 = new Car(120,'white');
 +
var c2 = new Car(140,'green');
 +
 +
ฟังก์ชัน Car จะเรียกว่า constructor และเรานิยมขึ้นต้นชื่อฟังก์ชันด้วยตัวพิมพ์ใหญ่
 +
 +
ลองเรียก c1 หรือ c2 ใน console  แล้วเรียก
 +
 +
c1.run();
 +
 +
พิจารณาฟังก์ชันต่อไปนี้
 +
 +
function SuperCar(color) {
 +
  this.color = color;
 +
  this.speed = 180;
 +
}
 +
 +
ทดลองสัง (ทีละบรรทัด ใน console)
 +
 +
var s1 = new SuperCar('black');
 +
s1.speed
 +
s1.color
 +
s1.run();
 +
 +
ทำไมเกิด error
 +
 +
สั่งต่อ
 +
 +
SuperCar.prototype = new Car;
 +
var s2 = new SuperCar('blue');
 +
s2.speed;
 +
s2.run();
 +
 +
คาดว่าอะไรจะอยู่ใน s2.__proto__ ?
 +
 +
ทดลองต่อ
 +
 +
function TurtleCar(color) {
 +
  this.color = color;
 +
}
 +
TurtleCar.prototype = new Car(1,'Invisible');
 +
 +
var t = new TurtleCar('Brown');
 +
 +
ถ้าสั่งคำสั่งถัดไป ผลลัพธ์จะเป็นอย่างไร?  เพราะอะไร (ให้นึกคำตอบก่อนจะทดลอง)
 +
 +
t.run();
 +
 +
ถ้าสั่งคำสั่งถัดไป ผลลัพธ์จะเป็นอย่างไร?  เพราะอะไร (ให้นึกคำตอบก่อนจะทดลอง)
 +
 +
t.speed = 0.1;
 +
t.run();
  
 
== node.js: event-driven i/o ==
 
== node.js: event-driven i/o ==
  
 
: ไว้เป็นครั้งถัด ๆ ไป
 
: ไว้เป็นครั้งถัด ๆ ไป

รุ่นแก้ไขปัจจุบันเมื่อ 10:10, 13 มิถุนายน 2556

หน้านี้เป็นการทดลอง javascript และ node.js ซึ่งเป็นส่วนหนึ่งของวิชา 01204435

เอกสารอ้างอิงประกอบการทำแลบสามารถเอกสารจาก หน้า JavaScript ของ Mozilla Developer Network ได้ โดยอาจจะดูในส่วนของ JavaScript Guide

javascript: การทดลองเกี่ยวกับ scope

scope ใน block และใน function

พิจารณาโปรแกรม 3 โปรแกรมต่อไปนี้

a = 10;
{ 
  var a = 20;    // ***
  console.log(a);
}
console.log(a);
a = 10;
function f() { 
  var a = 20;    // ***
  console.log(a);
};
f();
console.log(a);
a = 10;
function f() { 
  a = 20;          // ***
  console.log(a);
};
f();
console.log(a);

อธิบายความแตกต่าง อธิบายว่าตัวแปร a ในบรรทัด *** ของแต่ละโปรแกรมหมายถึงตัวแปรตัวใด และเพราะเหตุใด

ทดลองขอบเขตเพิ่มเติม 1

พิจารณาโปรแกรมต่อไปนี้ ผลลัพธ์ของโปรแกรมจะเป็นเช่นใด? ทำไม?

var x = 20;
for(var x = 0; x < 5; x++) {
  console.log(x);
}
console.log(x);

ทดลองแก้โปรแกรม (พยายามแก้ให้น้อยที่สุด) เพื่อทำให้ตัวแปร x ในลูป for กับ x ภายนอกเป็นคนละตัวแปรกัน (นั่นคือบรรทัดสุดท้ายของผลลัพธ์ควรจะมีค่า 20)

ตำแหน่งในการประกาศ

ในการทดลองต่อไป ให้สร้างไฟล์นามสกุล js และเรียกให้ทำงานจาก command line (ไม่ใช่ทยอยป้อนใน javascript console)

พิจารณาโปรแกรมสามโปรแกรมต่อไปนี้

var a = x;
console.log(a);
var x = 10;
console.log(x);
var a = x;
console.log(a);
var x = 10;
console.log(x);
var a = x;
console.log(a);
var x = 20;
var a = x;
console.log(a);
var a = x;
console.log(a);

จากผลการทดลอง ให้อธิบายขอบเขตของตัวแปร x ในสองตัวอย่างแรก

javascript: functions

การประกาศ (และปัญหาที่ค้างคาใจ)

ใน javascript มีวิธีการประกาศ function ได้หลายแบบ สองรูปแบบหลัก ๆ ที่เห็นมีดังตัวอย่างด้านล่าง แบบแรกคือประกาศฟังก์ชัน a เลย

function a() {
  return 10;
}

และอีกแบบคือการประกาศฟังก์ชัน โดยไม่ระบุชื่อ จากนั้นค่อยนำไปกำหนดค่าให้กับตัวแปรที่แทนฟังก์ชันนั้น

var b = function() { 
  return 20; 
};

ในการใช้งานทั่วไป เราจะไม่ค่อยพบความแตกต่างมาก แต่ให้พิจารณาตัวอย่างอันน่าแปลกด้านล่างนี้

var f = function() {
  var a = g();
  function g() { return 10; }
  function g() { return 20; }
  return a;
};
console.log(f());
var f = function() {
  function g() { return 10; }
  var a = g();
  function g() { return 20; }
  return a;
};
console.log(f());
var f = function() {
  var g = function(){ return 10; };
  var a = g();
  function g() { return 20; }
  return a;
};
console.log(f());

ในส่วนนี้ให้อ่านเอกสาร Functions and function scope ประกอบ

จากเอกสารข้างต้น ลองพยายามหาเหตุผลว่าทำไมผลที่ได้จึงเป็นตามที่เราทดลอง

higher-order functions 1

ใน JavaScript นั้น function เป็นพลเมืองชั้นหนึ่ง นอกจากนี้ การที่เราสามารถประกาศฟังก์ชันโดยไม่ระบุชื่อได้ด้วย ทำให้เราเขียนฟังก์ชันที่คืนฟังกชั่นได้ง่าย เช่น

function double(f) {
  return function(x) { return 2*f(x); }; 
}

พิจารณาการเรียกใช้เช่น

g = double(function(y) { return y*10; });
console.log(g(10));
x = double(function(a) { return a/5; })(30);
console.log(x);

ให้เขียนฟังก์ชัน tower ที่รับฟังก์ชัน f จากนั้นคือฟังก์ชันที่รับ x และ y และคืนจำนวนครั้งที่จะต้องเรียกฟังก์ชัน f ซ้อนกันกี่ครั้งโดยเริ่มจาก x จนผลลัพธ์มีค่ามากกว่าหรือเท่ากับ y

ยกตัวอย่างเช่น ถ้า f เป็นฟังก์ชัน:

var f = function(x) { return x+2; }

แล้ว tower(f)(1,10) จะมีค่า 5, tower(f)(1,9) จะมีค่า 4 (เพราะว่า ((((1+2)+2)+2)+2) เท่ากับ 9)

หรือถ้า f เป็นฟังก์ชัน

var f = function(x) { return 2*x; }

แล้ว tower(f)(1,9) มีค่า 4 และ tower(f)(1,200) มีค่า 8

higher-order functions 2

พิจารณาโปรแกรมต่อไปนี้

var z = 1;
if(a < b)
  z++;
else
  z*=10;

ถ้าเราต้องการเขียนฟังก์ชันที่ทำงานเหมือน statement if นั้น ถ้าเราเขียนแบบตรง ๆ ดังนี้

function myif(condition,yesresult,noresult) {
  if(condition)
    return yesresult;
  else
    return noresult;

ในการเรียกใช้ ถ้าโค้ดเรามี side-effect เช่นตัวอย่างข้างต้น ผลที่ได้จะไม่เหมือนกับการสั่งคำสั่ง if ตรง ๆ เช่นลองพิจารณาการเรียกด้านล่าง

myif(a<b,z++,z*=10);

อย่างไรก็ตามในภาษาที่ส่งฟังก์ชั่นได้ เราสามารถเขียนฟังก์ชันที่ทำงานในรูปแบบเดียวกับฟังก์ชัน if ข้างต้นได้ ลองเขียนฟังก์ชัน myif และแสดงวิธีการเรียกใช้ให้ผลลัพธ์เหมือนกับโปรแกรมตั้งต้นที่เขียนด้วย if statement

closures 0

พิจารณาโปรแกรมด้านล่างนี้

function counter() {
  var c = 0;
  return function() {
    c++;
    return c;
  };
}
a = counter();
b = counter();
console.log(a());
console.log(a());
console.log(b());
console.log(a());

อธิบายการทำงานของโปรแกรมดังกล่าว

javascript: objects

ในส่วนนี้ให้อ่าน Working with objects และ Details of the object model ประกอบได้

Objects, properties, และ methods

ใน JavaScript นั้น object ก็คือ associative array นี่เอง

o1 = {a:10, b:20};
o2 = new Object();
o2['a'] = 20;
o2.b = 20;
console.log(o1);
console.log(o2);

method ก็คือฟังก์ชันที่เป็น property ของ object

พิจารณาตัวอย่างด้านล่าง

var g = function() { console.log(this.a); };
o1.printA = g;
o1.printA();

เราสามารถกำหนดค่า method ให้กับ object อื่นได้ด้วย เช่น

o2.a = 100;
o2.pp = o1.printA;
o2.pp();

สังเกตว่าฟังก์ชัน g ถูกเรียกเมื่อเราเรียก o1.printA และ o2.pp ในการเรียกดังกล่าว this หมายถึงอะไร?

ให้เรียก

g();

ผลลัพธ์ที่ได้เป็นอย่างไร? ถ้าเราต้องการให้ผลลัพธ์เท่ากับ 1000000 จะต้องทำอย่างไร? ในกรณีนี้ this ในฟังก์ชัน g หมายถึงอะไร?

prototypes 1

ทดลองโปรแกรมต่อไปนี้ โดยพิมพ์ทีละบรรทัดและสังเกต

x = {a:10, b:10}
x.f();
y = {f:function() { return 10; }}
x.__proto__ = y;
x.f();
x.g();
z = {g:function() { return this.a + 10; }};
y.__proto__ = z;
x.g();

อธิบายบทบาทของ property __proto__

prototypes 2

เรามีอีกวิธีในการสร้าง object โดยใช้ operator new พิจารณาฟังก์ชันต่อไปนี้

function Car(speed, color) {
  this.speed = speed;
  this.color = color;
  this.run = function() { console.log('Running at '+this.speed); };
}

ในการสร้าง object ด้วยฟังก์ชันดังกล่าว เราจะเรียก

var c1 = new Car(120,'white');
var c2 = new Car(140,'green');

ฟังก์ชัน Car จะเรียกว่า constructor และเรานิยมขึ้นต้นชื่อฟังก์ชันด้วยตัวพิมพ์ใหญ่

ลองเรียก c1 หรือ c2 ใน console แล้วเรียก

c1.run();

พิจารณาฟังก์ชันต่อไปนี้

function SuperCar(color) {
  this.color = color;
  this.speed = 180;
}

ทดลองสัง (ทีละบรรทัด ใน console)

var s1 = new SuperCar('black');
s1.speed
s1.color
s1.run();

ทำไมเกิด error

สั่งต่อ

SuperCar.prototype = new Car;
var s2 = new SuperCar('blue');
s2.speed;
s2.run();

คาดว่าอะไรจะอยู่ใน s2.__proto__ ?

ทดลองต่อ

function TurtleCar(color) {
  this.color = color;
}
TurtleCar.prototype = new Car(1,'Invisible');
var t = new TurtleCar('Brown');

ถ้าสั่งคำสั่งถัดไป ผลลัพธ์จะเป็นอย่างไร? เพราะอะไร (ให้นึกคำตอบก่อนจะทดลอง)

t.run();

ถ้าสั่งคำสั่งถัดไป ผลลัพธ์จะเป็นอย่างไร? เพราะอะไร (ให้นึกคำตอบก่อนจะทดลอง)

t.speed = 0.1;
t.run();

node.js: event-driven i/o

ไว้เป็นครั้งถัด ๆ ไป