└── README.md /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # Tổng hợp câu hỏi phỏng vấn Javascript về Front-end lẫn Back-end 5 | ![enter image description here](https://i.imgur.com/9P7ipCX.png) 6 | Các câu hỏi bên dưới chủ yếu về Javascript bao gồm cả Front-end lẫn Back-end. Rất mong sẽ giúp ích cho các bạn trong quá trình ôn luyện Javascript cũng như chuẩn bị phỏng vấn . 7 | 8 | Nếu thích hãy để lại cho mình **1 STAR** nhé . Nếu bạn nào có câu hỏi hay và muốn đóng góp để repository này ngày càng chất lượng đừng ngần ngại **Create Pull Request** để đăng câu mới nhé ! 9 | 10 | # Người đóng góp : 11 | 12 | - [@quangpl](https://github.com/quangpl) 13 | 14 | ## Câu 1. Sự khác biệt giữa `undefined` và ` not defined` trong JavaScript 15 | 16 | ### Câu trả lời 17 | 18 | Trong JavaScript nếu bạn sử dụng một biến không tồn tại và chưa được khai báo, thì JavaScript sẽ đưa ra một lỗi `var name is not defined` và các lệnh sẽ ngừng thực thi sau đó. Nhưng nếu bạn sử dụng `typeof undeclared_variable` thì nó sẽ trả về `undefined`. 19 | 20 | Tiếp theo, hãy hiểu sự khác biệt giữa khai báo và định nghĩa. 21 | 22 | `var x` là một khai báo vì bạn chưa xác định giá trị của nó, nhưng bạn đang khai báo sự tồn tại của nó và nhu cầu cấp phát bộ nhớ cho chính nó 23 | 24 | ```javascript 25 | var x; // khai báo x 26 | console.log (x); // kết quả : undefined 27 | ``` 28 | 29 | `var x = 1` bao gồm cả khai báo và định nghĩa (chúng ta cũng có thể nói rằng chúng ta đang thực hiện khởi tạo), Ở đây xảy ra 2 việc là khai báo và gán giá trị cho biến x . Trong JavaScript, mọi khai báo biến và khai báo hàm đều được đưa lên đầu phạm vi hiện tại của nó sau đó mới được sử dụng và thuật ngữ này gọi là `hoising`. 30 | 31 | Một biến có thể được khai báo nhưng không được xác định giá trị . Và dĩ nhiên giá trị của nó là `undefined`. 32 | 33 | ```javascript 34 | var x; // khai báo biến x 35 | typeof x === 'undefined'; // kết quả : true 36 | ``` 37 | 38 | Một biến có thể không được khai báo cũng không được định nghĩa. Khi chúng ta tham chiếu đên biến đó thì kết quả sẽ là `undefined`. 39 | 40 | ``` 41 | console.log (y); // Kết quả: ReferenceError: y is not defined 42 | ``` 43 | 44 | ### Tham khảo : 45 | [http://stackoverflow.com/questions/20822022/javascript-variable-definition-declaration](http://stackoverflow.com/questions/20822022/javascript-variable-definition-declaration) 46 | 47 | 48 | ## Câu 2. Với giá trị nào của `x` thì kết quả của các câu lệnh sau không giống nhau? 49 | 50 | 51 | ```javascript 52 | // if( x <= 100 ) {...} 53 | // if( !(x > 100) ) {...} 54 | ``` 55 | ### Câu trả lời 56 | 57 | `NaN <= 100` là` false` và` NaN> 100` cũng là` false`, vì vậy nếu 58 | giá trị của `x` là `NaN`, các câu lệnh không giống nhau. 59 | 60 | Điều tương tự cũng xảy ra với bất kỳ giá trị nào của x khi trả về **NaN**, ví dụ: `undefined`,` [1,2,5] `,` {a: 22} `, v.v. 61 | 62 | Đây là lý do tại sao bạn cần chú ý khi xử lý các biến . `NaN` có thể bằng nhau, nhỏ hơn hoặc nhiều hơn bất kỳ giá trị số nào khác, vì vậy cách tốt nhất để kiểm tra xem giá trị đó có phải là `NaN` hay không, là sử dụng hàm ` isNaN () `. 63 | 64 | ## Câu 3. Hạn chế của việc khai báo hàm trực tiếp bằng các đối tượng JavaScript là gì? 65 | 66 | ### Câu trả lời 67 | 68 | Một trong những nhược điểm của việc khai báo các hàm trực tiếp bằng các đối tượng JavaScript là chúng quản lý bộ nhớ rất kém . Song song đó, một bản sao mới của hàm được tạo cho mỗi phiên bản của một đối tượng (biến). Hãy xem ví dụ bên dưới : 69 | 70 | ```javascript 71 | var Employee = function (name, company, salary) { 72 | this.name = name || ""; 73 | this.company = company || ""; 74 | this.salary = salary || 5000; 75 | 76 | // Tạo một hàm/phương thức mới bằng cách này : 77 | this.formatSalary = function () { 78 | return "$ " + this.salary; 79 | }; 80 | }; 81 | 82 | // Chúng ta cũng có thể tạo hàm/phương thức mới bằng prototype: 83 | Employee.prototype.formatSalary2 = function() { 84 | return "$ " + this.salary; 85 | } 86 | 87 | // Tạo mới các đối tượng với các đối tượng khác nhau 88 | var emp1 = new Employee('Yuri Garagin', 'Company 1', 1000000); 89 | var emp2 = new Employee('Dinesh Gupta', 'Company 2', 1039999); 90 | var emp3 = new Employee('Erich Fromm', 'Company 3', 1299483); 91 | ``` 92 | 93 | Ở đây, mỗi biến đối tượng `emp1`,` emp2`, `emp3` có bản sao riêng của phương thức` formatSalary`. Tuy nhiên, `formatSalary2` sẽ chỉ được thêm một lần vào một đối tượng `Employee.prototype`. 94 | 95 | ## Câu 4. Thế nào là closure trong javascript? bạn có thể cho một ví dụ? 96 | 97 | ### Câu trả lời 98 | 99 | Closure là một hàm được định nghĩa bên trong một hàm khác (được gọi là hàm cha) và có quyền truy cập vào biến được khai báo và định nghĩa trong phạm vi hàm cha. 100 | 101 | Closure có quyền truy cập vào biến trong ba phạm vi: 102 | - Biến được khai báo trong phạm vi của chính mình 103 | - Biến được khai báo trong phạm vi hàm cha 104 | - Biến toàn cục 105 | 106 | ```javascript 107 | var globalVar = "abc"; 108 | 109 | 110 | (function outerFunction (outerArg) { // bắt đầu phạm vi của outerFunction 111 | // Biến bên trong phạm vi của outerFunction 112 | var outerFuncVar = 'x'; 113 | // Hàm close tự gọi 114 | (function innerFunction (innerArg) { // bắt đầu phạm vi của innerFunction 115 | // Biến được khai báo và định nghĩa bên trong pham vi của innerFunction 116 | var innerFuncVar = "y"; 117 | console.log( 118 | "outerArg = " + outerArg + "\n" + 119 | "outerFuncVar = " + outerFuncVar + "\n" + 120 | "innerArg = " + innerArg + "\n" + 121 | "innerFuncVar = " + innerFuncVar + "\n" + 122 | "globalVar = " + globalVar); 123 | //kết thúc phạm vi của innerFunction 124 | })(5); // Truyền tham số 5 125 | // kết thúc phạm vi của outerFunction 126 | })(7); //Truyền tham số 7 127 | ``` 128 | 129 | 130 | innerFunction là một Closure được định nghĩa bên trong outerFunction và có quyền truy cập vào tất cả các biến được khai báo và định nghĩa trong phạm vi hàm cha. Ngoài chức năng này thì Closure có quyền truy cập vào biến toàn cục . 131 | 132 | 133 | ## Câu 5. Viết hàm `mul` để được kết quả như bên dưới 134 | 135 | `` `javascript 136 | console.log (mul (2) (3) (4)); // kết quả: 24 137 | console.log (mul (4) (3) (4)); // kết quả: 48 138 | `` ` 139 | ### Câu trả lời 140 | 141 | Dưới đây là code để giải đề trên : 142 | ```javascript 143 | function mul (x) { 144 | return function (y) { // hàm ẩn danh 145 | return function (z) { // hàm ẩn danh 146 | return x * y * z; 147 | }; 148 | }; 149 | } 150 | ``` 151 | 152 | Ở đây, hàm `mul` nhận đối số thứ nhất và trả về hàm ẩn danh nhận tham số thứ hai và trả về hàm ẩn danh nhận tham số thứ ba và trả về phép nhân của các đối số được truyền liên tiếp 153 | 154 | Trong hàm Javascript được định nghĩa bên trong có quyền truy cập vào biến hàm ngoài và hàm là đối tượng lớp đầu tiên để nó cũng có thể được trả về bởi hàm và được truyền dưới dạng đối số trong hàm khác. 155 | Một số điểm cần lưu ý : 156 | - Hàm là một hình thức khác của loại Đối tượng 157 | - Một hàm có thể có các thuộc tính và có một liên kết trả về hàm constructor của nó 158 | - Một hàm có thể được lưu trữ dưới dạng biến 159 | - Một hàm có thể được truyền dưới dạng tham số cho hàm khác 160 | - Một hàm có thể được trả về từ một hàm khác 161 | 162 | ## Câu 6. Làm thế nào để làm trống một mảng trong JavaScript? 163 | Ví dụ: 164 | 165 | ```javascript 166 | var arrayList = ['a', 'b', 'c', 'd', 'e', 'f']; 167 | ``` 168 | 169 | Làm thế nào chúng ta có thể làm trống mảng trên? 170 | 171 | ### Câu trả lời 172 | Chúng ta hãy thử qua các cách sau đây 173 | 174 | #### Cách 1 175 | 176 | ``` 177 | javascript 178 | arrayList = []; 179 | ``` 180 | 181 | Đoạn mã trên sẽ làm cho biến ArrayList thành một mảng trống mới. Cách này được khuyến nghị nếu bạn không có **tham chiếu đến mảng ban đầu** Ví dụ: 182 | 183 | ```javascript 184 | var arrayList = ['a', 'b', 'c', 'd', 'e', 'f']; // Tạo mảng 185 | var anotherArrayList = arrayList; // Tham chiếu đến arrayList từ một biến khác 186 | arrayList = []; // Làm trống mảng đó 187 | console.log(anotherArrayList); // Kết quả ['a', 'b', 'c', 'd', 'e', 'f'] 188 | ``` 189 | 190 | #### Cách 2 191 | 192 | ```javascript 193 | arrayList.length = 0; 194 | ``` 195 | Code trên sẽ xóa mảng hiện có bằng cách đặt độ dài của nó thành 0. Cách làm này cũng sẽ cập nhật tất cả các biến tham chiếu trỏ đến mảng ban đầu. 196 | 197 | Ví dụ: 198 | 199 | `` `javascript 200 | var arrayList = ['a', 'b', 'c', 'd', 'e', 'f']; // Tạo mảng 201 | var anotherArrayList = arrayList; // Tham chiếu đến arrayList từ một biến khác 202 | arrayList.length = 0; // Làm rỗng mảng 203 | console.log(anotherArrayList); // Kết quả : [] 204 | `` ` 205 | 206 | 207 | #### Cách 3 208 | 209 | ```javascript 210 | while(arrayList.length) { 211 | arrayList.pop(); 212 | } 213 | ``` 214 | 215 | Cách mình vừa thực hiện cũng có thể làm trống mảng. Nhưng không nên sử dụng thường xuyên. 216 | 217 | ## Câu 7 . Kết quả của đoạn code sau đây? 218 | 219 | 220 | ```javascript 221 | var output = (function(x) { 222 | delete x; 223 | return x; 224 | })(0); 225 | 226 | console.log(output); 227 | ``` 228 | 229 | ### Câu trả lời 230 | 231 | Đoạn mã trên sẽ xuất ra `0` . Toán tử `delete` được sử dụng để xóa một thuộc tính khỏi một đối tượng. Ở đây `x` không phải là một đối tượng, nó là ** biến cục bộ **. Toán tử `delete` không ảnh hưởng đến các biến cục bộ. 232 | 233 | 234 | 235 | ## Câu 8. Kết quả của đoạn code sau đây ? 236 | 237 | 238 | ```javascript 239 | var x = 1; 240 | var output = (function() { 241 | delete x; 242 | return x; 243 | })(); 244 | 245 | console.log(output); 246 | ``` 247 | ### Câu trả lời 248 | 249 | Đoạn mã trên sẽ xuất ra `1` . Toán tử `delete` được sử dụng để xóa một thuộc tính khỏi một đối tượng. Ở đây `x` không phải là một đối tượng, nó là ** biến toàn cục ** thuộc loại` number`. 250 | 251 | 252 | ## Câu 9. Kết quả của đoạn code sau đây ? 253 | 254 | 255 | ```javascript 256 | var x = { foo : 1}; 257 | var output = (function() { 258 | delete x.foo; 259 | return x.foo; 260 | })(); 261 | 262 | console.log(output); 263 | ``` 264 | ### Câu trả lời 265 | 266 | Đoạn mã trên sẽ xuất ra `undefined` . Toán tử `delete` được sử dụng để xóa một thuộc tính khỏi một đối tượng. Ở đây `x` là một đối tượng có foo là một thuộc tính và từ một hàm IIFE, mình đang xóa thuộc tính`foo` của đối tượng` x` và sau khi xóa, mình đang tham chiếu thuộc tính đã xóa **foo** nên kết quả sẽ là `undefined`. 267 | 268 | ## Câu 10. Kết quả của đoạn code sau đây ? 269 | 270 | ```javascript 271 | 272 | var Employee = { 273 | company: 'xyz' 274 | } 275 | var emp1 = Object.create(Employee); 276 | delete emp1.company 277 | console.log(emp1.company); 278 | ``` 279 | 280 | ### Câu trả lời 281 | Đoạn mã trên sẽ xuất ra `xyz` . Ở đây, đối tượng `emp1` có company là **prototype**, xóa toán tử không xóa thuộc tính **prototype** 282 | 283 | Đối tượng `emp1` không có ** company** làm thuộc tính của mình. bạn có thể kiểm tra bằng cách `console.log (emp1.hasOwnProperty ('company')); // Kết quả : false` Tuy nhiên, chúng ta có thể xóa thuộc tính **company** khỏi đối tượng `Employee` bằng cách sử dụng `delete Employee.company` hoặc chúng ta cũng có thể xóa khỏi đối tượng `emp1` bằng cách sử dụng thuộc tính `__proto__` và `delete emp1.__proto__.company`. 284 | 285 | 286 | ## Câu 11. `undefined x 1` trong JavaScript là gì? 287 | 288 | ```javascript 289 | var trees = ["redwood", "bay", "cedar", "oak", "maple"]; 290 | delete trees[3]; 291 | ``` 292 | 293 | ### Câu trả lời 294 | - Khi bạn chạy code trên và `console.log(trees);` và bạn sẽ nhận được kết quả `["redwood", "bay", "cedar", undefined × 1, "maple"]` 295 | - Trong các phiên bản gần đây của Chrome, bạn sẽ thấy từ `empty` thay vì `undefined x 1` 296 | - Khi bạn chạy trên trình duyệt Firefox thì bạn sẽ nhận được kết quả `["redwood", "bay", "cedar", undefined, "maple"]` 297 | 298 | Rõ ràng, Chrome có cách hiển thị cho các index chưa được khởi tạo trong các mảng. Tuy nhiên, khi bạn kiểm tra `trees[3] === undefined` trong bất kỳ trình duyệt nào, bạn sẽ nhận được kết quả là ` true`. Rõ ràng `undefined x 1` đại diện cho các phần tử hay index chưa được khởi tạo. 299 | 300 | 301 | 302 | ## Câu 12. Kết quả của đoạn code bên dưới là gì? 303 | 304 | ```javascript 305 | var trees = ["xyz", "xxxx", "test", "ryan", "apple"]; 306 | delete trees[3]; 307 | console.log(trees.length); 308 | ``` 309 | ### Câu trả lời 310 | Kết qủa của đoạn code bên trên là `5`. Khi chúng ta sử dụng toán tử `delete` để xoá mảng các phần tử , thì độ dài mảng sẽ không ảnh hưởng. Điều này luôn đúng nếu bạn dùng `delete` cho từng phần tử của mảng. 311 | 312 | Bởi vì khi ta dùng toán tử `delete` để xoá các phần tử của mảng thì các phần từ đó sẽ được chuyển thành `undefined x 1` nên độ dài mảng không thay đổi là tất nhiên . Còn `undefined x 1` là gì, mời xem 313 | 314 | ## Câu 13. Kết quả của đoạn code bên dưới là gì? 315 | 316 | ```javascript 317 | var bar = true; 318 | console.log(bar + 0); 319 | console.log(bar + "xyz"); 320 | console.log(bar + true); 321 | console.log(bar + false); 322 | ``` 323 | ### Câu trả lời 324 | 325 | Kết quả của đoạn code sẽ là `1, "truexyz", 2, 1` , bởi vì ta có quy luật sau : 326 | - Số + Số -> Phép cộng 327 | - Biến Boolean + Số -> Phép cộng 328 | - Biến Boolean + Biến Boolean --> Phép cộng 329 | - Số + Chuỗi -> Phép nối chuỗi 330 | - Chuỗi + Biến Boolean -> Phép nối chuỗi 331 | - Chuỗi + Chuỗi -> Phép nối chuỗi 332 | 333 | 334 | 335 | ## Câu 14. Kết quả của đoạn code bên dưới là gì? 336 | 337 | ```javascript 338 | var z = 1, y = z = typeof y; 339 | console.log(y); 340 | ``` 341 | ### Câu trả lời 342 | 343 | 344 | Kết quả của code bên trên sẽ là `"undefined"` .Theo như quy luật toán tử kết hợp với mức độ ưu tiên như nhau. Quy luật của toán tử gán là `Phải sang trái ` nên `typeof y` sẽ được xem xét đầu tiên và giá trị hiện tại của nó là `"undefined"` và gán cho `z` sau đó gán cho `y` nên ta được kết quả như trên. 345 | Code sẽ được thực hiện theo thứ tự bên dưới 346 | ```javascript 347 | var z; 348 | z = 1; 349 | var y; 350 | z = typeof y; 351 | y = z; 352 | 353 | 354 | 355 | ## Câu 15. Kết quả của đoạn code bên dưới là gì? 356 | 357 | 358 | ```javascript 359 | // NFE (Named Function Expression) 360 | var foo = function bar() { return 12; }; 361 | typeof bar(); 362 | ``` 363 | 364 | ### Câu trả lời 365 | 366 | Kết quả sẽ là `Reference Error`. Để khắc phục lỗi trên ta sẽ thực hiện như sau : 367 | 368 | **Cách 1** 369 | ```javascript 370 | var bar = function() { return 12; }; 371 | typeof bar(); 372 | ``` 373 | 374 | **Cách 2** 375 | 376 | ```javascript 377 | function bar() { return 12; }; 378 | typeof bar(); 379 | ``` 380 | 381 | Định nghĩa hàm chỉ có thể có một biến tham chiếu đó là tên hàm , Ở Cách 1 `bar` tham chiếu đến một `anonymous function` và trong Cách 2 chúng ta có định nghĩa `bar` là một tên hàm 382 | 383 | ```javascript 384 | var foo = function bar() { 385 | // foo is visible here 386 | // bar is visible here 387 | console.log(typeof bar()); // Works here :) 388 | }; 389 | // foo is visible here 390 | // bar is undefined here 391 | ``` 392 | 393 | **CẬP NHẬT MỖI TUẦN - NHỚ STAR ĐỂ THEO DÕI CÂU HỎI MỚI NHÉ** 394 | 395 | 396 | --------------------------------------------------------------------------------