{
  "assessmentTests": {
    "javascript_test": {
      "name": "Pagsubok sa JavaScript",
      "desc": "30 scenario questions sa core syntax at coercion, functions/scope/closures at this, objects/arrays at data structures, at ang event loop/async/prototype idioms — alamin kung tumutugma ang iyong JavaScript sa ibig sabihin ng isang job posting ng JavaScript proficiency.",
      "recommendation": "Ang iyong JavaScript skills profile",
      "results": {
        "beginner": {
          "name": "Nagsisimula pa lang",
          "desc": "Kaya mo nang sumulat ng gumaganang functions at objects, pero ang mga tanong na na-miss mo ay nag-cluster sa paligid ng type coercion at reference semantics sa halip na syntax — ang == na tahimik na nag-co-convert ng types bago mag-compare, ang isang array assignment na nagsha-share ng isang object sa halip na kopyahin ito, kung bakit hindi kailanman equal sa sarili nito ang NaN. Wala sa mga ito ang tungkol sa pagiging mahina sa JavaScript; ito ang mga specific rules na nakakatisod sa mga taong natuto ng language sa pamamagitan ng pagsulat ng code na nagkataong gumana sa halip na pag-aaral kung paano talaga kumikilos ang values at references. Mahalaga ang mga ito sa trabaho dahil ang bawat isa ay kung saan tumatakbo ang code nang walang error pero gumagawa pa rin ng maling bagay.",
          "recommendation": "Magsimula sa tatlong bagay, sa pagkakasunod-sunod na ito: kung bakit nagco-coerce ng types ang == bago mag-compare habang hindi ito ginagawa ng ===, kung bakit ang pag-assign ng isang array o object sa isang bagong variable ay kumo-copy ng reference sa halip na value, at kung paano hino-hoist at ina-initialize sa undefined ang var habang ang let at const ay nananatili sa temporal dead zone hanggang sa tumakbo ang declaration nila. Sinasaklaw ng JavaScript guide ng MDN ang lahat ng tatlo nang may mga runnable examples."
        },
        "intermediate": {
          "name": "Katamtaman",
          "desc": "Komportable mong ha-handle ang everyday application code — functions, array methods, straightforward control flow — at hindi ka mababagalan sa routine feature work. Ang agwat sa pagitan nito at Advanced ay nasa kadalasan kung ano ang mangyayari kapag nag-interact ang scoping at timing rules ng JavaScript: isang var na na-capture sa loob ng callbacks ng isang loop na lahat ay bumabasa ng parehong final value, isang this na tahimik na huminto sa pagtuturo sa object kapag na-detach ang isang method mula rito, isang spread copy na mukhang malalim pero isang level lang ang kini-copy. Ito ang klase ng mga bug na nakakalusot sa isang mabilisang pagbasa at lumalabas lang sa ilalim ng isang specific runtime condition.",
          "recommendation": "Mag-focus sa kung paano talaga nire-resolve ang scope at this sa call time sa halip na definition time: kung bakit binibigyan ng isang var-based na for loop ang bawat callback ng parehong final counter value habang hindi ginagawa ito ng let, kung paano tinutukoy ang this batay sa kung paano tinawag ang isang function sa halip na kung saan ito isinulat, at kung bakit kino-copy lang ng spread o Object.assign ang top level ng isang object. Pagkatapos ang event loop, dahil iyon ang nakakatisod sa mga taong marunong na indibidwal ng promises."
        },
        "advanced": {
          "name": "Mataas",
          "desc": "Ito ang level na ibig sabihin ng karamihan ng job postings kapag sinabi nilang \"strong JavaScript.\" Binabasa mo ang isang chain ng filter/map/reduce at eksaktong maihuhula mo kung ano ang ire-return nito nang hindi nagmu-mutate sa orihinal na array, alam mo kung bakit palaging tinatalo ng synchronous console.log ang isang microtask na palaging tumatalo sa isang setTimeout, at kinukuha mo ang Promise.all na alam na ito ay nagre-reject sa sandaling mag-reject ang alinmang promise sa halip na maghintay sa iba. Ang naghihiwalay sa band na ito mula sa itaas ay ang prototype at object-model na side ng trabaho: kung paano nire-resolve ng prototype chain ang isang na-inherit na method laban sa hasOwnProperty, at kung ano talaga ang itinatago ng isang private class field.",
          "recommendation": "Itulak papasok sa mga parte na nag-p-protect ng state na ginagalaw din ng ibang code: kung paano nire-resolve ng prototype chain ng JavaScript ang method lookups na wala sa instance mismo, kung ano talaga ang itinatago ng private #fields ng isang class mula sa outside access, at kung paano tinatrato nang magkaiba ng JSON.stringify ang undefined at functions sa loob ng isang plain object kumpara sa loob ng isang array. Ang materyal ng MDN sa event loop at prototype chain ang natural na susunod na hakbang para sa dalawa."
        },
        "expert": {
          "name": "Eksperto",
          "desc": "Nakakuha ka ng top score sa bawat section — core syntax, types at coercion; functions, scope, closures at this; objects, arrays at data structures; at async, ang event loop, prototypes at idioms. Sa praktikal, ibig sabihin nito ay puwede kang bigyan ng function ng isang stranger at maipaliwanag mo kung bakit ito nagre-return ng ire-return nito, hindi lang kung ano ang sinasabi ng syntax na dapat nitong gawin, na siyang mas mahirap at mas valuable na skill. Sa level na ito, bihira ang language mismo ang limiting factor; ang limit ay kadalasan ang async control flow o ang hugis ng data sa ilalim nito.",
          "recommendation": "Nasa design at diagnosis na ngayon ang mga return: pag-reason tungkol sa isang race condition sa pagitan ng Promise.all at Promise.race sa halip na i-recite ang mga definition nito, ang pagpili kung kailan ang closure ang tamang tool para sa private state kumpara sa kailan ang private field ng isang class, at ang pagbasa ng isang microtask-vs-macrotask ordering bug sa production logs sa halip na sa isang quiz. Kung sine-screen ka para sa isang role, ilarawan ang isang timing bug na natagpuan mo — isang stale closure variable o isang out-of-order async callback — sa halip na pangalanan ang mga JavaScript features; ipinapakita nito ang reasoning, hindi lang ang vocabulary."
        }
      },
      "questions": [
        {
          "question": "console.log(x);\nvar x = 5;\nAno ang ipi-print nito?",
          "options": [
            {
              "icon": "",
              "label": "5 — ang var declarations ay tumatakbo agad, bago ang anumang ibang code"
            },
            {
              "icon": "",
              "label": "ReferenceError: x is not defined"
            },
            {
              "icon": "",
              "label": "undefined — ang var declarations ay hino-hoist sa itaas ng kanilang scope at ina-initialize sa undefined, pero ang assignment ay tumatakbo sa kinaroroonan nito, kaya bago ito tumakbo ang variable ay existing na pero may hawak na undefined"
            },
            {
              "icon": "",
              "label": "null"
            }
          ]
        },
        {
          "question": "console.log(y);\nlet y = 5;\nAno ang mangyayari?",
          "options": [
            {
              "icon": "",
              "label": "Nagtapon ito ng ReferenceError: Cannot access 'y' before initialization — ang let ay hino-hoist sa itaas ng kanyang scope pero nananatili sa temporal dead zone hanggang sa aktwal na tumakbo ang declaration line"
            },
            {
              "icon": "",
              "label": "Nag-print ito ng undefined, katulad ng gagawin ng var"
            },
            {
              "icon": "",
              "label": "Nag-print ito ng 5"
            },
            {
              "icon": "",
              "label": "Nagtapon ito ng SyntaxError sa parse time"
            }
          ]
        },
        {
          "question": "const arr = [1, 2, 3];\narr.push(4);\nconsole.log(arr.length);\nAno ang ipi-print nito?",
          "options": [
            {
              "icon": "",
              "label": "4 — ang const ay pumipigil lang sa muling pag-assign sa arr binding mismo, hindi sa pag-mutate ng array object na tinuturo nito, kaya gumagana pa rin ang push"
            },
            {
              "icon": "",
              "label": "Nagtapon ito ng TypeError, dahil const ang arr"
            },
            {
              "icon": "",
              "label": "3 — naka-block ang push sa isang const array"
            },
            {
              "icon": "",
              "label": "undefined"
            }
          ]
        },
        {
          "question": "console.log('' == 0);\nconsole.log('' === 0);\nAno ang ipi-print ng dalawang linya?",
          "options": [
            {
              "icon": "",
              "label": "true tapos true"
            },
            {
              "icon": "",
              "label": "false tapos false"
            },
            {
              "icon": "",
              "label": "true tapos false — ang == ay nag-co-coerce sa empty string papuntang 0 bago mag-compare, habang ang === ay nagco-compare ng type at value nang walang coercion, at ang isang string ay hindi kailanman strictly equal sa isang number"
            },
            {
              "icon": "",
              "label": "false tapos true"
            }
          ]
        },
        {
          "question": "console.log(NaN === NaN);\nconsole.log(Number.isNaN(NaN));\nAno ang ipi-print ng dalawang linya?",
          "options": [
            {
              "icon": "",
              "label": "true tapos true"
            },
            {
              "icon": "",
              "label": "true tapos false"
            },
            {
              "icon": "",
              "label": "false tapos false"
            },
            {
              "icon": "",
              "label": "false tapos true — ang NaN ang tanging value sa JavaScript na hindi equal sa sarili nito sa ilalim ng ===, pero tama pa rin itong nade-detect ng Number.isNaN()"
            }
          ]
        },
        {
          "question": "console.log(typeof null);\nAno ang ipi-print nito?",
          "options": [
            {
              "icon": "",
              "label": "\"null\""
            },
            {
              "icon": "",
              "label": "\"object\" — isang matagal nang bug sa language: nagre-return ang typeof null ng \"object\" kahit na primitive ang null, at napanatili ito para sa backwards compatibility mula noon"
            },
            {
              "icon": "",
              "label": "\"undefined\""
            },
            {
              "icon": "",
              "label": "\"boolean\""
            }
          ]
        },
        {
          "question": "Alin sa mga sumusunod ang truthy kapag ginamit sa isang if condition?",
          "options": [
            {
              "icon": "",
              "label": "0"
            },
            {
              "icon": "",
              "label": "\"\" (isang empty string)"
            },
            {
              "icon": "",
              "label": "null"
            },
            {
              "icon": "",
              "label": "\"0\" — ang isang non-empty string ay palaging truthy sa JavaScript, kahit na ang content nito mismo ay ang string na \"0\""
            }
          ]
        },
        {
          "question": "foo();\nfunction foo() { console.log('a'); }\nbar();\nvar bar = function() { console.log('b'); };\nAno ang mangyayari?",
          "options": [
            {
              "icon": "",
              "label": "Parehong tawag ay nag-print, \"a\" tapos \"b\""
            },
            {
              "icon": "",
              "label": "Nag-print ang foo() ng \"a\"; nagtapon ang bar() ng TypeError: bar is not a function — ang function declarations ay fully hino-hoist kasama ang body nila, pero ang isang var-assigned function expression ay hino-hoist lang ang var mismo (bilang undefined), hindi ang assignment"
            },
            {
              "icon": "",
              "label": "Parehong tawag ay nagtapon ng ReferenceError"
            },
            {
              "icon": "",
              "label": "Nagtapon ang foo(); nag-print ang bar() ng \"b\""
            }
          ]
        },
        {
          "question": "function makeCounter() {\n  let count = 0;\n  return function() { count++; return count; };\n}\nconst counter = makeCounter();\nconsole.log(counter());\nconsole.log(counter());\nAno ang ipi-print ng dalawang linya?",
          "options": [
            {
              "icon": "",
              "label": "1 tapos 1"
            },
            {
              "icon": "",
              "label": "0 tapos 1"
            },
            {
              "icon": "",
              "label": "undefined tapos undefined"
            },
            {
              "icon": "",
              "label": "1 tapos 2 — ang na-return na function ay nag-close over sa parehong count variable mula sa scope ng makeCounter, at nagpapatuloy ang variable na iyon sa pagitan ng mga tawag sa halip na mag-reset"
            }
          ]
        },
        {
          "question": "for (var i = 0; i < 3; i++) {\n  setTimeout(() => console.log(i), 0);\n}\nAno ang ipi-print nito?",
          "options": [
            {
              "icon": "",
              "label": "0, 1, 2"
            },
            {
              "icon": "",
              "label": "3, 3, 3 — ang var ay function-scoped, hindi block-scoped, kaya ang lahat ng tatlong callbacks ay nag-close over sa parehong i, na natapos na sa loop at katumbas ng 3 sa oras na aktwal na tumakbo ang alinman sa kanila"
            },
            {
              "icon": "",
              "label": "0, 0, 0"
            },
            {
              "icon": "",
              "label": "undefined, undefined, undefined"
            }
          ]
        },
        {
          "question": "for (let i = 0; i < 3; i++) {\n  setTimeout(() => console.log(i), 0);\n}\nAno ang ipi-print nito?",
          "options": [
            {
              "icon": "",
              "label": "3, 3, 3"
            },
            {
              "icon": "",
              "label": "0, 0, 0"
            },
            {
              "icon": "",
              "label": "undefined, undefined, undefined"
            },
            {
              "icon": "",
              "label": "0, 1, 2 — ang let ay gumagawa ng bagong binding ng i para sa bawat loop iteration, kaya ang bawat callback ay nag-close over sa sarili nitong hiwalay na kopya sa halip na isang shared variable"
            }
          ]
        },
        {
          "question": "function greet() { return `Hi, ${this.name}`; }\nconst person = { name: 'Ana' };\nconsole.log(greet.call(person));\nAno ang ipi-print nito?",
          "options": [
            {
              "icon": "",
              "label": "\"Hi, Ana\" — tinatawag ng Function.prototype.call ang function nang may this na explicit na naka-set sa unang argument nito, kaya ang this.name ay nire-resolve laban kay person"
            },
            {
              "icon": "",
              "label": "\"Hi, undefined\" — gumagana lang ang call() sa functions na methods na ng isang object"
            },
            {
              "icon": "",
              "label": "Nagtapon ito ng TypeError, dahil hindi method ng person ang greet"
            },
            {
              "icon": "",
              "label": "\"Hi, ${this.name}\" — hindi ine-evaluate ng call() ang template literal"
            }
          ]
        },
        {
          "question": "const timer = {\n  seconds: 0,\n  start: function() {\n    setInterval(() => { this.seconds++; }, 1000);\n  },\n};\nBakit mas gusto ng mga tao ang arrow function kaysa sa function() { this.seconds++ } sa loob ng setInterval dito?",
          "options": [
            {
              "icon": "",
              "label": "Ang arrow functions ay walang sariling this — kina-capture nila ang this nang lexical mula sa nakapalibot na start function, na siyang timer (dahil tinawag ang start bilang timer.start()), kaya tama ang pagtukoy ng this.seconds sa timer.seconds sa bawat tick"
            },
            {
              "icon": "",
              "label": "Mas mabilis tumakbo ang arrow functions kaysa sa regular functions sa runtime"
            },
            {
              "icon": "",
              "label": "Awtomatikong ibi-bind ng arrow functions ang this sa global object, na nagkataong katumbas ng timer"
            },
            {
              "icon": "",
              "label": "Awtomatikong kina-convert ng arrow functions ang this papuntang global variable"
            }
          ]
        },
        {
          "question": "function multiply(a, b) { return a * b; }\nconst double = multiply.bind(null, 2);\nconsole.log(double(5));\nAno ang ipi-print nito?",
          "options": [
            {
              "icon": "",
              "label": "Nagtapon ito ng error, dahil kailangan ng bind ang parehong arguments nang maaga"
            },
            {
              "icon": "",
              "label": "10 — ang bind ay nagre-return ng bagong function na may this at anumang leading arguments na pre-set na; ang pagtawag sa double(5) ay nagbibigay ng natitirang argument na b=5, kaya tumatakbo ang multiply(2, 5)"
            },
            {
              "icon": "",
              "label": "NaN"
            },
            {
              "icon": "",
              "label": "7, dahil ang bind ay nagdadagdag ng mga argument nito sa tawag sa halip na palitan ang mga ito"
            }
          ]
        },
        {
          "question": "function outer() {\n  let x = 10;\n  function inner() {\n    let x = 20;\n    console.log(x);\n  }\n  inner();\n  console.log(x);\n}\nouter();\nAno ang ipi-print ng dalawang console.log calls?",
          "options": [
            {
              "icon": "",
              "label": "20 tapos 20"
            },
            {
              "icon": "",
              "label": "20 tapos 10 — ang sariling let x ng inner ay nagsha-shadow sa x ng outer sa loob lang ng scope ng inner; hindi kailanman nagagalaw ang sariling x ng outer"
            },
            {
              "icon": "",
              "label": "10 tapos 10"
            },
            {
              "icon": "",
              "label": "Nagtapon ito ng ReferenceError, dahil dalawang beses na-declare ang x"
            }
          ]
        },
        {
          "question": "const a = [1, 2, 3];\nconst b = a;\nb.push(4);\nconsole.log(a.length);\nAno ang ipi-print nito?",
          "options": [
            {
              "icon": "",
              "label": "3 — hiwalay na kopya ng a ang b"
            },
            {
              "icon": "",
              "label": "undefined"
            },
            {
              "icon": "",
              "label": "Nagtapon ito ng TypeError, dahil const ang a"
            },
            {
              "icon": "",
              "label": "4 — ang arrays ay mga object, kaya ang const b = a ay kumo-copy ng reference, hindi ng array; ang pag-mutate sa b sa pamamagitan ng push ay nag-mu-mutate rin sa eksaktong parehong array na tinuturo ng a"
            }
          ]
        },
        {
          "question": "const original = { name: 'Ana', tags: ['x', 'y'] };\nconst copy = { ...original };\ncopy.name = 'Bea';\ncopy.tags.push('z');\nconsole.log(original.name, original.tags.length);\nAno ang ipi-print nito?",
          "options": [
            {
              "icon": "",
              "label": "'Ana' 2 — dini-deep-clone ng spread ang bawat nested object at array"
            },
            {
              "icon": "",
              "label": "'Ana' 3 — shallow copy lang ang spread: ang isang primitive property tulad ng name ay kino-copy by value, kaya ang muling pag-assign sa copy.name ay hindi kailanman nagagalaw ang original, pero ang isang nested array tulad ng tags ay kino-copy by reference, kaya ang pag-push papunta sa copy.tags ay nag-mu-mutate sa eksaktong parehong array na tinuturo ng original.tags"
            },
            {
              "icon": "",
              "label": "'Bea' 3 — kino-copy ng spread ang lahat by reference, kaya parehong ang top-level at nested changes ay bumabalik sa original"
            },
            {
              "icon": "",
              "label": "'Bea' 2"
            }
          ]
        },
        {
          "question": "const { a: x = 10, b: y = 20 } = { a: 5 };\nconsole.log(x, y);\nAno ang ipi-print nito?",
          "options": [
            {
              "icon": "",
              "label": "undefined undefined"
            },
            {
              "icon": "",
              "label": "5 undefined"
            },
            {
              "icon": "",
              "label": "10 20"
            },
            {
              "icon": "",
              "label": "5 20 — ang a ay pinalitan ng pangalan papuntang x at present ito, kaya pinapanatili nito ang value nitong 5; ang b ay pinalitan ng pangalan papuntang y at wala ito, kaya babalik ito sa default nitong 20"
            }
          ]
        },
        {
          "question": "const [first, ...rest] = [1, 2, 3, 4];\nconsole.log(rest);\nAno ang ipi-print nito?",
          "options": [
            {
              "icon": "",
              "label": "[1, 2, 3, 4]"
            },
            {
              "icon": "",
              "label": "[2, 3, 4] — tinitipon ng rest ang bawat natitirang element pagkatapos ng first papunta sa bagong-bagong array"
            },
            {
              "icon": "",
              "label": "2"
            },
            {
              "icon": "",
              "label": "[1]"
            }
          ]
        },
        {
          "question": "const nums = [10, 1, 2];\nnums.sort();\nconsole.log(nums);\nAno ang ipi-print nito?",
          "options": [
            {
              "icon": "",
              "label": "[1, 2, 10] — palaging inaayos ng sort ang mga numero nang numerically sa ascending order bilang default"
            },
            {
              "icon": "",
              "label": "[10, 1, 2] — hindi nagmu-mutate ang sort sa orihinal na array"
            },
            {
              "icon": "",
              "label": "[1, 10, 2] — kina-convert ng default comparator ng Array.prototype.sort ang mga elemento papuntang strings at ino-compare ang mga ito nang lexicographically, kaya ang \"10\" ay nauuna sa \"2\"; ang sort ay nag-mu-mutate rin sa array in place sa halip na magbalik ng bago"
            },
            {
              "icon": "",
              "label": "[2, 1, 10]"
            }
          ]
        },
        {
          "question": "const user = { profile: { age: 0 } };\nconsole.log(user.profile?.age ?? 'unknown');\nconsole.log(user.address?.city ?? 'unknown');\nAno ang ipi-print ng dalawang linya?",
          "options": [
            {
              "icon": "",
              "label": "'unknown' tapos 'unknown' — tinuturing ng ?? ang 0 bilang missing, kapareho ng ginagawa ng ||"
            },
            {
              "icon": "",
              "label": "0 tapos 'unknown' — ang ?? ay bumabalik lang sa null o undefined, hindi sa ibang falsy values tulad ng 0, kaya ang age (0) ay napapanatili as-is; undefined ang user.address, kaya ang ?. ay nag-short-circuit sa buong chain papuntang undefined at pagkatapos ay ang ?? ang nagbibigay ng 'unknown'"
            },
            {
              "icon": "",
              "label": "0 tapos undefined"
            },
            {
              "icon": "",
              "label": "'unknown' tapos 0"
            }
          ]
        },
        {
          "question": "const obj = { a: undefined, b: function(){}, c: NaN, d: [undefined, function(){}, 1] };\nconsole.log(JSON.stringify(obj));\nAno ang ipi-print nito?",
          "options": [
            {
              "icon": "",
              "label": "'{\"a\":null,\"b\":null,\"c\":null,\"d\":[null,null,1]}' — ang bawat hindi-suportadong value ay nagiging null kahit saan, sa objects man o arrays"
            },
            {
              "icon": "",
              "label": "'{\"a\":undefined,\"b\":undefined,\"c\":NaN,\"d\":[undefined,null,1]}'"
            },
            {
              "icon": "",
              "label": "'{\"c\":null,\"d\":[null,null,1]}' — ang object properties na ang value ay undefined o isang function ay ganap na tinatanggal, at ang NaN ay nagse-serialize papuntang null, pero sa loob ng isang array ang parehong hindi-suportadong values ay nagiging null sa halip na matanggal, dahil ang pagtanggal ng isang array element ay magsi-shift sa bawat later index"
            },
            {
              "icon": "",
              "label": "Nagtapon ito ng TypeError, dahil hindi ma-serialize ang NaN papuntang JSON"
            }
          ]
        },
        {
          "question": "console.log('1');\nsetTimeout(() => console.log('2'), 0);\nPromise.resolve().then(() => console.log('3'));\nconsole.log('4');\nAnong pagkakasunod-sunod ang pagpi-print ng mga ito?",
          "options": [
            {
              "icon": "",
              "label": "1, 2, 3, 4"
            },
            {
              "icon": "",
              "label": "1, 4, 2, 3"
            },
            {
              "icon": "",
              "label": "1, 4, 3, 2 — tumatakbo muna ang synchronous code (kaya agad na nagpi-print ang 1 at 4), pagkatapos ang microtask queue (Promise callbacks) ay ganap na nauubos bago lumipat ang event loop sa susunod na macrotask, kaya nagpi-print ang 3 bago ang 2 ng setTimeout callback"
            },
            {
              "icon": "",
              "label": "1, 3, 4, 2"
            }
          ]
        },
        {
          "question": "async function foo() {\n  console.log('a');\n  await null;\n  console.log('b');\n}\nconsole.log('start');\nfoo();\nconsole.log('end');\nAnong pagkakasunod-sunod ang pagpi-print ng mga ito?",
          "options": [
            {
              "icon": "",
              "label": "start, a, end, b — tumatakbo nang synchronous ang foo() hanggang sa unang await nito, kaya agad na nagla-log ang 'a' kapag tinawag ang foo(); pagkatapos ay sinuspinde ng await ang foo at ibinabalik ang control sa caller, kaya nagla-log ang 'end' bago ang na-resume na 'b', na tumatakbo mamaya bilang isang microtask"
            },
            {
              "icon": "",
              "label": "start, a, b, end"
            },
            {
              "icon": "",
              "label": "start, end, a, b"
            },
            {
              "icon": "",
              "label": "a, start, end, b"
            }
          ]
        },
        {
          "question": "Promise.all([\n  Promise.resolve(1),\n  Promise.reject('err'),\n  Promise.resolve(3),\n]).then(r => console.log('ok', r)).catch(e => console.log('fail', e));\nAno ang ipi-print nito?",
          "options": [
            {
              "icon": "",
              "label": "'fail err' — ang Promise.all ay nagre-reject sa sandaling mag-reject ang alinman sa input promises nito, binabalewala ang mga resulta ng iba, kaya tumatakbo ang catch handler kasama ang reason ng rejection na iyon"
            },
            {
              "icon": "",
              "label": "'ok' [1, 3]"
            },
            {
              "icon": "",
              "label": "'ok' [1, undefined, 3]"
            },
            {
              "icon": "",
              "label": "Nagtapon ito nang synchronous at walang handler na kailanman tumakbo"
            }
          ]
        },
        {
          "question": "const fast = new Promise(res => setTimeout(() => res('fast'), 10));\nconst slow = new Promise(res => setTimeout(() => res('slow'), 100));\nPromise.race([fast, slow]).then(v => console.log(v));\nAno ang ipi-print nito?",
          "options": [
            {
              "icon": "",
              "label": "'slow'"
            },
            {
              "icon": "",
              "label": "['fast', 'slow']"
            },
            {
              "icon": "",
              "label": "'fast' — ang Promise.race ay nagse-settle sa sandaling mag-settle ang una sa input promises nito, at ang 10ms timer ay nagre-resolve nang mas maaga kaysa sa 100ms na isa"
            },
            {
              "icon": "",
              "label": "Nagtapon ito ng error, dahil kailangan ng race ng eksaktong dalawang promises"
            }
          ]
        },
        {
          "question": "function Animal(name) { this.name = name; }\nAnimal.prototype.speak = function() { return `${this.name} makes a sound`; };\nconst dog = new Animal('Rex');\nconsole.log(dog.speak());\nconsole.log(dog.hasOwnProperty('speak'));\nAno ang ipi-print ng dalawang linya?",
          "options": [
            {
              "icon": "",
              "label": "'Rex makes a sound' tapos true"
            },
            {
              "icon": "",
              "label": "undefined tapos false"
            },
            {
              "icon": "",
              "label": "Nagtapon ito ng TypeError, dahil walang sariling speak method ang dog"
            },
            {
              "icon": "",
              "label": "'Rex makes a sound' tapos false — naka-define ang speak sa Animal.prototype, hindi sa dog instance mismo; nahahanap ito ng dog sa pamamagitan ng prototype chain kapag tinawag ito, pero ang hasOwnProperty ay tinitingnan lang ang sariling properties ng instance, hindi anumang na-inherit"
            }
          ]
        },
        {
          "question": "class Counter {\n  #count = 0;\n  increment() { this.#count++; return this.#count; }\n}\nconst c = new Counter();\nconsole.log(c.increment());\nconsole.log(c.count);\nAno ang ipi-print ng dalawang linya?",
          "options": [
            {
              "icon": "",
              "label": "1 tapos undefined — ang #count ay isang private class field, nababasa at nasusulatan lang mula sa loob ng sariling methods ng class; ang c.count (walang #) ay isang ganap na ibang, ordinaryong property na hindi kailanman na-set, kaya undefined ito"
            },
            {
              "icon": "",
              "label": "1 tapos 0"
            },
            {
              "icon": "",
              "label": "1 tapos 1"
            },
            {
              "icon": "",
              "label": "Nagtapon ito ng SyntaxError kapag ina-access ang c.count"
            }
          ]
        },
        {
          "question": "const items = ['a', 'b'];\nconst label = `Items: ${items.length > 0 ? items.join(', ') : 'none'}`;\nconsole.log(label);\nAno ang ipi-print nito?",
          "options": [
            {
              "icon": "",
              "label": "'Items: ${items.length > 0 ? items.join(\\', \\') : \\'none\\'}'"
            },
            {
              "icon": "",
              "label": "'Items: none'"
            },
            {
              "icon": "",
              "label": "'Items: a, b' — ine-evaluate ng template literals ang anumang expression na nilagay sa loob ng ${...}, kasama ang isang buong ternary, at ini-interpolate ang resulta nito nang direkta papunta sa string"
            },
            {
              "icon": "",
              "label": "Nagtapon ito ng SyntaxError, dahil hindi pinapayagan ang ternaries sa loob ng template literals"
            }
          ]
        },
        {
          "question": "const nums = [1, 2, 3, 4, 5];\nconst result = nums.filter(n => n % 2 === 0).map(n => n * 10).reduce((sum, n) => sum + n, 0);\nconsole.log(result, nums);\nAno ang ipi-print nito?",
          "options": [
            {
              "icon": "",
              "label": "60 [1, 2, 3, 4, 5] — ang filter, map at reduce ay bawat isa ay nagre-return ng bagong array o value nang hindi nagmu-mutate ng orihinal na array, kaya hindi nagbabago ang nums habang ang result ay ang huling reduced sum (ang 2 at 4, dinoble papuntang 20 at 40, tinotal papuntang 60)"
            },
            {
              "icon": "",
              "label": "60 [2, 4, 20, 40]"
            },
            {
              "icon": "",
              "label": "150 [1, 2, 3, 4, 5]"
            },
            {
              "icon": "",
              "label": "60 [20, 40]"
            }
          ]
        }
      ],
      "optionOrderVersion": "50fc0eba818f2d72"
    }
  },
  "testNames": {
    "javascript-test": "Pagsusulit sa JavaScript"
  }
}
