70 Pertanyaan Wawancara Javascript

Selamat siang teman!

Saya harap artikel ini bermanfaat bagi pengembang pemula dan yang berpengalaman.

Dalam pertanyaan-pertanyaan yang menurut saya lebih sulit daripada yang lain, referensi untuk literatur tambahan diberikan.

Saya akan berterima kasih atas komentar rinci. Semua komentar akan diperhitungkan saat mengedit artikel.

Jadi ayo pergi.

70 Pertanyaan Wawancara Javascript


Pertanyaan:
1. Apa perbedaan antara nol dan tidak terdefinisi?
2. Untuk apa operator && digunakan?
3. Untuk apa operator "||" digunakan?
4. Apakah menggunakan unary plus (+ operator) cara tercepat untuk mengkonversi string ke angka?
5. Apa itu DOM?
6. Apa itu Propogasi Acara?
7. Apa itu Event Bubbling?
8. Apa yang dimaksud dengan Pengambilan Acara?
9. Apa perbedaan antara metode event.preventDefault () dan event.stopPropagation ()?
10. Bagaimana cara belajar menggunakan metode event.preventDefault ()?
11. Mengapa obj.someprop.x menyebabkan kesalahan?
12. Apa itu target acara atau elemen target (event.target)?
13. (event.currentTarget)?
14. "==" "==="?
15. false?
16. "!!"?
17. ?
18. (Hoisting)?
19. (Scope)?
20. (Closures)?
21. JS ?
22. , ?
23. «use strict»?
24. this?
25. ?
26. IIFE?
27. Function.prototype.apply?
28. Function.prototype.call?
29. call apply?
30. Function.prototype.bind?
31. JS ?
32. (Higher Order Functions)?
33. JS (First-class Objects)?
34. Array.prototype.map?
35. Array.prototype.filter?
36. Array.prototype.reduce?
37. arguments?
38. , ?
39. b ?
40. ECMAScript?
41. JS ES6 ECMAScript2015?
42. «var», «let» «const»?
43. (Arrow Functions)?
44. (Classes)?
45. (Template Literals)?
46. (Object Destructuring)?
47. (Modules)?
48. Set?
49. (Callback Function)?
50. (Promises)?
51. async/await?
52. spread- rest-?
53. (Default Parameters)?
54. (Wrapper Objects)?
55. (Implicit and Explicit Coercion)?
56. NaN? , NaN?
57. , ?
58. , , ( "%")?
59. ?
60. AJAX?
61. JS ?
62. Object.freeze Object.seal?
63. «in» hasOwnProperty?
64. Apa teknik bekerja dengan kode asinkron di JS yang Anda tahu?
65. Apa perbedaan antara fungsi normal dan ekspresi fungsional?
66. Bagaimana cara memanggil fungsi di JS?
67. Apa itu menghafal atau menghafal?
68. Bagaimana Anda menerapkan fungsi bantu menghafal?
69. Mengapa typeof null mengembalikan objek? Bagaimana cara memeriksa apakah suatu nilai nol?
70. Untuk apa kata kunci "baru" digunakan?

1. Apa perbedaan antara null dan undefined?


Untuk memulai, mari kita bicara tentang kesamaan mereka.

Pertama, mereka milik 7 "primitif" JS (tipe primitif):

let primitiveTypes = ['string', 'number', 'null', 'undefined', 'boolean', 'symbol', 'bigint']

Kedua, mereka adalah nilai yang salah, yaitu hasil dari mengubahnya menjadi boolean menggunakan Boolean () atau operator "!!" salah:

console.log(!!null) // false
console.log(!!undefined) // false

console.log(Boolean(null)) // false
console.log(Boolean(undefined)) // false

Oke, sekarang tentang perbedaannya.

undefined adalah nilai default:
  • variabel yang tidak diberi nilai, mis. variabel yang dinyatakan tetapi tidak diinisialisasi;
  • fungsi yang tidak mengembalikan apa pun secara eksplisit, misalnya, console.log (1);
  • properti objek tidak ada.

Dalam kasus ini, mesin JS menetapkan nilai menjadi tidak terdefinisi.

let _thisIsUndefined
const doNothing = () => {}
const someObj = {
    a: 'ay',
    b: 'bee',
    c: 'si'
}
console.log(_thisIsUndefined) // undefined
console.log(doNothing()) // undefined
console.log(someObj['d']) // undefined

null adalah "nilai tanpa nilai". null adalah nilai yang diberikan ke variabel secara eksplisit. Pada contoh di bawah ini, kita mendapatkan null ketika metode fs.readFile bekerja tanpa kesalahan:

fs.readFile('path/to/file', (e, data) => {
    console.log(e) //    null
if(e) {
    console.log(e)
}
    console.log(data)
})

Saat membandingkan nol dan tidak terdefinisi, kami menjadi benar ketika menggunakan operator "==", dan false ketika menggunakan operator "===". Tentang mengapa ini terjadi, lihat di bawah.

console.log(null == undefined) // true
console.log(null === undefined) // false

2. Untuk apa operator && digunakan?


Operator && (logis dan) menemukan dan mengembalikan nilai false pertama atau operan terakhir ketika semua nilai benar. Ini menggunakan korsleting untuk menghindari biaya yang tidak perlu:

console.log(false && 1 && []) // false
console.log(' ' && true && 5) // 5

Dengan pernyataan if:

const router: Router = Router()

router.get('/endpoint', (req: Request, res: Response) => {
    let conMobile: PoolConnection
    try {
        //    
    } catch (e) {
        if (conMobile) {
            conMobile.release()
        }
    }
})

Hal yang sama dengan operator &&:

const router: Router = Router()

router.get('/endpoint', (req: Request, res: Response) => {
    let conMobile: PoolConnection
    try {
        //    
    } catch (e) {
        conMobile && conMobile.release()
    }
})

3. Untuk apa operator "||" digunakan?


Operator "||" (boolean atau) menemukan dan mengembalikan nilai true pertama. Itu juga menggunakan arus pendek. Operator ini digunakan untuk menetapkan parameter default dalam fungsi-fungsi sebelum parameter standar distandarisasi dalam ES6.

console.log(null || 1 || undefined) // 1

function logName(name) {
    let n = name || Mark
    console.log(n)
}

logName() // Mark

4. Apakah menggunakan unary plus (+ operator) cara tercepat untuk mengkonversi string ke angka?


Menurut MDN , operator + memang merupakan cara tercepat untuk mengonversi string menjadi angka, karena ia tidak melakukan operasi apa pun pada nilai yang merupakan angka.

5. Apa itu DOM?


DOM atau Document Object Model adalah antarmuka pemrograman aplikasi (API) untuk bekerja dengan dokumen HTML dan XML. Saat browser pertama kali membaca ("parses") dokumen HTML, ia membentuk objek besar, objek sangat besar berdasarkan pada dokumen - DOM. DOM adalah struktur pohon (pohon dokumen). DOM digunakan untuk berinteraksi dan mengubah struktur DOM itu sendiri atau elemen dan node individualnya.

Katakanlah kita memiliki HTML ini:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document Object Model</title>
</head>

<body>
    <div>
        <p>
            <span></span>
        </p>
        <label></label>
        <input>
    </div>
</body>

</html>

DOM HTML ini terlihat seperti ini:



Di JS, DOM diwakili oleh objek Dokumen. Objek Dokumen memiliki sejumlah besar metode untuk bekerja dengan elemen, pembuatannya, modifikasi, penghapusan, dll.

6. Apa itu Propagasi Acara?


Ketika suatu peristiwa terjadi dalam elemen DOM, itu sebenarnya terjadi tidak hanya di dalamnya. Acara "merambat" dari objek Window ke elemen yang menyebutnya (event.target). Selain itu, peristiwa tersebut secara berurutan meresap (mempengaruhi) semua leluhur dari elemen target. Perambatan acara memiliki tiga tahap atau fase:
  1. Fase perendaman (tangkapan, intersepsi) - suatu peristiwa terjadi di objek Window dan turun ke target acara melalui semua leluhurnya.
  2. Fase target adalah saat acara mencapai elemen target.
  3. Fase naik - suatu peristiwa muncul dari event.target, secara berurutan melewati semua leluhurnya dan mencapai objek Window.



Baca lebih lanjut tentang distribusi acara di sini dan di sini .

7. Apa itu popup acara?


Ketika suatu peristiwa terjadi dalam elemen DOM, itu mempengaruhi tidak hanya elemen ini. Suatu peristiwa "muncul" (seperti gelembung udara di dalam air), berpindah dari elemen yang menyebabkan peristiwa (event.target) ke induknya, kemudian naik lebih tinggi lagi, ke induk dari induk elemen, hingga mencapai objek Window.

Katakanlah kita memiliki markup ini:

<div class="grandparent">
    <div class="parent">
        <div class="child">1</div>
    </div>
</div>

Dan JS seperti itu:

function addEvent(el, event, callback, isCapture = false) {
    if (!el || !event || !callback || typeof callback !== 'function') return

    if (typeof el === 'string') {
        el = document.querySelector(el)
    }
    el.addEventListener(event, callback, isCapture)
}

addEvent(document, 'DOMContentLoaded', () => {
    const child = document.querySelector('.child')
    const parent = document.querySelector('.parent')
    const grandparent = document.querySelector('.grandparent')

    addEvent(child, 'click', function(e) {
        console.log('child')
    })

    addEvent(parent, 'click', function(e) {
        console.log('parent')
    })

    addEvent(grandparent, 'click', function(e) {
        console.log('grandparent')
    })

    addEvent('html', 'click', function(e) {
        console.log('html')
    })

    addEvent(document, 'click', function(e) {
        console.log('document')
    })

    addEvent(window, 'click', function(e) {
        console.log('window')
    })
})

Metode addEventListener memiliki parameter opsional ketiga - useCapture. Ketika nilainya salah (default), acara dimulai dengan fase pendakian. Ketika nilainya benar, acara dimulai dengan fase perendaman (untuk "pendengar" peristiwa yang melekat pada target acara, acara tersebut dalam fase target, dan bukan dalam fase perendaman atau pendakian. Acara dalam fase target dipicu oleh semua pendengar pada elemen dalam urutan. di mana mereka terdaftar terlepas dari parameter useCapture - kira-kira. Jika kita klik pada elemen turunan, konsol akan menampilkan: turunan, orangtua, kakek-nenek, html, dokumen, jendela. Inilah yang dimaksud dengan popup acara.

8. Apa itu acara perendaman?


Ketika suatu peristiwa terjadi dalam elemen DOM, itu terjadi tidak hanya di dalamnya. Pada fase perendaman, acara turun dari objek Window ke target acara melalui semua leluhurnya.

Markup:

<div class="grandparent">
    <div class="parent">
        <div class="child">1</div>
    </div>
</div>

JS:

function addEvent(el, event, callback, isCapture = false) {
    if (!el || !event || !callback || typeof callback !== 'function') return

    if (typeof el === 'string') {
        el = document.querySelector(el);
    }
    el.addEventListener(event, callback, isCapture)
}

addEvent(document, 'DOMContentLoaded', () => {
    const child = document.querySelector('.child')
    const parent = document.querySelector('.parent')
    const grandparent = document.querySelector('.grandparent')

    addEvent(child, 'click', function(e) {
        console.log('child');
    }, true)

    addEvent(parent, 'click', function(e) {
        console.log('parent')
    }, true)

    addEvent(grandparent, 'click', function(e) {
        console.log('grandparent')
    }, true)

    addEvent('html', 'click', function(e) {
        console.log('html')
    }, true)

    addEvent(document, 'click', function(e) {
        console.log('document')
    }, true)

    addEvent(window, 'click', function(e) {
        console.log('window')
    }, true)
})

Metode addEventListener memiliki parameter opsional ketiga - useCapture. Ketika nilainya salah (default), acara dimulai dengan fase pendakian. Ketika nilainya benar, acara dimulai dengan fase menyelam. Jika kita klik pada elemen anak, kita akan melihat yang berikut di konsol: jendela, dokumen, html, kakek-nenek, orang tua, anak. Ini adalah perendaman acara.

9. Apa perbedaan antara metode event.preventDefault () dan event.stopPropagation ()?


Metode event.preventDefault () menonaktifkan perilaku default suatu elemen. Jika Anda menggunakan metode ini di elemen formulir, itu akan mencegah formulir mengirimkan. Jika Anda menggunakannya dalam menu konteks, menu konteks akan dinonaktifkan (metode ini sering digunakan pada tombol untuk mendefinisikan kembali keyboard, misalnya, saat membuat pemutar musik / video atau editor teks - kira-kira. Metode event.stopPropagation () menonaktifkan propagasi acara (pendakian atau pencelupannya).

10. Bagaimana cara belajar menggunakan metode event.preventDefault ()?


Untuk melakukan ini, kita dapat menggunakan properti event.defaulPrevented, yang mengembalikan boolean yang berfungsi sebagai indikator aplikasi ke elemen metode event.preventDefault.

11. Mengapa obj.someprop.x menyebabkan kesalahan?



const obj = {}
console.log(obj.someprop.x)

Jawabannya jelas: kami mencoba mengakses properti x properti someprop, yang tidak ditentukan. obj .__ proto __.__ proto = null, sehingga mengembalikan tidak terdefinisi, dan undefined tidak memiliki properti x.

12. Apa itu target acara atau elemen target (event.target)?


Dengan kata sederhana, event.target adalah elemen di mana peristiwa itu terjadi, atau elemen yang mengangkat peristiwa.

Kami memiliki markup berikut:

<div onclick="clickFunc(event)" style="text-align: center; margin: 15px;
border: 1px solid red; border-radius: 3px;">
    <div style="margin: 25px; border: 1px solid royalblue; border-radius: 3px;">
        <div style="margin: 25px; border: 1px solid skyblue; border-radius: 3px;">
            <button style="margin: 10px">
                Button
            </button>
        </div>
    </div>
</div>

Dan JS sederhana seperti itu:

function clickFunc(event) {
    console.log(event.target)
}

Kami melampirkan "pendengar" ke div luar. Namun, jika kita mengklik tombol, kita mendapatkan tata letak tombol ini di konsol. Ini memungkinkan kita untuk menyimpulkan bahwa elemen yang menyebabkan peristiwa adalah tombol itu sendiri, dan bukan divs eksternal atau internal.

13. Apa tujuan acara saat ini (event.currentTarget)?


Event.currentTarget adalah elemen yang dilampirkan pendengar acara.

Markup serupa:

<div onclick="clickFunc(event)" style="text-align: center;margin:15px;
border:1px solid red;border-radius:3px;">
    <div style="margin: 25px; border:1px solid royalblue;border-radius:3px;">
        <div style="margin:25px;border:1px solid skyblue;border-radius:3px;">
            <button style="margin:10px">
                Button
            </button>
        </div>
    </div>
</div>

Dan JS yang sedikit dimodifikasi:

function clickFunc(event) {
    console.log(event.currentTarget)
}

Kami melampirkan pendengar ke div luar. Di mana pun kita mengklik, apakah itu tombol atau salah satu div internal, di konsol kita selalu mendapatkan tata letak div eksternal. Ini memungkinkan kita untuk menyimpulkan bahwa event.currentTarget adalah elemen yang dilampirkan pendengar acara.

14. Apa perbedaan antara operator "==" dan "==="?


Perbedaan antara operator == (kesetaraan abstrak atau tidak ketat) dan operator === (kesetaraan ketat) adalah bahwa yang pertama membandingkan nilai setelah dikonversi atau dilemparkan ke satu jenis (Koersi), dan yang kedua - tanpa konversi seperti itu .

Mari menggali lebih dalam. Dan pertama, mari kita bicara tentang transformasi.

Konversi adalah proses memberikan nilai ke tipe lain, atau lebih tepatnya, proses casting nilai yang dibandingkan dengan satu tipe. Saat membandingkan, operator "==" menghasilkan apa yang disebut perbandingan implisit. Operator "==" melakukan beberapa operasi sebelum membandingkan dua nilai.

Misalkan kita membandingkan x dan y.

Algoritma adalah sebagai berikut:

  1. Jika x dan y memiliki tipe yang sama, perbandingan dilakukan menggunakan operator "===".
  2. x = null y = undefined true.
  3. x = undefined y = null true.
  4. x = , y = , x == toNumber(y) ( y ).
  5. x = , y = , toNumber(x) == y ( x ).
  6. x = , toNumber(x) == y.
  7. y = , x == toNumber(y).
  8. x = , , y = , x == toPrimitive(y) ( y ).
  9. x = , y = , , toPrimitive(x) == y.
  10. false.

Ingat: untuk melemparkan objek ke "primitif", metode toPrimitive pertama menggunakan metode valueOf, kemudian metode toString.

Contoh:



Semua contoh mengembalikan true.

Contoh pertama adalah kondisi pertama dari algoritma.
Contoh kedua adalah kondisi keempat.
Yang ketiga adalah yang kedua.
Yang keempat adalah yang ketujuh.
Kelima - kedelapan.
Dan yang terakhir adalah yang kesepuluh.



Jika kita menggunakan operator "===", semua contoh kecuali yang pertama akan mengembalikan false, karena nilai dalam contoh ini dari tipe yang berbeda.

15. Mengapa hasil membandingkan dua benda serupa itu salah?


let a = {
    a: 1
}
let b = {
    a: 1
}
let c = a

console.log(a === b) // false
console.log(a === c) // true ...

Dalam JS, objek dan primitif dibandingkan secara berbeda. Primitif dibandingkan dengan nilai. Objek - dengan referensi atau alamat di memori tempat variabel disimpan. Inilah sebabnya mengapa console.log pertama mengembalikan false dan yang kedua mengembalikan true. Variabel "a" dan "c" merujuk ke objek yang sama, sedangkan variabel "a" dan "b" merujuk ke objek yang berbeda dengan properti dan nilai yang sama.

16. Untuk apa operator "!!" digunakan?


Operator "!!" (negasi ganda) menuntun nilai ke kanannya ke nilai logis.

console.log(!!null) // false
console.log(!!undefined) // false
console.log(!!'') // false
console.log(!!0) // false
console.log(!!NaN) // false
console.log(!!' ') // true
console.log(!!{}) // true
console.log(!![]) // true
console.log(!!1) // true
console.log(!![].length) // false

17. Bagaimana cara menulis banyak ekspresi pada satu baris?


Untuk ini kita bisa menggunakan operator "," (koma). Operator ini "bergerak" dari kiri ke kanan dan mengembalikan nilai ekspresi atau operan terakhir.

let x = 5

x = (x++, x = addFive(x), x *= 2, x -= 5, x += 10)

function addFive(num) {
    return num + 5
}

Jika kita mencetak nilai x ke konsol, kita mendapatkan 27. Pertama, kita meningkatkan nilai x per satu (x = 6). Kemudian kita memanggil fungsi addFive () dengan parameter 6, yang kita tambahkan 5 (x = 11). Setelah itu, kita mengalikan nilai x dengan 2 (x = 22). Kemudian kurangi 5 (x = 17). Dan akhirnya, tambahkan 10 (x = 27).

18. Apa yang mengangkat?


Angkat adalah istilah yang menggambarkan munculnya variabel atau fungsi dalam lingkup global atau fungsional.

Untuk memahami apa itu Hoisting, Anda perlu memahami apa konteks eksekusi itu.

Konteks eksekusi adalah lingkungan di mana kode dieksekusi. Konteks eksekusi memiliki dua fase - kompilasi dan eksekusi itu sendiri.

Kompilasi. Dalam fase ini, ekspresi fungsional dan variabel dinyatakan menggunakan kata kunci "var" dengan nilai yang tidak ditentukan naik ke bagian paling atas dari lingkup global (atau fungsional) (seolah-olah pindah ke awal kode kita. Ini menjelaskan mengapa kita dapat memanggil fungsi sebelum mereka pengumuman - kira-kira.

Performa. Dalam fase ini, variabel diberi nilai, dan fungsi (atau metode objek) dipanggil atau dieksekusi.

Ingat: hanya ekspresi dan variabel fungsional yang dideklarasikan menggunakan kata kunci "var" yang dinaikkan. Fungsi biasa dan fungsi panah, serta variabel yang dideklarasikan menggunakan kata kunci "let" dan "const", tidak dinaikkan.

Misalkan kita memiliki kode seperti ini:

console.log(y)
y = 1
console.log(y)
console.log(greet('Mark'))

function greet(name) {
    return 'Hello ' + name + '!'
}

var y

Kami mendapatkan undefined, 1 dan 'Hello Mark!'.

Beginilah fase kompilasi terlihat:

function greet(name) {
    return 'Hello ' + name + '!'
}

var y //  undefined

//    

//    
/*
console.log(y)
y = 1
console.log(y)
console.log(greet('Mark'))
*/

Setelah fase kompilasi selesai, fase eksekusi dimulai ketika variabel diberi nilai dan fungsi dipanggil.

Lebih lanjut tentang Mengangkat dapat ditemukan di sini .

19. Apa itu ruang lingkup?


Lingkup adalah tempat di mana (atau dari mana) kita memiliki akses ke variabel atau fungsi. JS kami memiliki tiga jenis cakupan: global, fungsional dan blok (ES6).

Cakupan global - variabel dan fungsi yang dinyatakan dalam namespace global memiliki cakupan global dan dapat diakses dari mana saja dalam kode.

//   
var g = 'global'

function globalFunc() {
    function innerFunc() {
        console.log(g) //     g,    
    }
    innerFunc()
}

Cakupan fungsional (lingkup fungsi) - variabel, fungsi, dan parameter yang dideklarasikan di dalam fungsi hanya tersedia di dalam fungsi ini.

function myFavouriteFunc(a) {
    if (true) {
        var b = 'Hello ' + a
    }
    return b
}
myFavouriteFunc('World')

console.log(a) // Uncaught ReferenceError: a is not defined
console.log(b) //  

Cakupan blok - variabel (dideklarasikan menggunakan kata kunci "let" dan "const") di dalam blok ({}) hanya tersedia di dalamnya.

function testBlock() {
    if (true) {
        let z = 5
    }
    return z
}

testBlock() // Uncaught ReferenceError: z is not defined

Lingkup juga merupakan seperangkat aturan yang digunakan untuk mencari variabel. Jika variabel tidak ada dalam cakupan saat ini, pencariannya dilakukan lebih tinggi dalam visibilitas eksternal dari cakupan saat ini. Jika tidak ada variabel dalam lingkup eksternal, pencariannya akan berlanjut hingga lingkup global. Jika variabel ditemukan dalam lingkup global, pencarian berhenti, jika tidak, pengecualian dilemparkan. Pencarian dilakukan oleh yang paling dekat dengan area visibilitas saat ini dan berhenti dengan menemukan variabel. Ini disebut Rantai Lingkup.

//   
//    ->    ->   

//   
var variable1 = 'Comrades'
var variable2 = 'Sayonara'

function outer() {
    //   
    var variable1 = 'World'

    function inner() {
        //   
        var variable2 = 'Hello'
        console.log(variable2 + ' ' + variable1)
    }
    inner()
}
outer()
//    'Hello World',
//   variable2 = 'Hello'  variable1 = 'World'  
//     



20. Apa itu penutupan (Penutupan)?


Ini mungkin pertanyaan paling sulit dari daftar. Saya akan mencoba menjelaskan bagaimana saya memahami penutupan.

Sebenarnya, closure adalah kemampuan suatu fungsi untuk membuat, pada saat penciptaan, menghafal referensi ke variabel dan parameter yang terletak di lingkup saat ini, dalam lingkup fungsi induk, dalam lingkup fungsi induk dari induk, dan seterusnya ke lingkup global menggunakan rantai cakupan. Biasanya, ruang lingkup ditentukan ketika suatu fungsi dibuat.

Contohnya adalah cara yang bagus untuk menjelaskan penutupan:

//   
var globalVar = 'abc'

function a() {
    //   
    console.log(globalVar)
}

a() // 'abc'
//   
//    a ->   

Dalam contoh ini, ketika kami mendeklarasikan suatu fungsi, cakupan global adalah bagian dari penutupan.



Variabel "globalVar" tidak masalah dalam gambar, karena nilainya dapat berubah tergantung di mana dan kapan fungsi akan dipanggil. Tetapi dalam contoh di atas, globalVar akan memiliki nilai "abc".

Sekarang contohnya lebih rumit:

var globalVar = 'global'
var outerVar = 'outer'

function outerFunc(outerParam) {
    function innerFunc(innerParam) {
        console.log(globalVar, outerParam, innerParam)
    }
    return innerFunc
}

const x = outerFunc(outerVar)
outerVar = 'outer-2'
globalVar = 'guess'
x('inner')



Hasilnya adalah "tebak luar dalam". Penjelasannya adalah ini: ketika kita memanggil fungsi outerFunc dan mengatur variabel "x" ke nilai yang dikembalikan oleh fungsi innerFunc, parameter "outerParam" sama dengan "luar". Terlepas dari kenyataan bahwa kami menetapkan variabel "outerVar" ke "outer-2", ini terjadi setelah memanggil fungsi outerFunc, yang "berhasil" menemukan nilai variabel "outerVar" dalam rantai lingkup, nilai ini adalah "luar". Ketika kita memanggil "x", yang merujuk ke innerFunc, nilai "innerParam" adalah "inner", karena kita meneruskan nilai ini sebagai parameter saat memanggil "x". globalVar memiliki nilai "tebak" karena kami menetapkan nilai itu sebelum memanggil "x".

Contoh dari kesalahpahaman tentang sirkuit.

const arrFunc = []
for (var i = 0; i < 5; i++) {
    arrFunc.push(function() {
        return i
    })
}
console.log(i) // 5

for (let i = 0; i < arrFunc.length; i++) {
    console.log(arrFunc[i]()) //  5
}

Kode ini tidak berfungsi seperti yang diharapkan. Mendeklarasikan variabel menggunakan kata kunci var menjadikan variabel ini mendunia. Setelah menambahkan fungsi ke array arrFunc, nilai variabel global "i" menjadi "5". Karena itu, ketika kita memanggil fungsi, ia mengembalikan nilai variabel global "i". Penutupan menyimpan referensi ke variabel, bukan nilainya pada waktu pembuatan. Masalah ini dapat diselesaikan dengan menggunakan IIFE atau dengan mendeklarasikan variabel menggunakan kata kunci "let".

Baca lebih lanjut tentang penutupan di sini dan di sini .

21. Nilai apa dalam JS yang salah?


const falsyValues = ['', 0, null, undefined, NaN, false]

False adalah nilai yang konversinya ke nilai boolean salah.

22. Bagaimana cara memeriksa apakah suatu nilai salah?


Gunakan fungsi Boolean atau operator "!!" (dua kali tidak).

23. Untuk apa penggunaan arahan ketat?


"Gunakan ketat" adalah arahan ES5 yang memaksa semua kode kami atau kode fungsi individu untuk dijalankan dalam mode ketat. Mode ketat memperkenalkan beberapa batasan pada penulisan kode, sehingga menghindari kesalahan pada tahap awal.

Berikut batasan mode ketat.

Anda tidak dapat menetapkan nilai atau mengakses variabel yang tidak dideklarasikan:

function returnY() {
    'use strict'
    y = 123
    return y
}
returnY() // Uncaught ReferenceError: y is not defined

Dilarang menetapkan nilai global untuk variabel read-only atau write-only:

'use strict'
var NaN = NaN // Uncaught TypeError: Cannot assign to read only property 'NaN' of object '#<Window>'
var undefined = undefined
var Infinity = 'and beyond'

Anda tidak dapat menghapus properti "undeletable" dari suatu objek:

'use strict'
const obj = {}

Object.defineProperties(obj, 'x', {
    value: 1
})

delete obj.x // Uncaught TypeError: Property description must be an object: x

Duplikasi parameter dilarang:

'use strict'

function someFunc(a, b, b, c) {} // Uncaught SyntaxError: Duplicate parameter name not allowed in this context

Anda tidak dapat membuat fungsi menggunakan fungsi eval:

'use strict'

eval('var x = 1')

console.log(x) // Uncaught ReferenceError: x is not defined

Nilai default untuk ini tidak ditentukan:

'use strict'

function showMeThis() {
    return this
}

showMeThis() // undefined

... dll.

24. Apa artinya ini?


Ini biasanya merujuk pada nilai objek yang sedang menjalankan atau memanggil fungsi. "Saat ini" berarti bahwa nilai ini bervariasi tergantung pada konteks eksekusi, tempat kami menggunakannya.

const carDetails = {
    name: 'Ford Mustang',
    yearBought: 2005,
    getName() {
        return this.name
    }
    isRegistered: true
}

console.log(carDetails.getName()) // Ford Mustang

Dalam kasus ini, metode getName mengembalikan this.name, dan ini merujuk ke carDetails, objek di mana getName dijalankan, yang merupakan "pemilik" -nya.

Tambahkan tiga baris setelah console.log:

var name = 'Ford Ranger'
var getCarName = carDetails.getName

console.log(getCarName()) // Ford Ranger

Log console.log kedua menghasilkan Ford Ranger, dan ini aneh. Alasan untuk perilaku ini adalah bahwa "pemilik" getCarName adalah objek jendela. Variabel yang dideklarasikan dengan kata kunci var dalam lingkup global ditulis ke properti objek window. ini dalam lingkup global mengacu pada objek jendela (kecuali itu mode ketat).

console.log(getCarName === window.getCarName) // true
console.log(getCarName === this.getCarName) // true

Dalam contoh ini, ini dan jendela merujuk ke objek yang sama.

Salah satu cara untuk mengatasi masalah ini adalah dengan menggunakan panggilan atau menerapkan metode:

console.log(getCarName.apply(carDetails)) // Ford Mustang
console.log(getCarName.call(carDetails)) // Ford Mustang

Panggil dan terapkan, ambil sebagai argumen pertama objek yang akan menjadi nilai dari ini di dalam fungsi.

Dalam IIFE, fungsi yang dibuat dalam lingkup global, fungsi anonim, dan fungsi internal metode objek, nilai default untuk ini adalah objek jendela.

(function() {
    console.log(this)
})() // window

function iHateThis() {
    console.log(this)
}
iHateThis() // window

const myFavouriteObj = {
    guessThis() {
        function getName() {
            console.log(this.name)
        }
        getName()
    },
    name: 'Marko Polo',
    thisIsAnnoying(callback) {
        callback()
    }
}

myFavouriteObj.guessThis() // window
myFavouriteObj.thisIsAnnoying(function() {
    console.log(this) // window
})

Ada dua cara untuk mendapatkan Marko Polo.

Pertama, kita dapat menyimpan nilai ini dalam sebuah variabel:

const myFavoriteObj = {
    guessThis() {
        const self = this //   this   self
        function getName() {
            console.log(self.name)
        }
        getName()
    },
    name: 'Marko Polo',
    thisIsAnnoying(callback) {
        callback()
    }
}

Kedua, kita bisa menggunakan fungsi panah:

const myFavoriteObj = {
    guessThis() {
        const getName = () => {
            //   this   
            console.log(this.name)
        }
        getName()
    },
    name: 'Marko Polo',
    thisIsAnnoying(callback) {
        callback()
    }
}

Fungsi panah tidak memiliki nilai eigen ini. Mereka menyalin makna ini dari lingkungan leksikal eksternal.

25. Apa prototipe suatu objek?


Singkatnya, prototipe adalah rencana (diagram atau proyek) dari suatu objek. Ini digunakan sebagai fallback untuk properti dan metode yang ada di objek ini. Ini juga salah satu cara untuk bertukar properti dan fungsionalitas antara objek. Ini adalah konsep dasar pewarisan prototipe di JS.

const o = {}
console.log(o.toString()) // [object Object]

Meskipun objek "o" tidak memiliki properti toString, mengakses properti ini tidak menyebabkan kesalahan. Jika properti tertentu tidak ada dalam objek, pencariannya dilakukan pertama kali dalam prototipe objek, kemudian dalam prototipe prototipe objek, dan seterusnya hingga properti ditemukan. Ini disebut rantai prototipe. Di bagian atas rantai prototipe adalah Object.prototype.

console.log(o.toString === Object.prototype.toString) // true

Baca lebih lanjut tentang prototipe dan warisan di sini dan di sini .

26. Apa itu IIFE?


Ekspresi Fungsi IIFE atau Segera Diminta adalah fungsi yang dipanggil atau dieksekusi segera setelah pembuatan atau deklarasi. Untuk membuat IIFE, Anda perlu membungkus fungsi dalam tanda kurung (operator pengelompokan), mengubahnya menjadi ekspresi, dan kemudian memanggilnya menggunakan tanda kurung lain. Ini terlihat seperti ini: (function () {}) ().

(function( ) { }( ))

(function( ) { })( )

(function named(params) { })( )

(( ) => { })

(function(global) { })(window)

const utility = (function( ) {
    return {
        // 
    }
})

Semua contoh ini valid. Contoh kedua terakhir menunjukkan bahwa kami dapat meneruskan parameter ke IIFE. Contoh terakhir menunjukkan bahwa kita dapat menyimpan hasil IIFE dalam suatu variabel.

Penggunaan IIFE terbaik adalah untuk melakukan fungsi konfigurasi inisialisasi dan mencegah konflik nama dengan variabel lain dalam lingkup global (polusi ruang nama global). Kami memberi contoh.

<script src="https://cdnurl.com/somelibrary.js"></script>

Kami memiliki tautan ke perpustakaan somelibrary.js yang menyediakan beberapa fungsi global yang dapat kami gunakan dalam kode kami, tetapi ada dua metode di perpustakaan ini, createGraph dan drawGraph, yang tidak kami gunakan karena mengandung kesalahan. Dan kami ingin mengimplementasikan fungsi-fungsi ini sendiri.

Salah satu cara untuk mengatasi masalah ini adalah dengan mengubah struktur skrip kami:

<script src="https://cdnurl.com/somelibrary.js"></script>
<script>
    function createGraph() {
        // 
    }

    function drawGraph() {
        // 
    }
</script>

Jadi, kami mendefinisikan kembali metode yang disediakan oleh perpustakaan.

Cara kedua adalah mengubah nama fungsi kita:

<script src="https://cdnurl.com/somelibrary.js"></script>
<script>
    function myCreateGraph() {
        // 
    }

    function myDrawGraph() {
        // 
    }
</script>

Cara ketiga adalah menggunakan IIFE:

<script>
    const graphUtility = (function() {
        function createGraph() {
            // 
        }

        function drawGraph() {
            // 
        }
        return {
            createGraph,
            drawGraph
        }
    })
</script>

Dalam contoh ini, kami membuat variabel utilitas yang berisi hasil IIFE, yang mengembalikan objek yang berisi metode createGraph dan drawGraph.

Berikut adalah masalah lain yang dapat diselesaikan dengan IIFE:

val li = document.querySelectorAll('.list-group > li')
for (var i - 0, len = li.length; i < len; i++) {
    li[i].addEventListener('click', function(e) {
        console.log(i)
    })
}

Misalkan kita memiliki elemen ul dengan kelas grup daftar yang berisi 5 elemen anak li. Dan kami ingin menampilkan nilai "i" di konsol ketika mengklik "li" yang terpisah. Namun, sebagai gantinya, konsol selalu menampilkan 5. Kesalahan adalah semua kesalahan.

Salah satu solusinya adalah IIFE:

var li = document.querySelectorAll('.list-group > li')
for (var i = 0, len = li.length; i < len; i++) {
    (function(currentIndex) {
        li[currentIndex].addEventListener('click', function(e) {
            console.log(currentIndex)
        })
    })(i)
}

Alasan kode ini berfungsi sebagaimana dimaksud adalah karena IIFE membuat lingkup baru di setiap iterasi, dan kami menulis nilai "i" di currentIndex.

27. Apa metode Function.prototype.apply digunakan untuk?


Terapkan digunakan untuk mengikat objek tertentu dengan nilai fungsi yang disebut ini.

const details = {
    message: 'Hello World!'
}

function getMessage() {
    return this.message
}

getMessage.apply(details) // Hello World!

Metode ini mirip dengan Function.prototype.call. Satu-satunya perbedaan adalah bahwa dalam menerapkan, argumen dilewatkan sebagai array.

const person = {
    name: 'Marko Polo'
}

function greeting(greetingMessage) {
    return `${greetingMessage} ${this.name}`
}

greeting.apply(person, ['Hello']) // Hello Marko Polo

28. Untuk apa metode function.prototype.call digunakan?


Panggilan digunakan untuk mengikat objek tertentu dengan nilai fungsi ini dipanggil.

const details = {
    message: 'Hello World!'
};

function getMessage() {
    return this.message;
}

getMessage.call(details); // Hello World!

Metode ini mirip dengan Function.prototype.apply. Perbedaannya adalah bahwa dalam argumen panggilan disahkan dipisahkan oleh koma.

const person = {
    name: 'Marko Polo'
};

function greeting(greetingMessage) {
    return `${greetingMessage} ${this.name}`;
}

greeting.call(person, 'Hello'); // Hello Marko Polo

29. Apa perbedaan antara metode panggilan dan terapkan?


Perbedaan antara panggilan dan berlaku adalah bagaimana kita memberikan argumen dalam fungsi yang dipanggil. Dalam berlaku, argumen dilewatkan sebagai array, dalam panggilan, dipisahkan dengan koma.

const obj1 = {
    result: 0
}

const obj2 = {
    result: 0
}

function reduceAdd() {
    let result = 0
    for (let i = 0, len = arguments.length; i < len; i++) {
        result += arguments[i]
    }
    this.result = result
}

reduceAdd.apply(obj1, [1, 2, 3, 4, 5]) // 15
reduceAdd.call(obj2, 1, 2, 3, 4, 5) // 15

30. Untuk apa metode function.prototype.bind digunakan?


Bind mengembalikan fungsi baru yang nilainya adalah objek yang ditentukan sebagai parameter pertama. Tidak seperti bind, panggil dan terapkan fungsi panggil segera.

import React from 'react'

class MyComponent extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            value: ''
        }
        this.handleChange = this.handleChange.bind(this)
        //   handleChange   MyComponent
    }

    handleChange(e) {
        // 
    }

    render() {
        return ( < >
            <
            input type = {
                this.props.type
            }
            value = {
                this.state.value
            }
            onChange = {
                this.handleChange
            }
            /> </ >
        )
    }
}

31. Apa itu pemrograman fungsional dan fitur JS apa yang memungkinkan kami untuk membicarakannya sebagai bahasa pemrograman fungsional?


Pemrograman fungsional adalah konsep pemrograman deklaratif atau contoh (pola) dari bagaimana aplikasi dibangun, bagaimana fungsi yang mengandung ekspresi yang menghitung nilai tanpa mengubah argumen yang diteruskan ke mereka digunakan.

Objek Array berisi peta, filter, dan mengurangi metode, yang merupakan fungsi paling terkenal di dunia pemrograman fungsional karena kegunaannya dan juga karena mereka tidak memodifikasi array, yang membuat fungsi-fungsi ini "bersih". JS juga memiliki fungsi penutupan dan tingkat tinggi yang merupakan karakteristik dari bahasa pemrograman fungsional.

Metode peta mengembalikan array baru dengan hasil panggilan balik untuk setiap elemen array:

const words = ['Functional', 'Procedural', 'Object-Oriented']

const wordsLength = words.map(word => word.length)

Metode filter membuat array baru dengan semua elemen yang memenuhi kondisi yang ditentukan dalam panggilan balik:

const data = {
    {
        name: 'Mark',
        isRegistered: true
    } {
        name: 'Mary',
        isRegistered: false
    } {
        name: 'Mae',
        isRegistered: true
    }
}

const registeredUsers = data.filter(user => user.isRegistered)

Metode pengurangan melakukan callback sekali untuk setiap elemen array, dengan pengecualian void, mengambil empat argumen: nilai awal (atau nilai dari callback sebelumnya), nilai elemen saat ini, indeks saat ini, dan array yang diulang:

const strs = ['I', ' ', 'am', ' ', 'Iron', ' ', 'Man']

const result = strs.reduce((acc, currentStr) => acc + str, '')

32. Apa Fungsi Orde Tinggi?


Fungsi tingkat tinggi adalah fungsi yang mengembalikan fungsi lain atau menerima fungsi lain sebagai argumen.

function higherOrderFunction(param, callback) {
    return callback(param)
}

33. Mengapa fungsi dalam JS disebut Objek kelas?


Fungsi disebut objek kelas satu karena mereka diproses sama seperti nilai lain di JS. Mereka dapat ditugaskan ke variabel, menjadi properti dari objek (metode), elemen array, argumen ke fungsi lain, nilai yang dikembalikan oleh fungsi. Satu-satunya perbedaan antara fungsi dan nilai lain di JS adalah bahwa fungsi tersebut dapat dieksekusi atau dipanggil.

34. Bagaimana Anda menerapkan metode Array.prototype.map?


function map(arr, mapCallback) {
    //   
    if (!Array.isArray(arr) || !arr.length || typeof mapCallback !== 'function') {
        return []
    } else {
        let result = []
        //         
        //       
        for (let i = 0, len = arr.length; i < len; i++) {
            result.push(mapCallback(arr[i], i, arr))
            //   mapCallback  result
        }
        return result
    }
}

Metode peta menciptakan array baru dengan hasil memanggil fungsi yang ditentukan untuk setiap elemen array.

35. Bagaimana Anda menerapkan metode Array.prototype.filter?


function filter(arr, filterCallback) {
    //   
    if (!Array.isArray(arr) || !arr.length || typeof filterCallback !== 'function') {
        return []
    } else {
        let result = []
        // ...
        for (let i = 0, len = arr.length; i < len; i++) {
            //      
            if (filterCallback(arr[i], i, arr)) {
                //  ,  ,  result
                result.push(arr[i])
            }
        }
        return result
    }
}

Metode filter menciptakan array baru dengan semua elemen yang lulus tes yang ditentukan dalam fungsi yang diteruskan.

36. Bagaimana Anda menerapkan metode Array.prototype.reduce?


function reduce(arr, reduceCallbak, initialValue) {
    // ..
    if (!Array.isArray(arr) || !arr.length || typeof filterCallback !== 'function') {
        return []
    } else {
        //        initialValue, 
        let hasInitialValue = initialValue !== undefined
        let value = hasInitialValue ? initialValue : arr[0]
        //      initialValue

        //    ,   1,       initialValue,   0,    
        for (let i = hasInitialValue ? 0 : 1, len = arr.length; i < len; i++) {
            //         reduceCallback 
            value = reduceCallback(value, arr[i], i, arr)
        }
        return value
    }
}

Metode pengurangan menerapkan fungsi peredam ke setiap elemen array (dari kiri ke kanan), mengembalikan satu nilai yang dihasilkan.

37. Apa itu objek argumen?


Argumen adalah kumpulan argumen yang diteruskan ke suatu fungsi. Ini adalah objek mirip array, memiliki properti panjang, kita dapat mengakses nilai tertentu menggunakan argumen [i], tetapi tidak memiliki metode forEach, kurangi, filter, dan map. Ini memungkinkan Anda untuk mengetahui jumlah parameter fungsi.

Anda bisa mengonversi argumen menjadi array menggunakan Array.prototype.slice:

Array.prototype.slice.call(arguments)

Ingat: dalam fungsi panah, objek argumen tidak berfungsi.

function one() {
    return arguments
}
const two = function() {
    return arguments
}
const three = function three({
    return arguments
})
const four = () => arguments

four() // arguments is not defined

Memanggil empat fungsi menghasilkan ReferenceError: argumen tidak didefinisikan sebagai kesalahan. Masalah ini dapat diselesaikan menggunakan pernyataan lainnya:

const four = (...args) => args

Ini akan secara otomatis menempatkan semua parameter dalam array.

38. Bagaimana cara membuat objek yang tidak memiliki prototipe?


Ini dapat dilakukan dengan menggunakan Object.create:

const o1 = {}
console.log(o1.toString) // [object Object]

const o2 = Object.create(null) //      Object-create  -
//    -,   null
console.log(o2.toString) // o2.toString is not a function

39. Mengapa dalam kode yang disajikan apakah variabel b menjadi global ketika fungsi dipanggil?



function myFunc(){
    let a = b = 0
}
myFunc()

Ini terjadi karena operator penugasan ("=") memiliki asosiatif tangan kanan, mis. memberikan nilai dari kanan ke kiri. Oleh karena itu, kode ini mengambil bentuk berikut:

function myFunc(){
    let a = (b = 0)
}
myFunc()

Pertama, nilai 0 ditugaskan ke variabel "b", yang tidak dideklarasikan. Mesin JS menjadikannya global. Nilai (0) yang dikembalikan oleh b = 0 kemudian ditetapkan ke variabel lokal “a”.

Masalah ini dapat diselesaikan dengan terlebih dahulu mendeklarasikan variabel lokal dan kemudian memberikan nilai kepada mereka:

function myFunc(){
    let a, b
    a = b = 0
}
myFunc()

40. Apa itu ECMAScript?


ECMAScript adalah spesifikasi, bahasa pemrograman scripting standar, ini adalah dasar dari JS, jadi setiap perubahan pada ECMAScript dicerminkan dalam JS.

Versi terbaru dari spesifikasi ECMA-262 dapat dilihat di sini .

41. Apa hal baru yang dibawa ES6 atau ECMAScript2015 ke JS?


  • Fungsi Panah
  • Kelas
  • String Templat.
  • Literal Objek yang Ditingkatkan
  • Destrukturisasi (Destrukturisasi Objek).
  • Janji (Janji).
  • Generator
  • Modul
  • Simbol.
  • Proksi
  • Set.
  • Opsi default.
  • Istirahat dan sebarkan operator.
  • Blokir ruang lingkup (kata kunci “let” dan “const”).

42. Apa perbedaan antara kata kunci "var", "let" dan "const"?


Variabel yang dideklarasikan menggunakan kata kunci var bersifat global. Ini berarti mereka dapat diakses dari mana saja dalam kode:

function giveMeX(showX){
    if(showX){
        var x = 5
    }
    return x
}

console.log(giveMeX(false))
console.log(giveMeX(true))

Hasil dari console.log pertama akan tidak terdefinisi, yang kedua - 5. Kami memiliki akses ke variabel "x" karena kemunculannya ke dalam lingkup global. Kode dari contoh di atas ditafsirkan sebagai berikut:

function giveMeX(showX){
    var x //   undefined
    if(showX){
        x = 5
    }
    return x
}

Hasil console.log pertama tidak terdefinisi, karena variabel yang dideklarasikan yang tidak diberi nilai tidak ditentukan secara default.

Variabel yang dideklarasikan menggunakan kata kunci "let" dan "const" memiliki lingkup blok. Ini berarti bahwa mereka hanya tersedia di dalam blokir ({}):

function giveMeX(showX){
    if(showX){
        let x = 5
    }
    return x
}

function giveMeY(showY){
    if(showY){
        let y = 5
    }
    return y
}

Memanggil fungsi-fungsi ini dengan parameter palsu akan menghasilkan kesalahan ReferenceError, karena variabel "x" dan "y" tidak dapat diakses di luar blok dan nilainya tidak dikembalikan (jangan muncul).

Perbedaan antara "let" dan "const" adalah bahwa dalam kasus pertama kita dapat mengubah nilai variabel, dan pada yang kedua - tidak (konstan). Pada saat yang sama, kita dapat mengubah nilai properti dari objek yang dideklarasikan menggunakan const, tetapi bukan properti itu sendiri (variabel).

43. Apa fungsi panah (Fungsi Panah)?


Fungsi panah adalah cara yang relatif baru untuk membuat fungsi di JS. Fungsi panah lebih cepat dan memiliki lebih banyak sintaks yang dapat dibaca daripada ekspresi fungsional. Dalam fungsi panah, kata "fungsi" dihilangkan:

// ES5
var getCurrentDate = function(){
    return new Date()
}

// ES6
const getCurrentDate = () => new Date()

Dalam ekspresi fungsional, kami menggunakan kata kunci kembali untuk mengembalikan nilai. Dalam fungsi panah, kita tidak melakukan ini, karena fungsi panah secara implisit mengembalikan nilai, asalkan kita mengembalikan satu ekspresi atau nilai:

// ES5
function greet(name){
    return 'Hello ' + name + '!' 
}

// ES6
const greet = (name) => `Hello ${name}`
const greet2 = name = > `Hello ${name}`

Kami juga dapat meneruskan parameter ke fungsi panah. Jika kami melewati satu parameter, kami tidak perlu membungkusnya dengan tanda kurung:

const getArgs = () => arguments

const getArgs2 = (...rest) => rest

Fungsi panah tidak memiliki akses ke objek argumen. Oleh karena itu, memanggil fungsi pertama akan menghasilkan kesalahan. Untuk mendapatkan parameter yang diteruskan ke fungsi, kita dapat menggunakan operator lainnya.

const data = {
    result: 0
    nums: [1,2,3,4,5]
    computeResult(){
        // this    data
        const addAll = () => {
        //     this   
        return this.nums.reduce((total, cur) => total + cur, 0)
        }
    this.result = addAll()
    }
}

44. Apa itu kelas?


Kelas adalah cara menulis fungsi konstruktor yang relatif baru di JS. Ini adalah gula sintaksis untuk fungsi konstruktor. Kelas didasarkan pada prototipe dan warisan prototipe yang sama:

// ES5
function Person(firstName, lastName, age, address){
    this.firstName = firstName
    this.lastName = lastName
    this.age = age
    this.address = address
}

Person.self = function(){
    return this
}

Person.prototype.toString = function(){
    return '[object Person]'
}

Person.prototype.getFullName = function(){
    return this.firstName + ' ' + this.lastName
}

// ES6
class Person{
    constructor(firstName, lastName, age, address){
        this.firstName = firstName
        this.lastName = lastName
        this.age = age
        this.address = address
    }

    static self(){
        return this
    }

    toString(){
        return '[object Person]'
    }

    getFullName(){
        return `${this.firstName} ${this.lastName}`
    }
}

Metode menimpa dan mewariskan dari kelas lain:

// ES5
Employee.prototype = Object.create(Person.prototype)

function Employee(firstName, lastName, age, address, jobTitle, yearStarted){
    Person.call(this, firstName, lastName, age, address)
    this.jobTitle = jobTitle
    this.yearStarted = yearStarted
}

Employee.prototype.describe = function(){
    return `I am ${this.getFullName()} and I have a position of #{this.jobTitle} and I started at ${this.yearStarted}}`
}

Employee.prototype.toString = function(){
    return '[object Employee]'
}

// ES6
class Employee extends Person{ //   Person
    constructor(firstName, lastName, age, address, jobTitle, yearStarted){
        super(firstName, lastName, age, address)
        this.jobTitle = jobTitle
        this.yearStarted = yearStarted
    }

    describe(){
       return `I am ${this.getFullName()} and I have a position of #{this.jobTitle} and I started at ${this.yearStarted}}` 
    }

    toString(){ //   toString  Person
        return '[object Employee]'
    }
}

Bagaimana mempelajari tentang penggunaan prototipe?

class Something{ }

function AnotherSomething(){ }

const as = new AnotherSomething()
const s = new Something()

console.log(typeof Something) // function
console.log(typeof AnotherSomething) // function
console.log(as.toString()) // [object Object]
console.log(a.toString()) // [object Object]
console.log(as.toString === Object.prototype.toString)
console.log(a.toString === Object.prototype.toString)
//     true
// Object.prototype     
// Something  AnotherSomething   Object.prototype

45. Apa itu Literal Templat?


Templat literal adalah cara yang relatif baru untuk membuat string di JS. Literal template dibuat menggunakan double backticks (``):

// ES5
var greet = 'Hi I\'m Mark'

// ES6
let greet = `Hi I'm Mark`

Dalam literal templat, kita tidak perlu lepas dari tanda kutip tunggal.
// ES5
var lastWords = '\n'
    + ' I \n'
    + ' am \n'
    + 'Iron Man \n'

// ES6
let lastWords = `
    I
    am
    Iron Man
`

Dalam ES6, kita tidak perlu menggunakan urutan escape "\ n" untuk memberi makan baris.

// ES5
function greet(name){
    return 'Hello ' + name + '!'
}

// ES6
function greet(name){
    return `Hello ${name}!`
}

Di ES6, kita tidak perlu menggunakan penggabungan string untuk menggabungkan teks dengan variabel: kita dapat menggunakan ekspresi $ {expr} untuk mendapatkan nilai variabel.

46. ​​Apa itu Destrukturisasi Objek?


Destrukturisasi adalah cara yang relatif baru untuk mendapatkan (mengambil) nilai-nilai suatu objek atau array.

Katakanlah kita memiliki objek seperti ini:

const employee = {
    firstName: 'Marko',
    lastName: 'Polo',
    position: 'Software Developer',
    yearHired: 2017
}

Sebelumnya, untuk membuat properti suatu objek, kami membuat variabel untuk setiap properti. Itu sangat membosankan dan sangat menjengkelkan:

var firstName = employee.firstName
var lastName = employee.lastName
var position = employee.position
var yearHired = employee.yearHired

Menggunakan destrukturisasi membuat kode lebih bersih dan membutuhkan waktu lebih sedikit. Sintaksis perusak adalah sebagai berikut: kita melampirkan properti objek yang ingin kita terima dalam kurung keriting ({}), dan jika kita berbicara tentang sebuah array, dalam kurung siku ([]):

let { firstName, lastName, position, yearHired } = employee

Untuk mengubah nama variabel, gunakan "propertyName: newName":

let { firstName: fName, lastName: lName, position, yearHired } = employee

Untuk menetapkan nilai default ke variabel, gunakan "propertyName = 'defaultValue'":

let { firstName = 'Mark', lastName: lName, position, yearHired } = employee

47. Apa itu Modul?


Modul memungkinkan Anda untuk menggabungkan (menggunakan) kode dari file yang berbeda dan menyelamatkan kami dari keharusan menyimpan semua kode dalam satu file besar. Sebelum modul muncul di JS, ada dua sistem modul populer untuk kode pendukung:

  • CommonJS - Nodejs
  • AMD (AsyncronousModuleDefinition) - Browser

Sintaks modul sangat sederhana: kami menggunakan impor untuk mengimpor fungsionalitas atau nilai dari file atau file lain, dan ekspor untuk mengekspor.

Ekspor fungsionalitas ke file lain (bernama ekspor):

// ES5 CommonJS - helpers.js
exports.isNull = function(val){
    return val === null
}

exports.isUndefined = function(val){
    return val === undefined
}

exports.isNullOrUndefined = function(val){
    return exports.isNull(val) || exports.isUndefined(val)
}

// ES6 
export function isNull(val){
    return val === null;
}

export function isUndefined(val) {
    return val === undefined;
}

export function isNullOrUndefined(val) {
    return isNull(val) || isUndefined(val);
}

Impor fungsionalitas ke file lain:

// ES5 CommonJS - index.js
const helpers = require('./helpers.js')
const isNull = helpers.isNull
const isUndefined = helpers.isUndefined
const isNullOrUndefined = helpers.isNullOrUndefined

//    
const { isNull, isUndefined, isNullOrUndefined } = require('./helpers.js')

// ES6 
import * as helpers from './helpers.js' // helpers -  

// 
import { isNull, isUndefined, isNullOrUndefined as isValid} from './helpers.js' //  "as"  

Ekspor Default:

// ES5 CommonJS - index.js
class Helpers {
    static isNull(val){
        return val === null
    }

    static isUndefined(val){
        return val === undefined
    }

    static isNullOrUndefined(val){
        return this.isNull(val) || this.isUndefined(val)
    }
}

module.exports = Helpers

// ES6 
class Helpers {
    static isNull(val){
        return val === null
    }

    static isUndefined(val){
        return val === undefined
    }

    static isNullOrUndefined(val){
        return this.isNull(val) || this.isUndefined(val)
    }
}

export default Helpers

Impor:

// ES5 CommonJS - index.js
const Helpers = require('./helpers.js')
console.log(Helpers.isNull(null))

// ES6 
import Helpers from './helpers.js'
console.log(Helpers.isNull(null))

Ini adalah penggunaan dasar modul. Saya tidak masuk ke detail, karena posting saya sudah terlalu besar.

48. Apa yang dimaksud objek Set?


Objek Set memungkinkan Anda untuk menyimpan nilai unik, primitif, dan referensi objek. Sekali lagi: hanya nilai unik yang dapat ditambahkan ke Set. Ini memeriksa nilai yang disimpan di dalamnya menggunakan algoritma SameZeroValue.

Set instance dibuat menggunakan set constructor. Kami juga dapat memberikan beberapa nilai saat membuat:

const set1 = new Set()
const set2 = new Set(['a','b','c','d','d','e']) //  "d"  

Kita bisa menambahkan nilai ke Set menggunakan metode add. Karena metode add dapat dikembalikan, kita dapat menggunakan serangkaian panggilan:

set2.add('f')
set2.add('g').add('h').add('i').add('j').add('k').add('k') //  "k"  

Kami dapat menghapus nilai dari Set menggunakan metode hapus:

set2.delete('k') // true
set2.delete('z') // false,    set2   

Kami dapat memeriksa properti di Set menggunakan metode has:

set2.has('a') // true
set2.has('z') // false

Untuk mendapatkan panjang Set, gunakan metode ukuran:

set2.size // 10

Metode yang jelas menghapus Set:

set2.clear() // 

Kita bisa menggunakan Set untuk menghapus nilai duplikat dalam array:

const nums = [1,2,3,4,5,6,6,7,8,8,5]
const uniqNums = [...new Set(nums)] // [1,2,3,4,5,6,7,8]

49. Apa itu Fungsi Panggilan Balik?


Fungsi panggilan balik adalah fungsi yang panggilannya ditunda untuk masa depan (terjadi dalam kondisi tertentu, misalnya, ketika suatu peristiwa terjadi).

const btnAdd = document.getElementById('btnAdd')

btnAdd.addEventListener('click', function clickCallback(e)){
    //   
}

Dalam contoh ini, kami sedang menunggu acara "klik" pada elemen dengan pengidentifikasi "btnAdd". Dengan klik, fungsi clickCallback disebut. Fungsi panggilan balik menambahkan beberapa fungsionalitas ke data atau acara. Perkecil, saring, dan metode peta melewati fungsi panggilan balik sebagai argumen kedua. Analogi yang baik untuk menelepon kembali adalah situasi berikut: Anda menelepon seseorang, dia tidak menjawab, Anda meninggalkan pesan padanya dan menunggu dia menelepon kembali. Panggilan atau pesan adalah peristiwa atau data, dan panggilan balik adalah harapan (antisipasi) dari panggilan balik.

50. Apa itu Janji?


Janji adalah salah satu cara untuk bekerja dengan kode asinkron di JS. Mereka mengembalikan hasil operasi asinkron. Janji-janji diciptakan untuk memecahkan masalah yang disebut fungsi panggilan balik neraka.

fs.readFile('somefile.txt', function(e, data){
    if(e){
        console.log(e)
    }
    console.log(data)
})

Masalah dengan pendekatan ini dimulai ketika kita perlu menambahkan operasi asinkron lain ke yang pertama (di dalam yang pertama), lalu yang lain, dll. Akibatnya, kami mendapatkan kode yang berantakan dan tidak dapat dibaca:

fs.readFile('somefile.txt', function(e,data){
    // 
    fs.readFile('directory', function(e, files){
        // 
        fs.mkdir('directory', function(e){
            // 
        })
    })
})

Dan inilah tampilannya dengan janji:

promReadFile('file/path')
.then(data => {
    return promReaddir('directory')
})
.then(data => {
    return promMkdir('directory')
})
.catch(e => {
    console.error(e)
})

Janji memiliki empat kondisi:

  • Menunggu adalah kondisi awal dari sebuah janji. Hasil dari janji tidak diketahui karena operasi tidak selesai.
  • Selesai - Operasi asinkron selesai, ada hasilnya.
  • Ditolak - operasi asinkron gagal, ada alasannya.
  • Selesai - selesai atau ditolak.

Konstruktor Promise menerima tekad dan tolak sebagai parameter. Dalam penyelesaian, hasil operasi dicatat, di tolak, alasan kegagalan operasi. Hasilnya dapat diproses dalam metode .kemudian, kesalahan dapat diproses dalam metode .catch. Metode .then juga mengembalikan janji, jadi kita bisa menggunakan rantai yang terdiri dari beberapa .then.

const myPromiseAsync = (...args) => {
    return new Promise((resolve, reject) => {
        doSomeAsync(...args, (error, data) => {
            if(error){
                reject(error)
            } else{
                resolve(data)
            }
        })
    })
}

myPromiseAsync()
.then(result => {
    console.log(result)
})
.catch(reason => {
    console.error(reason)
})

Kami dapat membuat fungsi pembantu untuk mengonversi operasi asinkron dari panggilan balik ke janji. Ini akan berfungsi seperti util dari Node.js ("promisifikasi"):

const toPromise = (asyncFuncWithCallback) => {
    return (...args) => {
        return new Promise((res, rej) => {
            asyncFuncWithCallback(...args, (e, result) => {
                return e ? rej(e) : res(result)
            })
        })
    }
}

const promiseReadFile = toPromise(fs.readFile)

promiseReadFile('file/path')
.then((data) => {
    console.log(data)
})
.catch(e => console.error(e))

Anda dapat membaca lebih lanjut tentang janji di sini dan di sini .

51. Apa itu async / menunggu?


Async / await adalah cara yang relatif baru untuk menulis kode asynchronous (non-blocking) di JS. Mereka dibungkus dalam sebuah janji. Itu membuat kode lebih mudah dibaca dan bersih daripada janji dan fungsi panggilan balik. Namun, untuk menggunakan async / menunggu, Anda harus mengetahui janji-janji itu dengan baik.

// 
function callApi(){
    return fetch('url/to/api/endpoint')
    .then(resp => resp.json())
    .then(data => {
        //   
    }).catch(err => {
        //   
    })
}

// async/await
//     try/catch
async function callApi(){
    try{
        const resp = await fetch('url/to/api/endpoint')
        const data = await res.json()
        //   
    } catch(e){
        //   
    }
}

Ingat: menggunakan kata kunci async sebelum suatu fungsi memaksanya untuk mengembalikan janji:

const giveMeOne = async () = 1

giveMeOne()
.then((num) => {
    console.log(num) // 1
})

Kata kunci yang menunggu hanya dapat digunakan di dalam fungsi asinkron. Menggunakan menunggu di dalam fungsi lain akan menghasilkan kesalahan. Menunggu ekspresi selesai di sebelah kanan untuk mengembalikan nilainya sebelum baris kode berikutnya.

const giveMeOne = async() => 1

function getOne(){
    try{
        const num = await giveMeOne()
        console.log(num)
    } catch(e){
        console.log(e)
    }
}
// Uncaught SyntaxError: await is only valid in an async function

async function getTwo(){
    try{
        const num1 = await giveMeOne()
        const nm2 = await giveMeOne()
        return num1 + num2
    } catch(e){
        console.log(e)
    }
}

await getTwo() // 2

Baca lebih lanjut tentang async / tunggu di sini dan di sini .

52. Apa perbedaan antara operator spread dan operator sisanya?


Pernyataan spread dan rest memiliki sintaks yang sama ("..."). Perbedaannya terletak pada kenyataan bahwa dengan bantuan spread, kami mentransfer atau menyebarkan data array ke data lain, dan dengan bantuan rest, kami mendapatkan semua parameter fungsi dan memasukkannya ke dalam array (atau kami mengekstrak beberapa parameter).

function add(a, b){
    return a + b
}

const nums = [5, 6]
const sum = add(...nums)
console.log(sum) // 11

Dalam contoh ini, kami menggunakan spread saat memanggil fungsi add dengan data array nums. Nilai dari variabel "a" akan menjadi 5, b = 6, jumlah = 11.

function add(...rest){
    return rest.reduce((total, current) => total + current)
}

console.log(add(1, 2)) // 3
console.log(add(1, 2, 3, 4, 5)) // 15

Di sini kita memanggil fungsi add dengan sejumlah argumen. Tambahkan mengembalikan jumlah argumen ini.

const [first, ...others] = [1, 2, 3, 4, 5]
console.log(first) // 1
console.log(others) // [2, 3, 4, 5]

Dalam contoh ini, kita menggunakan rest untuk meletakkan sejumlah parameter kecuali yang pertama ke array lainnya.

53. Apa Parameter Defaultnya?


Ini adalah cara yang relatif baru untuk mendefinisikan nilai variabel default.

// ES5
function add(a,b){
    a = a || 0
    b = b || 0
    return a + b
}

// ES6
function add(a = 0, b = 0){
    return a + b
}
//      "a"  "b" - ,    0
add(1) // 1

Anda dapat menggunakan perusakan:

function getFirst([first, ...rest] = [0, 1]){
    return first
}

getFirst() // 0
getFirst([10,20,30]) // 10

function getArr({ nums } = { nums: [1,2,3,4] }){
    return nums
}

getArr // [1,2,3,4]
getArr({nums:[5,4,3,2,1]}) // [5,4,3,2,1]

Kami bahkan dapat menggunakan parameter default yang dideklarasikan di tempat yang sama:

function doSomethingWithValue(value = 'Hello World', callback = () => { console.log(value) }){
    callback()
}
doSomethingWithValue() // Hello World

54. Apa itu pembungkus objek (Wrapper Objects)?


String, angka, dan boolean primitif memiliki properti dan metode, meskipun faktanya mereka bukan objek:

let name = 'marko'

console.log(typeof name) // string
console.log(name.toUpperCase()) // MARKO

Nama adalah string (tipe primitif) yang tidak memiliki properti dan metode, tetapi ketika kita memanggil metode toUpperCase (), ini tidak mengarah ke kesalahan, tetapi ke "MARKO".

Alasan untuk perilaku ini adalah bahwa nama sementara dikonversi ke suatu objek. Setiap primitif, kecuali nol dan tidak terdefinisi, memiliki objek pembungkus. Objek tersebut adalah String, Number, Boolean, Symbol, dan BigInt. Dalam kasus kami, kode tersebut mengambil bentuk berikut:

console.log(new String(name).toUpperCase()) // MARKO

Objek sementara dibuang setelah menyelesaikan pekerjaan dengan properti atau metode.

55. Apa perbedaan antara Pemaksaan Tersirat dan Eksplisit?


Konversi tersirat adalah cara memberikan nilai ke tipe lain tanpa sepengetahuan kami (partisipasi).

Misalkan kita memiliki yang berikut ini:

console.log(1 + '6')
console.log(false + true)
console.log(6 * '2')

Hasil dari console.log pertama akan menjadi 16. Dalam bahasa lain, ini akan menyebabkan kesalahan, tetapi di JS 1 itu dikonversi ke string dan digabungkan (dilampirkan) dari 6. Kami tidak melakukan apa-apa, konversi terjadi secara otomatis.

Hasil dari console.log kedua adalah 1. Salah dikonversi menjadi 0, benar menjadi 1. 0 +1 = 1.

Hasil dari console.log ketiga adalah 12. Baris 2 dikonversi ke angka sebelum dikalikan dengan 6.

Konversi eksplisit menunjukkan partisipasi kita dalam casting nilai ke tipe lain:

console.log(1 + parseInt('6'))

Dalam contoh ini, kami menggunakan parseInt untuk memberikan string 6 ke angka, kemudian tambahkan dua angka dan dapatkan 7.

56. Apa itu NaN? Bagaimana cara memeriksa apakah nilainya NaN?


NaN atau Bukan Angka (bukan angka) adalah nilai yang diperoleh sebagai hasil dari melakukan operasi numerik pada nilai non-numerik:

let a

console.log(parseInt('abc'))
console.log(parseInt(null))
console.log(parseInt(undefined))
console.log(parseInt(++a))
console.log(parseInt({} * 10))
console.log(parseInt('abc' - 2))
console.log(parseInt(0 / 0))
console.log(parseInt('10a' * 10))

JS memiliki metode isNaN bawaan yang memungkinkan Anda memeriksa apakah nilainya NaN, tetapi berperilaku cukup aneh:

console.log(isNaN()) // true
console.log(isNaN(undefined)) // true
console.log(isNaN({})) // true
console.log(isNaN(String('a'))) // true
console.log(isNaN(() => { })) // true

Hasil dari semua console.log benar, terlepas dari kenyataan bahwa tidak ada nilai yang NaN.

ES6 merekomendasikan menggunakan metode Number.isNaN untuk memeriksa apakah nilainya NaN. Kita juga dapat menulis fungsi bantu untuk menyelesaikan masalah "Ketimpangan NaN untuk dirinya sendiri":

function checkIsNan(value){
    return value !== value
}

57. Bagaimana cara memeriksa apakah suatu nilai adalah array?


Untuk melakukan ini, gunakan metode Array.isArray:

console.log(Array.isArray(5)) // false
console.log(Array.isArray('')) // false
console.log(Array.isArray()) // false
console.log(Array.isArray(null)) // false
console.log(Array.isArray( {length: 5 })) // false
console.log(Array.isArray([])) // true

Jika lingkungan tempat Anda bekerja tidak mendukung metode ini, Anda dapat menggunakan polyfile berikut:

function isArray(value){
    return Object.prototype.toString.call(value) === '[object Array]'
}

58. Bagaimana cara memeriksa nomor yang genap, tanpa menggunakan divisi modulo atau divisi dengan sisa (operator "%")?


Untuk mengatasi masalah ini, Anda dapat menggunakan operator "&" (biner dan). & Operator membandingkan operan sebagai nilai biner.

function isEven(num){
    if(num & 1){
        return false
    } else{
        return true
    }
}

0 dalam notasi biner adalah 000
1 - ini adalah 001
2 - 010
3 - 011
4 - 100
5 - 101
6 - 110
7 - 111
, dll.



Console.log (5 & 1) akan mengembalikan 1. Pertama, operator & mengubah kedua angka menjadi nilai biner, 5 berubah menjadi 101, 1 berubah menjadi 001. Kemudian perbandingan bitwise dibuat:



Bandingkan 1 dan 0, kita mendapatkan 0.
Bandingkan 0 dan 0 , kami mendapatkan 0.
Bandingkan 1 dan 1, kami mendapatkan 1.
Konversikan nilai biner ke integer, kami dapatkan 1.

Jika informasi ini tampaknya terlalu rumit untuk Anda, kami dapat menyelesaikan masalah menggunakan fungsi rekursif:

function isEven(num){
    if(num < 0 || num === 1) return false
    if(num == 0) return true
    return isEven(num - 2)
}

59. Bagaimana cara menentukan keberadaan properti dalam suatu objek?


Ada tiga cara untuk melakukan ini.

Cara pertama adalah dengan menggunakan operator in:

const o = {
    'prop': 'bwahahah',
    'prop2': 'hweasa'
}

console.log('prop' in o) // true
console.log('prop1' in o) // false

Yang kedua adalah menggunakan metode hasOwnProperty:

console.log(o.hasOwnProperty('prop2')) // true
console.log(o.hasOwnProperty('prop1')) // false

Yang ketiga adalah notasi indeks array:

console.log(o['prop']) // bwahahah
console.log(o['prop1']) // undefined

60. Apa itu AJAX?


AJAX atau Asyncronous JavaScript and XML adalah seperangkat teknologi yang saling berhubungan yang memungkinkan Anda untuk bekerja dengan data dalam mode asinkron. Ini berarti bahwa kami dapat mengirim data ke server dan menerima data darinya tanpa memuat ulang laman web.

AJAX menggunakan teknologi berikut:
HTML - struktur halaman web.
CSS - gaya halaman web.
JavaScript - perilaku halaman dan bekerja dengan DOM.
XMLHttpRequest API - mengirim dan menerima data dari server.
PHP, Python, Nodejs - semacam bahasa server.

61. Bagaimana cara membuat objek di JS?


Objek literal:

const o = {
    name: 'Mark',
    greeting(){
        return `Hi, I'm ${this.name}`
    }
}

o.greeting // Hi, I'm Mark

Fungsi konstruktor:

function Person(name){
    this.name = name
}

Person.prototype.greeting = function(){
    return `Hi, I'm ${this.name}`
}

const mark = new Person('Mark')

mark.greeting() // Hi, I'm Mark

Metode Object.create:

const n = {
    greeting(){
        return `Hi, I'm ${this.name}`
    }
}

const o = Object.create(n)

o.name = 'Mark'

console.log(o.greeting) // Hi, I'm Mark

62. Apa perbedaan antara metode Object.freeze dan Object.seal?


Perbedaannya adalah bahwa ketika menggunakan metode Object.freeze, kita tidak dapat mengubah atau mengedit properti objek, dan ketika menggunakan Object.seal, kita memiliki kesempatan seperti itu.

63. Apa perbedaan antara operator in dan metode hasOwnProperty?


Perbedaannya adalah bahwa operator "dalam" memeriksa keberadaan properti tidak hanya dalam objek itu sendiri, tetapi juga dalam prototipe-nya, dan metode hasOwnProperty - hanya pada objek.

console.log('prop' in o) // true
console.log('toString' in o) // true

console.log(o.hasOwnProperty('prop')) // true
console.log(o.hasOwnProperty('toString')) // false

64. Apa teknik bekerja dengan kode asinkron di JS yang Anda tahu?


  • Telepon balik
  • Janji (Janji).
  • Async / tunggu.
  • Perpustakaan seperti async.js, cetak biru, q, co.

65. Apa perbedaan antara fungsi normal dan ekspresi fungsional?


Katakanlah kita memiliki yang berikut ini:

hoistedFunc()
notHoistedFunc()

function hoistedFunc(){
    console.log('I am hoisted')
}

var notHoistedFunc = function(){
    console.log('I will not be hoisted!')
}

Panggilan ke notHoistedFunc akan menghasilkan kesalahan, tetapi panggilan ke hoistedFunc tidak, karena hoistedFunc "muncul", naik ke lingkup global, tetapi notHoistedFunc tidak.

66. Bagaimana cara memanggil fungsi di JS?


Di JS, ada 4 cara untuk memanggil fungsi. Panggilan menentukan nilai ini atau "pemilik" fungsi.

Panggil sebagai fungsi. Jika suatu fungsi disebut sebagai metode, konstruktor, atau menggunakan metode apply atau call, maka itu disebut sebagai fungsi. Pemilik fungsi tersebut adalah objek jendela:

function add(a,b){
    console.log(this)
    return a + b
}

add(1,5) // window, 6

const o = {
    method(callback){
        callback()
    }
}

o.method(function(){
    console.log(this) // window
})

Panggil sebagai metode. Ketika suatu fungsi adalah properti dari suatu objek, kita menyebutnya metode. Ketika suatu metode dipanggil, objek ini menjadi objek metode ini:

const details = {
    name: 'Marko',
    getName(){
        return this.name
    }
}

details.getName() // Marko,  this   details

Sebut sebagai konstruktor. Ketika suatu fungsi dipanggil menggunakan kata kunci "baru", kami menyebut fungsi itu sebagai konstruktor. Ini menciptakan objek kosong, yang merupakan nilai dari ini:

function Employee(name, position, yearHired){
    //   ,   this
    // this = {}
    this.name = name
    this.position = position
    this.yearHired = yearHired
    //   Employee.prototype   this,    
}

const emp = new Employee('Marko Polo', 'Software Development', 2017)

Panggilan menggunakan metode panggilan atau penerapan. Kami menggunakan metode ini ketika kami ingin secara eksplisit menentukan nilai ini atau pemilik fungsi:

const obj1 = {
    result: 0
}

const obj2 = {
    result: 0
}

function reduceAdd(){
    let result = 0
    for(let i = 0, len = arguments.length; i < len; i++){
        result += arguments[i]
    }
    this.result = result
}

reduceAdd.apply(obj1, [1,2,3,4,5]) //  this  obj1
reduceAdd.call(obj2, 1,2,3,4,5) //  this  obj2

67. Apa itu menghafal atau menghafal?


Memoisasi adalah teknik menciptakan fungsi yang dapat mengingat hasil atau nilai yang dihitung sebelumnya. Keuntungan dari memoisasi adalah kita menghindari menjalankan kembali fungsi dengan argumen yang sama. Kerugiannya adalah kita terpaksa mengalokasikan memori tambahan untuk menyimpan hasilnya.

68. Bagaimana Anda menerapkan fungsi bantu menghafal?


function memoize(fn){
    const cache = {}
    return function(param){
        if(cache[param]){
            console.log('cached')
            return cache[param]
        } else{
            let result = fn(param)
            cache[param] = result
            console.log('not cached')
            return result
        }
    }
}

const toUpper = (str = '') => str.toUpperCase()

const toUpperMemoized = memoize(toUpper)

toUpperMemoized('abcdef')
toUpperMemoized('abcdef') //  

Kami menerapkan fungsi memoisasi dengan satu argumen. Mari kita buat "multi-argumen":

const slice = Array.prototype.slice
function memoize(fn){
    const cache = {}
    return (...args) => {
        const params = slice.call(args)
        console.log(params)
        if(cache[params]){
            console.log('cached')
            return cache[params]
        } else{
            let result = fn(...args)
            cache[params] = result
            console.log('not cached')
            return result
        }
    }
}
const makeFullName = (fName, lName) => `${fName} ${lName}`
const reduceAdd = (numbers, startValue = 0) => numbers.reduce((total, cur) => total + cur, startValue)

const memoizedFullName = memoize(makeFullName)
const memoizeReduceAdd = memoize(reduceAdd)

memoizedFullName('Marko', 'Polo')
memoizedFullName('Marko', 'Polo') //  

memoizeReduceAdd([1,2,3,4],5)
memoizeReduceAdd([1,2,3,4],5) //  

69. Mengapa typeof null mengembalikan objek? Bagaimana cara memeriksa apakah suatu nilai nol?


typeof null == 'objek' akan selalu kembali benar karena alasan historis. Ada proposal untuk memperbaiki kesalahan ini dengan mengubah typeof null = 'objek' menjadi typeof null = 'null', tetapi ditolak dengan tujuan mempertahankan kompatibilitas ke belakang (perubahan seperti itu akan menyebabkan sejumlah besar kesalahan).

Untuk memeriksa apakah nilainya nol, Anda dapat menggunakan operator kesetaraan ketat (===):

function isNull(value){
    return value === null
}

70. Untuk apa kata kunci "baru" digunakan?


Kata kunci "baru" digunakan dalam fungsi konstruktor untuk membuat objek baru (turunan baru dari kelas).

Katakanlah kita memiliki kode seperti ini:

function Employee(name, position, yearHired){
    this.name = name
    this.position = position
    this.yearHired = yearHired
}

const emp = new Employee('Marko Polo', 'Software Development', 2017)

Kata kunci "baru" melakukan 4 hal:

  1. Membuat objek kosong.
  2. Mengikat nilai ini ke sana.
  3. Fungsi mewarisi dari functionName.prototype.
  4. Mengembalikan ini kecuali ditentukan lain.

Source: https://habr.com/ru/post/undefined/


All Articles