ผลต่างระหว่างรุ่นของ "01204435/javascript"
Jittat (คุย | มีส่วนร่วม) |
Jittat (คุย | มีส่วนร่วม) |
||
| (ไม่แสดง 16 รุ่นระหว่างกลางโดยผู้ใช้คนเดียวกัน) | |||
| แถว 118: | แถว 118: | ||
จากเอกสารข้างต้น ลองพยายามหาเหตุผลว่าทำไมผลที่ได้จึงเป็นตามที่เราทดลอง | จากเอกสารข้างต้น ลองพยายามหาเหตุผลว่าทำไมผลที่ได้จึงเป็นตามที่เราทดลอง | ||
| − | === higher-order functions === | + | === higher-order functions 1 === |
ใน JavaScript นั้น function เป็นพลเมืองชั้นหนึ่ง นอกจากนี้ การที่เราสามารถประกาศฟังก์ชันโดยไม่ระบุชื่อได้ด้วย ทำให้เราเขียนฟังก์ชันที่คืนฟังกชั่นได้ง่าย เช่น | ใน JavaScript นั้น function เป็นพลเมืองชั้นหนึ่ง นอกจากนี้ การที่เราสามารถประกาศฟังก์ชันโดยไม่ระบุชื่อได้ด้วย ทำให้เราเขียนฟังก์ชันที่คืนฟังกชั่นได้ง่าย เช่น | ||
| แถว 133: | แถว 133: | ||
x = double(function(a) { return a/5; })(30); | x = double(function(a) { return a/5; })(30); | ||
console.log(x); | 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 == | == javascript: objects == | ||
| แถว 138: | แถว 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 และ | + | === Objects, properties, และ methods === |
ใน JavaScript นั้น object ก็คือ associative array นี่เอง | ใน JavaScript นั้น object ก็คือ associative array นี่เอง | ||
| แถว 148: | แถว 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
- ไว้เป็นครั้งถัด ๆ ไป