Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions 1-js/09-classes/01-class/1-rewrite-to-class/task.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ importance: 5

---

# Rewrite to class
# เขียนใหม่ด้วยคลาส

The `Clock` class (see the sandbox) is written in functional style. Rewrite it in the "class" syntax.
คลาส `Clock` (ดูใน sandbox) เขียนไว้แบบ functional style ให้เขียนใหม่โดยใช้ไวยากรณ์ "class"

P.S. The clock ticks in the console, open it to see.
P.S. นาฬิกาจะเดินอยู่ใน console ลองเปิดดู
215 changes: 107 additions & 108 deletions 1-js/09-classes/01-class/article.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
That's because the child constructor must call `super()`.
เป็นเพราะคอนสตรักเตอร์ของคลาสลูกต้องเรียก `super()` ก่อน

Here's the corrected code:
นี่คือโค้ดที่แก้แล้ว:

```js run
class Animal {
Expand All @@ -12,7 +12,7 @@ class Animal {
}

class Rabbit extends Animal {
constructor(name) {
constructor(name) {
*!*
super(name);
*/!*
Expand All @@ -21,7 +21,7 @@ class Rabbit extends Animal {
}

*!*
let rabbit = new Rabbit("White Rabbit"); // ok now
let rabbit = new Rabbit("White Rabbit"); // ตอนนี้ใช้ได้แล้ว
*/!*
alert(rabbit.name); // White Rabbit
```
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ importance: 5

---

# Error creating an instance
# Error ตอนสร้างอินสแตนซ์

Here's the code with `Rabbit` extending `Animal`.
โค้ดด้านล่างมี `Rabbit` สืบทอดจาก `Animal`

Unfortunately, `Rabbit` objects can't be created. What's wrong? Fix it.
แต่น่าเสียดาย ออบเจ็กต์ `Rabbit` สร้างไม่ได้ อะไรผิดพลาด? ลองแก้ดู
```js run
class Animal {

Expand All @@ -17,7 +17,7 @@ class Animal {
}

class Rabbit extends Animal {
constructor(name) {
constructor(name) {
this.name = name;
this.created = Date.now();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
clock.start();


/* Your class should work like this: */
/* คลาสของคุณควรทำงานได้แบบนี้: */

/*

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ importance: 5

---

# Extended clock
# นาฬิกาแบบขยาย (Extended clock)

We've got a `Clock` class. As of now, it prints the time every second.
เรามีคลาส `Clock` อยู่แล้ว ซึ่งแสดงเวลาทุกวินาที


[js src="source.view/clock.js"]

Create a new class `ExtendedClock` that inherits from `Clock` and adds the parameter `precision` -- the number of `ms` between "ticks". Should be `1000` (1 second) by default.
ให้สร้างคลาส `ExtendedClock` ที่สืบทอดจาก `Clock` แล้วเพิ่มพารามิเตอร์ `precision` ซึ่งเป็นจำนวนมิลลิวินาทีระหว่าง "ติ๊ก" แต่ละครั้ง ค่าเริ่มต้นคือ `1000` (1 วินาที)

- Your code should be in the file `extended-clock.js`
- Don't modify the original `clock.js`. Extend it.
- เขียนโค้ดในไฟล์ `extended-clock.js`
- อย่าแก้ไขไฟล์ `clock.js` เดิม ให้ขยายจากมันแทน
350 changes: 175 additions & 175 deletions 1-js/09-classes/02-class-inheritance/article.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
First, let's see why the latter code doesn't work.
มาดูกันก่อนว่าทำไมโค้ดด้านบนถึงใช้ไม่ได้

The reason becomes obvious if we try to run it. An inheriting class constructor must call `super()`. Otherwise `"this"` won't be "defined".
สาเหตุจะเห็นชัดเมื่อลองรันดู คลาสลูกที่สืบทอดมาจำเป็นต้องเรียก `super()` ในคอนสตรักเตอร์ ไม่อย่างนั้น `"this"` จะยังไม่ถูกกำหนดค่า

So here's the fix:
แก้ไขได้ดังนี้:

```js run
class Rabbit extends Object {
constructor(name) {
*!*
super(); // need to call the parent constructor when inheriting
super(); // ต้องเรียกคอนสตรักเตอร์ของคลาสแม่เมื่อมีการสืบทอด
*/!*
this.name = name;
}
Expand All @@ -19,16 +19,16 @@ let rabbit = new Rabbit("Rab");
alert( rabbit.hasOwnProperty('name') ); // true
```

But that's not all yet.
แต่ยังไม่จบแค่นี้

Even after the fix, there's still an important difference between `"class Rabbit extends Object"` and `class Rabbit`.
แม้แก้ไขแล้ว ยังมีความแตกต่างสำคัญระหว่าง `"class Rabbit extends Object"` กับ `class Rabbit` ธรรมดา

As we know, the "extends" syntax sets up two prototypes:
อย่างที่เราทราบ ไวยากรณ์ "extends" สร้างการเชื่อมโยงโปรโตไทป์ 2 จุด:

1. Between `"prototype"` of the constructor functions (for methods).
2. Between the constructor functions themselves (for static methods).
1. ระหว่าง `"prototype"` ของคอนสตรักเตอร์ (สำหรับเมธอดปกติ)
2. ระหว่างตัวคอนสตรักเตอร์เอง (สำหรับเมธอด static)

In the case of `class Rabbit extends Object` it means:
ในกรณีของ `class Rabbit extends Object` จะเป็นแบบนี้:

```js run
class Rabbit extends Object {}
Expand All @@ -37,45 +37,45 @@ alert( Rabbit.prototype.__proto__ === Object.prototype ); // (1) true
alert( Rabbit.__proto__ === Object ); // (2) true
```

So `Rabbit` now provides access to the static methods of `Object` via `Rabbit`, like this:
ดังนั้น `Rabbit` จึงเข้าถึงเมธอด static ของ `Object` ผ่านตัว `Rabbit` ได้เลย เช่น:

```js run
class Rabbit extends Object {}

*!*
// normally we call Object.getOwnPropertyNames
// ปกติเราเรียก Object.getOwnPropertyNames
alert ( Rabbit.getOwnPropertyNames({a: 1, b: 2})); // a,b
*/!*
```

But if we don't have `extends Object`, then `Rabbit.__proto__` is not set to `Object`.
แต่ถ้าไม่มี `extends Object` ค่า `Rabbit.__proto__` จะไม่ชี้ไปที่ `Object`

Here's the demo:
ลองดูตัวอย่าง:

```js run
class Rabbit {}

alert( Rabbit.prototype.__proto__ === Object.prototype ); // (1) true
alert( Rabbit.__proto__ === Object ); // (2) false (!)
alert( Rabbit.__proto__ === Function.prototype ); // as any function by default
alert( Rabbit.__proto__ === Function.prototype ); // เป็นค่าเริ่มต้นของทุกฟังก์ชัน

*!*
// error, no such function in Rabbit
// ไม่มีฟังก์ชันนี้ใน Rabbit
alert ( Rabbit.getOwnPropertyNames({a: 1, b: 2})); // Error
*/!*
```

So `Rabbit` doesn't provide access to static methods of `Object` in that case.
ในกรณีนี้ `Rabbit` จึงเข้าถึงเมธอด static ของ `Object` ไม่ได้

By the way, `Function.prototype` also has "generic" function methods, like `call`, `bind` etc. They are ultimately available in both cases, because for the built-in `Object` constructor, `Object.__proto__ === Function.prototype`.
อีกอย่าง `Function.prototype` ก็มีเมธอดทั่วไปของฟังก์ชัน เช่น `call`, `bind` เป็นต้น ซึ่งใช้ได้ทั้งสองกรณี เพราะคอนสตรักเตอร์ `Object` ในตัวก็มี `Object.__proto__ === Function.prototype` เช่นกัน

Here's the picture:
ภาพประกอบ:

![](rabbit-extends-object.svg)

So, to put it short, there are two differences:
สรุปสั้นๆ ความแตกต่างมีสองข้อ:

| class Rabbit | class Rabbit extends Object |
|--------------|------------------------------|
| -- | needs to call `super()` in constructor |
| -- | ต้องเรียก `super()` ในคอนสตรักเตอร์ |
| `Rabbit.__proto__ === Function.prototype` | `Rabbit.__proto__ === Object` |
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ importance: 3

# Class extends Object?

As we know, all objects normally inherit from `Object.prototype` and get access to "generic" object methods like `hasOwnProperty` etc.
อย่างที่เราทราบ ออบเจ็กต์ทุกตัวจะสืบทอดจาก `Object.prototype` โดยปกติ ทำให้เข้าถึงเมธอดทั่วไปของออบเจ็กต์ได้ เช่น `hasOwnProperty` เป็นต้น

For instance:
ตัวอย่าง:

```js run
class Rabbit {
Expand All @@ -18,16 +18,16 @@ class Rabbit {
let rabbit = new Rabbit("Rab");

*!*
// hasOwnProperty method is from Object.prototype
// เมธอด hasOwnProperty มาจาก Object.prototype
alert( rabbit.hasOwnProperty('name') ); // true
*/!*
```

But if we spell it out explicitly like `"class Rabbit extends Object"`, then the result would be different from a simple `"class Rabbit"`?
แต่ถ้าเราเขียนแบบระบุชัดเจนว่า `"class Rabbit extends Object"` ผลลัพธ์จะต่างจาก `"class Rabbit"` ธรรมดาไหม?

What's the difference?
ต่างกันตรงไหน?

Here's an example of such code (it doesn't work -- why? fix it?):
ลองดูตัวอย่างโค้ดนี้ (ซึ่งใช้ไม่ได้ -- ทำไม? แก้ยังไง?):

```js
class Rabbit extends Object {
Expand Down
Loading