Function និង Scope
មាតិកា
- ហេតុអ្វីត្រូវមាន Function
- បីរបៀបសរសេរ Function
- Parameter, Default និង Rest
- Return Value
- Pure Function និង Side Effect
- Scope៖ អ្នកណាអាចមើលឃើញអ្វី
- Hoisting សង្ខេប
- Closure
- Callback៖ ការបញ្ជូន Function ចូល
- សាកល្បងដោយខ្លួនឯង
1. ហេតុអ្វីត្រូវមាន Function
Function គឺជាកូដដែលមានឈ្មោះ និងប្រើឡើងវិញបាន។ អ្នកសរសេរជំហានម្តង ដាក់ឈ្មោះឲ្យវា ហើយ ហៅ វាគ្រប់ពេលដែលអ្នកត្រូវការ។ នេះផ្តល់អ្នកបីយ៉ាង៖
- គ្មានការសរសេរដដែលៗ: កែ bug នៅកន្លែងតែមួយ មិនមែនដប់កន្លែង។
- ឈ្មោះដែលពន្យល់:
formatYear(2025)ប្រាប់អ្នកអានច្រើនជាងការគណនាបួនបន្ទាត់។ - ផ្នែកតូចៗ: កម្មវិធីធំក្លាយជា function តូចៗជាច្រើន ដែលអ្នកអាចយល់ និងសាកល្បងម្តងមួយៗ។
ទំព័ររបស់ Dara នឹងត្រូវការ function សម្រាប់ស្ទើរតែគ្រប់យ៉ាង៖ ការបង្ហាញគម្រោង ការពិនិត្យ form ការប្តូរទៅ dark mode។ ជំពូកនេះផ្តល់ឧបករណ៍ឲ្យអ្នកសរសេរវាបានល្អ។
2. បីរបៀបសរសេរ Function
នេះជាគំនិតដូចគ្នាដែលសរសេរបីបែប។
Function declaration ចាប់ផ្តើមដោយ keyword function៖
function greet(name) {
return "Hello, " + name + "!";
}
console.log(greet("Dara")); // "Hello, Dara!"
Function expression ផ្ទុក function ក្នុង variable៖
const double = function (n) {
return n * 2;
};
Arrow function គឺជាទម្រង់ខ្លីជាងនៃ expression៖
const triple = (n) => n * 3;
const add = (a, b) => {
const sum = a + b;
return sum;
};
ច្បាប់ពីរសម្រាប់ arrow function ដែលត្រូវចងចាំ៖
- ប្រសិនបើតួ function ជា expression តែមួយ អ្នកអាចលុបសញ្ញាអង្កាប់ និងពាក្យ
returnហើយតម្លៃនឹងត្រូវបាន return ដោយស្វ័យប្រវត្តិ (tripleខាងលើ)។ - ដើម្បី return object តាមរបៀបនេះ សូមដាក់វាក្នុងសញ្ញាវង់ក្រចក ដើម្បីកុំឲ្យ JavaScript ស្មានថាសញ្ញាអង្កាប់ជាតួ function៖
const makeBadge = (title) => ({ label: title, isNew: true });
| ទម្រង់ | មើលទៅដូច | កំណត់សម្គាល់ |
|---|---|---|
| Declaration | function greet() {} | អាចហៅមុនបន្ទាត់របស់វាបាន (មើល hoisting) |
| Expression | const greet = function () {} | ដំណើរការតែបន្ទាប់ពីបន្ទាត់របស់វា |
| Arrow | const greet = () => {} | ខ្លី; ល្អបំផុតសម្រាប់ function តូចៗ និង callback |
តើគួរប្រើមួយណា? ជ្រើសរើសរបៀបមួយ ហើយប្រើឲ្យស្របគ្នា។ ជម្រើសទូទៅ ហើយជាជម្រើសក្នុងស៊េរីនេះ៖ declaration សម្រាប់ function មានឈ្មោះសំខាន់ៗ និង arrow សម្រាប់ helper ខ្លីៗ និង callback។
3. Parameter, Default និង Rest
ឈ្មោះក្នុងសញ្ញាវង់ក្រចកហៅថា parameter; តម្លៃដែលអ្នកបញ្ជូនចូលហៅថា argument។ Parameter ប្រៀបដូច variable ដែលត្រូវបានបង្កើតថ្មីរាល់ពេល function ដំណើរការ។
function describe(title, year = 2025, ...tags) {
return `${title} (${year}) [${tags.join(", ")}]`;
}
console.log(describe("Recipe Finder"));
console.log(describe("Recipe Finder", 2024, "html", "css"));
console.log(describe("Quick Note", undefined, "js"));
លទ្ធផលគឺ៖
Recipe Finder (2025) []
Recipe Finder (2024) [html, css]
Quick Note (2025) [js]
- Default value:
year = 2025ត្រូវបានប្រើនៅពេល argument បាត់ ឬជាundefined។ នៅការហៅទីបីundefinedត្រូវបានបញ្ជូនដោយចេតនា ដើម្បីរក្សា default។ - Rest parameter:
...tagsប្រមូល argument ដែលនៅសល់ទាំងអស់ទៅជា array ពិតប្រាកដ។ វាត្រូវតែជា parameter ចុងក្រោយ។ - ប្រសិនបើអ្នកបញ្ជូន argument តិចពេក parameter ដែលបាត់នឹងជា
undefined។ ប្រសិនបើបញ្ជូនច្រើនពេក ចំនួនលើសនឹងត្រូវបានមិនអើពើ (លុះត្រាតែអ្នកប្រើ rest)។
4. Return Value
return បញ្ចប់ function ហើយផ្ញើតម្លៃត្រឡប់ទៅអ្នកហៅវិញ៖
function sign(n) {
if (n < 0) {
return "negative";
}
return "not negative";
}
console.log(sign(-1)); // "negative"
console.log(sign(3)); // "not negative"
បន្ទាត់ដែលនៅក្រោយ return ដែលបានដំណើរការ នឹងមិនត្រូវបានទៅដល់ទេ។ នេះអនុញ្ញាតឲ្យអ្នកសរសេរ early return៖ ដោះស្រាយករណីមិនធម្មតាជាមុន រួចបន្តជាមួយករណីធម្មតា។ វាជៀសវាង if block ដែលដាក់ក្នុងគ្នាជ្រៅ។
Function ដែលគ្មាន return ផ្តល់ undefined ត្រឡប់មកវិញ៖
function noReturn() {
const x = 1;
}
console.log(noReturn()); // undefined
កំហុសទូទៅបំផុតរបស់អ្នកចាប់ផ្តើមគឺ បោះពុម្ព លទ្ធផលនៅក្នុង function (console.log) ខណៈដែលអ្នកចង់ return វា។ តម្លៃដែលបានបោះពុម្ពរលាយបាត់; តម្លៃដែលបាន return អាចត្រូវបានរក្សាទុក សាកល្បង និងបញ្ជូនទៅ function បន្ទាប់។
5. Pure Function និង Side Effect
Function ជា pure នៅពេលវាពឹងផ្អែកតែលើ argument របស់វា ហើយអ្វីតែមួយគត់ដែលវាធ្វើគឺ return លទ្ធផល។ ផ្តល់ input ដូចគ្នា អ្នកនឹងបាន output ដូចគ្នាជានិច្ច។
const withDiscount = (price, percent) => price - (price * percent) / 100;
console.log(withDiscount(100, 10)); // 90
Function មាន side effect នៅពេលវាផ្លាស់ប្តូរអ្វីមួយនៅខាងក្រៅខ្លួនវាផង៖ ការបោះពុម្ព ការផ្លាស់ប្តូរ variable ការកែទំព័រ ការរក្សាទុកឯកសារ។
const log = [];
function addToLog(message) {
log.push(message); // changes data outside the function
}
addToLog("page loaded");
console.log(log); // [ 'page loaded' ]
Side effect មិនអាក្រក់ទេ; កម្មវិធីត្រូវការវាដើម្បីធ្វើអ្វីដែលមានប្រយោជន៍។ ប៉ុន្តែ pure function ងាយស្រួលសាកល្បង និងទុកចិត្តជាងឆ្ងាយ។ ទម្លាប់ល្អ៖ រក្សាការគណនានៅក្នុង pure function ហើយរក្សា side effect នៅកន្លែងតូចៗមួយចំនួនដែលមានឈ្មោះច្បាស់លាស់។ ទំព័ររបស់ Dara នឹងធ្វើតាមនេះ៖ pure function មួយសម្រេចថាត្រូវបង្ហាញគម្រោងណាខ្លះ ហើយ function ដាច់ដោយឡែកមួយដាក់វាលើទំព័រ។
6. Scope៖ អ្នកណាអាចមើលឃើញអ្វី
Scope គឺជាតំបន់នៃកូដដែល variable អាចត្រូវបានប្រើ។ JavaScript មានបីកម្រិតដែលអ្នកត្រូវដឹង។
| Scope | បង្កើតដោយ | អាចមើលឃើញ |
|---|---|---|
| Global | កម្រិតកំពូលនៃឯកសារ | គ្រប់ទីកន្លែង |
| Function | តួ function | តែនៅក្នុង function នោះ |
| Block | { } ណាមួយ ដូចជា if ឬ for | តែនៅក្នុងសញ្ញាអង្កាប់ទាំងនោះ (let និង const) |
const siteName = "Dara Sok"; // global
function showScope() {
const local = "inside"; // function scope
if (true) {
const blockOnly = "block"; // block scope
}
console.log(blockOnly); // ReferenceError: blockOnly is not defined
return siteName + " " + local;
}
កូដខាងក្នុងមើលឃើញ variable ខាងក្រៅ ប៉ុន្តែកូដខាងក្រៅមើលមិនឃើញ variable ខាងក្នុងទេ។ នៅក្នុង showScope មើលឃើញ siteName។ នៅខាងក្រៅវា មើលមិនឃើញ local ទេ៖
console.log(local); // ReferenceError: local is not defined
JavaScript ស្វែងរកឈ្មោះចាប់ផ្តើមពី scope បច្ចុប្បន្ន រួចផ្លាស់ទៅខាងក្រៅម្តងមួយកម្រិត។ ប្រសិនបើ variable ខាងក្នុងមានឈ្មោះដូច variable ខាងក្រៅ variable ខាងក្នុង shadow (បាំង) វា៖
const x = "outer";
function shadow() {
const x = "inner";
return x;
}
console.log(shadow(), x); // "inner" "outer"
ហេតុអ្វីបានជាវាសំខាន់? Scope តូចៗការពារអ្នក។ Variable ដែលរស់នៅតែក្នុង function មួយ មិនអាចត្រូវបានផ្លាស់ប្តូរដោយចៃដន្យពីកន្លែងផ្សេងបានទេ។ ដូច្នេះ៖ ប្រកាស variable ឲ្យជិតកន្លែងដែលអ្នកប្រើវាបំផុត ហើយជៀសវាង global variable។
Keyword ចាស់មួយ var មិនអើពើ block scope ហើយលេចចេញពីសញ្ញាអង្កាប់របស់ if និង for។ អ្នកនឹងឃើញវាក្នុងកូដចាស់។ កុំសរសេរវា; ប្រើ const និង let។
7. Hoisting សង្ខេប
មុនពេលដំណើរការកូដរបស់អ្នក JavaScript ស្កេនវា ហើយចុះបញ្ជីការប្រកាស។ នេះហៅថា hoisting ហើយវាមានផលជាក់ស្តែងមួយ៖ function declaration អាចត្រូវបានហៅ មុន បន្ទាត់ដែលវាលេចឡើង។
console.log(hoisted()); // "works"
function hoisted() {
return "works";
}
ប៉ុន្តែ const, let និង function expression មិន អាចប្រើមុនបន្ទាត់របស់វាបានទេ។ ការព្យាយាមធ្វើឲ្យមានកំហុស៖
console.log(later); // ReferenceError: Cannot access 'later' before initialization
const later = 1;
អ្នកមិនចាំបាច់ទន្ទេញច្បាប់ទេ។ ដំបូន្មានគឺសាមញ្ញ៖ កំណត់អ្វីៗមុនពេលអ្នកប្រើវា ហើយនៅពេលអ្នកឃើញ "Cannot access ... before initialization" សូមផ្លាស់ទីការកំណត់ឡើងលើ។
8. Closure
Function ចងចាំ variable ជុំវិញកន្លែងដែលវាត្រូវបាន បង្កើត សូម្បីតែបន្ទាប់ពី function ខាងក្រៅបានបញ្ចប់ក៏ដោយ។ នេះហៅថា closure។
function makeCounter() {
let count = 0;
return () => {
count++;
return count;
};
}
const counterA = makeCounter();
const counterB = makeCounter();
console.log(counterA(), counterA(), counterA()); // 1 2 3
console.log(counterB()); // 1
makeCounter បានដំណើរការចប់ហើយ ប៉ុន្តែ function ដែលត្រូវបាន return នៅតែចូលដល់ count បាន។ រាល់ការហៅ makeCounter បង្កើត count ដាច់ដោយឡែក ដូច្នេះ counterB ចាប់ផ្តើមពី 1។ គ្មានអ្វីនៅខាងក្រៅអាចប៉ះ count ដោយផ្ទាល់ទេ; វាជាឯកជនចំពោះ function ទាំងនោះ។
Closure ក៏ជារបៀបងាយស្រួលដើម្បី "បំពេញជាមុន" function ផងដែរ៖
function makeGreeter(greeting) {
return (name) => `${greeting}, ${name}!`;
}
const sayHello = makeGreeter("Hello");
console.log(sayHello("Dara")); // "Hello, Dara!"
អ្នកនឹងជួប closure ម្តងទៀតនៅជំពូកទី 8 នៅពេល event handler "ចងចាំ" ថាវាជារបស់ប៊ូតុងណា។
9. Callback៖ ការបញ្ជូន Function ចូល
នៅក្នុង JavaScript function គឺជា តម្លៃ ដូចលេខ ឬ string ដែរ។ អ្នកអាចរក្សាទុកវាក្នុង variable ហើយអ្នកអាចបញ្ជូនវាទៅ function ផ្សេងបាន។ Function ដែលត្រូវបានបញ្ជូនជា argument ហៅថា callback។
function repeat(times, action) {
for (let i = 1; i <= times; i++) {
action(i);
}
}
repeat(3, (n) => console.log("Round", n));
វាបោះពុម្ព Round 1, Round 2, Round 3។ Function repeat មិនដឹងថាការងារជាអ្វីទេ; អ្នកហៅជាអ្នកសម្រេច។
អ្នកបានប្រើគំនិតនេះរួចហើយ។ Method របស់ array ទទួល callback៖
const titles = ["Recipe Finder", "Weather Dashboard"];
const upper = titles.map((title) => title.toUpperCase());
console.log(upper); // [ 'RECIPE FINDER', 'WEATHER DASHBOARD' ]
Callback ក៏ជារបៀបដែល JavaScript រង់ចាំផងដែរ។ អ្នកនិយាយថា "ដំណើរការ function នេះ ពេលក្រោយ"៖
setTimeout(() => console.log("later"), 1000);
console.log("first");
first លេចឡើងភ្លាមៗ ហើយ later បន្ទាប់ពីមួយវិនាទី។ លំនាំ "ហៅខ្ញុំត្រឡប់វិញពេលរួចរាល់" នេះជាមូលដ្ឋានរបស់ event (ជំពូកទី 8) និងកូដ asynchronous (ជំពូកទី 9)។
10. សាកល្បងដោយខ្លួនឯង
-
បីទម្រង់។ សរសេរ function
isEven(n)ជា declaration បន្ទាប់មកជា expression រួចជា arrow មួយបន្ទាត់។ សាកល្បងទាំងបីដោយ4និង7។ -
Default។ សរសេរ
welcome(name, greeting = "Hello")ដែល return string។ ហៅវាដោយ argument មួយ និងដោយពីរ។ -
Rest។ សរសេរ
average(...numbers)ដែល return មធ្យមភាគ។ តើវាគួរ return អ្វីសម្រាប់ករណីគ្មាន argument? ដោះស្រាយករណីនោះដោយ early return។ -
Return មិនមែនបោះពុម្ព។ សរសេរ
formatTitle(title)ដែល return ចំណងជើងជាអក្សរធំ ដោយបន្ថែម" - Dara Sok"។ ប្រើលទ្ធផលនៅក្នុងconsole.logនៅខាងក្រៅ function។ -
រកកំហុស scope។ ទស្សន៍ទាយថាបន្ទាត់នីមួយៗបោះពុម្ពអ្វី រួចដំណើរការវា៖
const a = 1; function test() { const b = 2; if (b > 1) { const c = 3; } console.log(a, b); console.log(c); } test(); -
Closure។ សរសេរ
makeMultiplier(factor)ដែល return function គុណ input របស់វាជាមួយfactor។ បង្កើតdoubleនិងtripleពីវា ហើយសាកល្បង។
បន្ទាប់ យើងនឹងមើលឲ្យជិតនូវរចនាសម្ព័ន្ធពីរដែលកម្មវិធី JavaScript ប្រើច្រើនបំផុត គឺ array និង object ហើយធ្វើគំរូគម្រោងរបស់ Dara ជាទិន្នន័យពិតប្រាកដ។
ទិញកាហ្វេជូនខ្ញុំ
ចូលចិត្តមេរៀននេះមែនទេ? សូមពិចារណាទិញកាហ្វេជូនខ្ញុំមួយកែវ ដើម្បីគាំទ្រការបង្កើតមាតិកាឥតគិតថ្លៃបន្ថែមទៀត!