43 Câu hỏi JavaScript Nâng Cao giúp trả lời Phỏng vấn "Mượt mà" hơn

Ngày đăng: 04/04/2021   -    Cập nhật: 08/04/2021
Javascript là ngôn ngữ cực kỳ phổ biến. Javascript kết hợp với HTML, CSS là bộ 3 huyền thoại trong lập trình web.


Hơn nữa, trong một vài năm trở lại đây Javacript lại càng nổi tiếng hơn bởi khả năng viết Ứng dụng đa nền tảng với React Native, khả năng viết Back end bằng NodeJS giống như ngôn ngữ PHP, JAVA hay là PYTHON...


!!!Đợi chút: Nếu bạn muốn học lập trình bài bản, thực tế, hỗ trợ đầu ra thì xem ngay!




  • Và đặc biệt, nếu bạn muốn chuyên sâu về JavaScript thì tham gia ngay KHÓA HỌC FRONT END (Với ReactJS)


Ngôn ngữ lập trình Javascript cực kỳ linh động. Và cũng chính vì tính linh động của Javascript mà khiến chúng ta rất dễ dàng bắt đầu nhưng lại khó control khi nâng cao.


Tuy nhiên, đừng lo, dưới đây là tổng hợp Giải đáp 43 Câu hỏi Javascript nâng cao sẽ giúp bạn bước ra khỏi vùng "Normal Dev", gây ấn tượng với nhà tuyển dụng.



43 câu hỏi Javascript nâng cao

43 câu hỏi Javascript nâng cao

 
Note: Nếu bạn đã có kỹ năng JS tốt. Hãy thử sức với câu hỏi mà không có câu trả lời tại đây.


> Và nếu như bạn vẫn còn mơ hồ về kiến thức JS thì hãy HỌC JAVASCRIPT CƠ BẢN 


Câu hỏi 1: Hoisting trong Javascript xảy ra như thế nào?



Trước tiên bạn thử đoán kết quả của chương trình Javacript sau đây là gì?


function sayHi() {
  console.log(name);
  console.log(age);
  var name = "Lydia";
  let age = 21;
}

sayHi();


  • A: Lydia and undefined
  • B: Lydia and ReferenceError
  • C: ReferenceError and 21
  • D: undefined and ReferenceError


Đáp án: D


Bên trong Function này, trước tiên chúng ta khai báo biến name bằng từ khóa var. Điều này có nghĩa là hoisting đã xảy ra (không gian bộ nhớ được thiết lập trong giai đoạn tạo, nhưng chưa thực hiện phép gán giá trị) với giá trị mặc định là undefined, tiếp sau đó chúng ta mới thực sự định nghĩa biến name.


Trước khi cố gắng log biến name thì chúng ta chưa hề định nghĩa biến name nào, vì hoisting xảy ra và biến name giữ giá trị là undefined.



Các biến với từ khóa let (và const) cũng được hoisting, nhưng không giống như từ khóa var, chúng không thể truy cập trước khi chúng thực sự được khởi tạo.


Đây được gọi là "Vùng chết tạm thời". Do đó, khi cố gắng truy cập các biến này trước khi được khai báo. Javascript sẽ ném ra ReferenceError.



> Đọc thêm: Hoisting trong JavaScript.


Câu hỏi 2: Vòng lặp sử dụng var hoặc let trong Javascript có gì khác nhau?



Để trả lời câu hỏi này thì bạn thử đoán kết quả của chương trình Javacript sau đây là gì?


for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 1);
}

for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 1);
}


  • A: 0 1 2 and 0 1 2
  • B: 0 1 2 and 3 3 3
  • C: 3 3 3 and 0 1 2


Đáp án: C


Bởi vì hàng đợi sự kiện trong JavaScript, hàm callback setTimeout() được gọi sau khi vòng lặp được thực thi.


Và do biến i trong vòng lặp đầu tiên được khai báo bằng từ khóa var, nên giá trị này là toàn cục.


Trong vòng lặp, chúng ta đã tăng giá trị của i lên 1 lần, bằng cách sử dụng toán tử ++. Vào thời điểm hàm callback setTimeout() được gọi, i đã có giá trị bằng 3 ở trong vòng lặp for đầu tiên.



Trong vòng lặp for thứ hai, biến i được khai báo bằng từ khóa let: Biến được khai báo với từ khóa let (và const) có phạm vi dạng block hay còn gọi là block-scoped (Phạm vi trong dấu ngoặc { }).


Trong mỗi lần lặp, ta sẽ có một giá trị mới và mỗi giá trị nằm trong phạm vi của vòng lặp.



> Đọc ngay: Hiểu đơn giản về Callback trong Javascript


Câu hỏi 3: Khi sử dụng từ khóa this trong arrow function nên lưu ý điều gì?




Kết quả của chương trình Javacript sau đây là gì?


const shape = {
  radius: 10,
  diameter() {
    return this.radius * 2;
  },
  perimeter: () => 2 * Math.PI * this.radius
};

shape.diameter();
shape.perimeter();


  • A: 20 and 62.83185307179586
  • B: 20 and NaN
  • C: 20 and 63
  • D: NaN and 63


Đáp án: B


Lưu ý rằng giá trị của diameter() là một hàm thông thường, trong khi giá trị của perimeter() là một arrow function.


Với các arrow function
, không giống như các hàm thông thường, từ khóa this ở đây là đề cập đến phạm vi hiện tại của nó (nơi nó được gọi).


Điều này có nghĩa là khi chúng ta gọi đến permeter(), nó không đề cập đến đối tượng shape, mà là phạm vi xung quanh của nó (ví dụ như đề cập đến window)


Kết quả là không có giá trị radius trên đối tượng đó, nó trả về undefined.



Câu hỏi 4: Chuyển đổi số bằng toán tử +, tính chất truthy value



Kết quả của chương trình Javacript sau đây là gì?


+true;
!"ICT Hà Nội";


  • A: 1 and false
  • B: false and NaN
  • C: false and false


Đáp án: A


Toán tử + ở đây đã chuyển đổi một toán hạng thành một số. true1false0.


Do trong Javascript thì chỉ có:



  • Kiểu Boolean có falsy value là false
  • Kiểu Number có falsy value là 0NaN
  • Kiểu String có falsy value là ''
  • Kiểu null là có falsy value null
  • Kiểu undefined có falsy value là undefined


Vậy chúng ta có tổng cộng là 6 falsy value. Các giá trị còn lại đều là truthy value.


Chính vì thế chuỗi 'ICT Hà Nội' là một truthy value. Do đó phủ định của truthy value. Dĩ nhiên kết quả sẽ trả về giá trị là false.


Câu 5: Sự khác nhau khi sử dụng dấu ngoặc [ ] và toán tử dot để truy cập Object là gì?



Kết quả của chương trình Javacript sau đây là gì?


const bird = {
  size: "small"
};

const mouse = {
  name: "Mickey",
  small: true
};


  • A: mouse.bird.size không hợp lệ
  • B: mouse[bird.size] không hợp lệ
  • C: mouse[bird["size"]] không hợp lệ
  • D: Tất cả đều hợp lệ


Đáp án: A


Trong JavaScript, tất cả các object key là chuỗi (trừ khi đó là Symbol). Mặc dù chúng ta có thể không gõ chúng dưới dạng chuỗi, chúng luôn được chuyển đổi thành chuỗi.


JavaScript thông dịch (hoặc unboxes) các statement. Khi chúng ta sử dụng ký hiệu ngoặc vuông, nó sẽ thấy dấu ngoặc vuông mở đầu tiên [ và tiếp tục cho đến khi tìm thấy dấu đóng ]. Sau đó, nó sẽ đánh giá statement.


Đối với mouse[bird.size]: Đầu tiên nó sẽ đánh giá bird.size, có giá trị là "small". Do đó mouse["small"] sẽ trả về giá trị true.


Tuy nhiên, đối với việc sử dụng dấu chấm . thì hành động này lại không xảy ra. Object mouse không có key nào gọi là bird , điều này có nghĩa là mouse.bird sẽ trả về undefined .


Sau đó, chúng ta gọi đến size cũng bằng cách sử dụng toán tử dot . là: mouse.bird.size. Từ mouse.bird đã là undefined thì chúng ta đang thực sự gọi là undefined.size 


Dẫn tới, điều này là không hợp lệ, lúc này bạn sẽ nhận được một lỗi như là: Cannot read property "size" of undefined



Câu hỏi 6: Tương tác bằng tham chiếu trong Javascript là thế nào?



Kết quả của chương trình Javacript sau đây là gì?


let c = { greeting: "Hey!" };
let d;

d = c;
c.greeting = "Hello";
console.log(d.greeting);


  • A: Hello
  • B: Hey
  • C: undefined
  • D: ReferenceError
  • E: TypeError

 
Đáp án: A


Trong JavaScript, tất cả các object tương tác bằng tham chiếu (reference) khi thiết lập chúng bằng nhau.


Đầu tiên, biến c giữ một object. Sau đó, chúng ta gán d với tham chiếu c (đang giữ một object)




Khi chúng ta thay đổi object đồng nghĩa với việc thay đổi tất cả chúng.


Câu hỏi 7: Toán tử == và === trong Javascript khác nhau như thế nào?



Kết quả của chương trình Javacript sau đây là gì?


let a = 3;
let b = new Number(3);
let c = 3;

console.log(a == b);
console.log(a === b);
console.log(b === c);


  • A: true false true
  • B: false false true
  • C: true false false
  • D: false true true


Đáp án: C


new Number() là một constructor function được xây dựng sẵn. Mặc dù nó trông giống như một số, nhưng nó không thực sự là một số: Nó có một loạt các tính năng bổ sung và là một đối tượng.


Khi chúng ta sử dụng toán tử ==, nó chỉ kiểm tra xem nó có cùng giá trị hay không. Cả hai đều có giá trị là 3, vì vậy nó trả về true.


Tuy nhiên, khi chúng ta sử dụng toán tử ===, thì sẽ phải so sánh cả giá trị và cả kiểu của nó. Do new Number() không phải là một số, nó là một object.


Dẫn tới cả hai phép so sánh đều trả lại false.



Câu hỏi 8: Hiểu hơn về hàm Static trong Javascript? 



Kết quả của chương trình Javacript sau đây là gì?


class Chameleon {
  static colorChange(newColor) {
    this.newColor = newColor;
    return this.newColor;
  }

  constructor({ newColor = "green" } = {}) {
    this.newColor = newColor;
  }
}

const freddie = new Chameleon({ newColor: "purple" });
freddie.colorChange("orange");


  • A: orange
  • B: purple
  • C: green
  • D: TypeError


Đáp án: D


Hàm colorChange là ở dạng static. Các phương thức static được thiết kế để chỉ ở trên hàm constructor mà chúng được tạo và không thể truyền lại cho bất kỳ child nào.


freddie là một child, do đó hàm không thể truyền lại, và không có sẵn trên freddie nên TypeError sẽ được ném ra.



Câu hỏi 9: Về cơ bản thì sử dụng 'use strict' để làm gì?



Kết quả của chương trình Javacript sau đây là gì?


let greeting;
greetign = {}; // Giả sử bị lỗi đánh máy!
console.log(greetign);


  • A: {}
  • B: ReferenceError: greetign is not defined
  • C: undefined


Đáp án: A


Nó log ra một object, bởi vì chúng ta vừa tạo một object trên global object. Khi gõ lỗi greeting thành greetign, trình thông dịch JS thực sự đã hiểu tình huống này như là global.greetign = {} (hoặc window.greetign = {} nếu ở trên trình duyệt)



Để tránh điều này, chúng ta có thể sử dụng 'use strict'. Cách này đảm bảo rằng bạn đã khai báo một biến trước khi gián nó cho bất cứ thứ gì.


> Đọc thêm: Strict Mode trong JavaScript



Câu hỏi 10: Điều gì xảy ra khi tạo thuộc tính cho hàm giống như object?



Kết quả của chương trình Javacript sau đây là gì?


function bark() {
  console.log("Woof!");
}

bark.animal = "dog";


  • A: Không có gì. Thế này hoàn toàn ok.
  • B: SyntaxError. You cannot add properties to a function this way.
  • C: undefined
  • D: ReferenceError


Đáp án: A


Điều này là hoàn toàn có thể trong JavaScript, bởi vì các hàm là các object! (Tất cả mọi thứ ngoài các kiểu nguyên thủy đều là các object)


Một hàm là một loại object đặc biệt. Code bạn tự viết không phải là hàm thực tế. Hàm này là một object có thuộc tính. Thuộc tính này là bất khả xâm phạm.



Câu hỏi 11: Thêm thuộc tính vào constructor thì xảy ra điều gì?



Kết quả của chương trình Javacript sau đây là gì?


function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
}

const member = new Person("Lydia", "Hallie");
Person.getFullName = function() {
  return `${this.firstName} ${this.lastName}`;
};

console.log(member.getFullName());


  • A: TypeError
  • B: SyntaxError
  • C: Lydia Hallie
  • D: undefined undefined


Đáp án: A


Bạn không thể thêm thuộc tính vào hàm constructor như bạn có thể với các object thông thường.


Nếu bạn muốn thêm một hàm cho tất cả các object cùng một lúc, bạn phải sử dụng prototype để thay thế. Vì vậy, trong trường hợp này bạn phải làm thế này:



Person.prototype.getFullName = function() {
  return `${this.firstName} ${this.lastName}`;
};


Bằng cách này thì member.getFullname() sẽ làm việc. Tại sao lại thế?


Giả sử nếu chúng ta đã thêm phương thức này vào chính hàm constructor. Có lẽ không phải mọi Person đều cần phương thức này.


Điều này sẽ lãng phí rất nhiều dung lượng bộ nhớ, vì chúng vẫn có thuộc tính đó, chiếm không gian bộ nhớ cho mỗi phiên bản Person.


Thay vào đó, nếu chúng ta chỉ thêm nó vào prototype, lúc đó chúng ta chỉ có một vị trí trong bộ nhớ, nhưng tất cả Person đều có quyền truy cập vào nó!



Câu hỏi 12: Khởi tạo đối tượng có từ khóa newkhông có từ khóa new khác gì nhau?



Kết quả của chương trình Javacript sau đây là gì?


function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
}

const lydia = new Person("Lydia", "Hallie");
const sarah = Person("Sarah", "Smith");

console.log(lydia);
console.log(sarah);


  • A: Person {firstName: "Lydia", lastName: "Hallie"} and undefined
  • B: Person {firstName: "Lydia", lastName: "Hallie"} and Person {firstName: "Sarah", lastName: "Smith"}
  • C: Person {firstName: "Lydia", lastName: "Hallie"} and {}
  • D:Person {firstName: "Lydia", lastName: "Hallie"} and ReferenceError


Đáp án: A


Đối với sarah, chúng ta đã không sử dụng từ khóa new. Khi sử dụng từ khóa new, nó đề cập đến empty object mới mà chúng ta tạo. Tuy nhiên, nếu bạn không thêm new, nó sẽ tìm đến global object!


Khi nói rằng this.firstName sẽ tương đương với "Sarah"this.lastName sẽ bằng "Smith".


Bản chất thực sự của hành động trên là định nghĩa global.firstName = 'Sarah' và 
global.lastName = 'Smith' 


Chính sarah thì là undefined



Câu 13: 3 Giai đoạn của event propagation là gì?



  • A: Target > Capturing > Bubbling
  • B: Bubbling > Target > Capturing
  • C: Target > Bubbling > Capturing
  • D: Capturing > Target > Bubbling


Đán án: D


Trong giai đoạn Capturing, các sự kiện đi qua phần tử đầu tiên xuống phần tử mục tiêu. Sau đó nó target vào phần tử mục tiêu, và Bubbling bắt đầu


Câu hỏi 14: Tất cả các object đều có prototype?



  • A: true
  • B: false


Đáp án: B


Tất cả các object đều có prototype, ngoại trừ base object. Base object có quyền truy cập vào một số phương thức và thuộc tính, chẳng hạn như .toString 



Đây là lý do tại sao bạn có thể sử dụng các phương thức JavaScript được tích hợp sẵn! Tất cả các phương thức như vậy có sẵn trên prototype.


Mặc dù JavaScript không thể tìm thấy nó trực tiếp trên object của bạn, nhưng nó đi xuống prototype chain và tìm thấy nó ở đó, điều này giúp bạn có thể truy cập nó.


Câu hỏi 15: Cộng 1 số với một chuỗi thì ra kết quả gì?




Kết quả của chương trình Javacript sau đây là gì?


function sum(a, b) {
  return a + b;
}

sum(1, "2");


  • A: NaN
  • B: TypeError
  • C: "12"
  • D: 3


Đáp án: C


Javascript là một dynamic language: Chúng ta không chỉ định kiểu biến nhất định là gì.


Giá trị có thể tự động được chuyển thành một loại mà bạn chưa biết, đó là tiềm ẩn được gọi là loại implicit type coercion (ép buộc). Coercion được chuyển đổi từ một kiểu này sang kiểu khác.


Trong ví dụ này, JavaScript đã chuyển đổi số 1 thành một string để hàm có ý nghĩa và trả về một giá trị. Trong quá trình cộng kiểu number (1) và kiểu string ('2'), number đã được coi là một string.


Vì vậy khi sử dụng toán tử + để cộng hai chuỗi lại với nhau như '1' + '2' sẽ trả về kết quả là '12'.



Câu 16: Sự khác biệt của number++ và ++number là gì?



Kết quả của chương trình Javacript sau đây là gì?


let number = 0;
console.log(number++);
console.log(++number);
console.log(number);


  • A: 1 1 2
  • B: 1 2 2
  • C: 0 2 2
  • D: 0 1 2


Đáp án: C


Toán tử ++ được thêm làm hậu tố hoạt động như sau:



  • Đầu tiên nó trả về giá trị
  • Sau đó mới tăng lên một đơn vị


Toán tử ++ được thêm làm tiền tố hoạt động như sau:


  • Đầu tiên nó tăng lên một đơn vị
  • Sau đó trả về giá trị


Kết quả như sau:

let number = 0;
console.log(number++); //Log ra number sau đó mới tăng number lên 1 đơn vị
console.log(++number); //Tăng number lên 1 đơn vị, number = 2 và log ra console
console.log(number); // Log ra giá trị number hiện tại là 2



> Đọc thêm: Toán tử trong JavaScript

 

Câu 17: Nội suy chuỗi với Tagg Template Literal trong ES6 là gì?



Xem xét ví dụ Javascript sau đây:


function getPersonInfo(one, two, three) {
  console.log(one);
  console.log(two);
  console.log(three);
}

const person = "Lydia";
const age = 21;

getPersonInfo`${person} is ${age} years old`;


  • A: "Lydia" 21 ["", " is ", " years old"]
  • B: ["", " is ", " years old"] "Lydia" 21
  • C: "Lydia" ["", " is ", " years old"] 21


Đáp án: B


Nếu bạn sử dụng tagg template literal, giá trị của đối số đầu tiên luôn là một mảng của các giá trị chuỗi. Các đối số còn lại nhận được các giá trị của các biểu thức được truyền qua!


Câu 18: Truyền object như tham số để so sánh các object với nhau thì xảy ra vấn đề gì?



Xem xét ví dụ Javascript sau đây:


function checkAge(data) {
  if (data === { age: 18 }) {
    console.log("You are an adult!");
  } else if (data == { age: 18 }) {
    console.log("You are still an adult.");
  } else {
    console.log(`Hmm.. You don't have an age I guess`);
  }
}

checkAge({ age: 18 });


Kết quả là gì?


  • A: You are an adult!
  • B: You are still an adult.
  • C: Hmm.. You don't have an age I guess


Đáp án: C


Khi kiểm tra sự bằng nhau, các dữ liệu nguyên thủy được so sánh bởi giá trị của chúng, trong khi các object được so sánh bằng tham chiếu của chúng.


JavaScript kiểm tra xem các object có tham chiếu đến cùng một vị trí trong bộ nhớ không.


Hai object mà chúng ta đang so sánh không có điều đó: object chúng ta truyền dưới dạng tham số đề cập đến một vị trí khác trong bộ nhớ so với đối tượng chúng ta đã sử dụng để kiểm tra sự bằng nhau.



Đây là lý do cả hai { age: 18 } === { age: 18 }  { age: 18 } == { age: 18 } trả về giá trị false. 


Câu hỏi 19: Hiểu thêm một chút về toán tử Spread hay còn gọi là toán tử ...



Xem xét ví dụ Javascript sau đây:


function getAge(...args) {
  console.log(typeof args);
}

getAge(21);


  • A: "number"
  • B: "array"
  • C: "object"
  • D: "NaN"


Đáp án: C


Toán tử spread ... (... args) trả về một mảng các đối số. Mảng là một object, vì thế typeof args sẽ trả về object


  • Bạn có thể tìm hiểu rõ hơn về Spread Opeartor tại đây.


Câu hỏi 20: "use strict" có tác dụng gì?



Xem xét ví dụ Javascript sau đây:


function getAge() {
  "use strict";
  age = 21;
  console.log(age);
}

getAge();


  • A: 21
  • B: undefined
  • C: ReferenceError
  • D: TypeError


Đáp án: C


Với việc sử dụng "use strict" hay còn gọi là "sử dụng nghiêm ngặt", bạn có thể đảm bảo rằng bạn không vô tình khai báo biến toàn cục (Global variable).


Chúng ta chưa bao giờ khai báo biến age, và vì chúng ta sử dụng "use strict" nên chương trình sẽ ném ra một lỗi reference error.


Nếu chúng tôi không sử dụng "use strict", chương trình sẽ hoạt động và trả về giá trị 21 vì biến age lúc này là biến toàn cục.





Câu hỏi 21: Tác dụng của eval là gì trong Javascript?



Xem xét ví dụ Javascript sau đây:


const sum = eval("10*10+5");


  • A: 105
  • B: "105"
  • C: TypeError
  • D: "10*10+5"


Đáp án: A


eval đánh giá các mã được truyền dưới dạng một chuỗi. Nếu đó là một biểu thức, như trong trường hợp này, nó sẽ đánh giá biểu thức.


Biểu thức là 10 * 10 + 5 vì thế kết quả sẽ trả về số 105.



Câu hỏi 22: Dữ liệu được lưu trữ trong sessionStorage bị xóa khi nào?



Hãy xem xét đoạn code sau:


sessionStorage.setItem("cool_secret", 123);


  • A: Mãi Mãi, các dữ liệu không bị mất. 
  • B: Khi người dùng đóng tab.
  • C: Khi người đóng lại toàn bộ trình duyệt, không chỉ là đóng tab. 
  • D: Khi người dùng dùng tắt máy tính của họ.


Đáp án: B


Dữ liệu được lưu trữ trong sessionStorage sẽ bị xóa sau khi đóng tab.


Nếu bạn sử dụng localStorage, dữ liệu sẽ ở đó mãi mãi, trừ khi localStorage.clear() được gọi.


Câu hỏi 23: Khai báo nhiều biến cùng tên trong cùng phạm vi có được không?



Hãy xem xét ví dụ sau:


var num = 8;
var num = 10;

console.log(num);


  • A: 8
  • B: 10
  • C: SyntaxError
  • D: ReferenceError


Đáp án: B


Với từ khóa var, bạn có thể khai báo nhiều biến có cùng tên. Biến được khai báo sau cùng sẽ giữ giá trị mới nhất.


Nhưng bạn không thể làm thế với let hoặc const vì chúng nằm trong block-scoped.



> Đọc thêm: Phạm vi biến trong JavaScript


Câu hỏi 24: Oject key được coi là kiểu gì?



Xem xét đoạn mã sau:


const obj = { 1: "a", 2: "b", 3: "c" };
const set = new Set([1, 2, 3, 4, 5]);

obj.hasOwnProperty("1");
obj.hasOwnProperty(1);
set.has("1");
set.has(1);


Kết quả là?


  • A: false true false true
  • B: false true true true
  • C: true true false true
  • D: true true true true


Đáp án: C


Tất cả các object key (trừ symbol) đều được coi là chuỗi, ngay cả khi bạn không tự gõ nó như là một chuỗi.


Đây là lý do tại sao obj.hasOwnProperty ('1') cũng trả về true


Tuy nhiên, nó không hoạt động với set, không có "1" trong set dẫn đến set.has('1') trả về false.


Nó có kiểu số là 1, vì thế set.has(1) trả về true



Câu hỏi 25: 2 key cùng tên trong object sẽ gây ra vấn đề gì?



Chúng ta có đoạn code:


const obj = { a: "one", b: "two", a: "three" };
console.log(obj);


Kết quả nhận được sẽ là?


  • A: { a: "one", b: "two" }
  • B: { b: "two", a: "three" }
  • C: { a: "three", b: "two" }
  • D: SyntaxError


Đáp án: C


Nếu bạn có hai key có cùng tên, key sẽ được thay thế. Nó vẫn sẽ ở vị trí đầu tiên, nhưng với giá trị được chỉ định cuối cùng.



Câu hỏi 26: Có phải Javascript global execution context tạo ra 2 thứ: global object và từ khóa "this"?



Đáp án: Đúng


Về cơ bản thì bối cảnh thực thi toàn cầu (Global execution context) giúp bạn có thể truy cập ở mọi nơi trong code của bạn.



Câu hỏi 27: Tác dụng của continue là gì?



Chúng ta có ví dụ sau:


for (let i = 1; i < 5; i++) {
  if (i === 3) continue;
  console.log(i);
}


Bạn đoán xem kết quả của chương trình trên là gì?


  • A: 1 2
  • B: 1 2 3
  • C: 1 2 4
  • D: 1 3 4


Đáp án: C


Câu lệnh continue bỏ qua một lần lặp nếu một điều kiện nhất định trả về true.



Câu hỏi 28: Có thể thêm thuộc tính vào một string hay không?



Ví dụ:


String.prototype.giveLydiaPizza = () => {
  return "Just give Lydia pizza already!";
};

const name = "Lydia";

name.giveLydiaPizza();


  • A: "Just give Lydia pizza already!"
  • B: TypeError: not a function
  • C: SyntaxError
  • D: undefined


Đáp án: A


String là một buitl-in constructor, vì thế chúng ta có thể thêm các thuộc tính vào. Mình chỉ thêm một phương thức vào nguyên mẫu của nó.


Các chuỗi nguyên thủy được tự động chuyển đổi thành một string object, được tạo bởi prototype function.


Vì vậy, tất cả các string (string object) đều có quyền truy cập vào phương thức đó!



Câu hỏi 29: Đặt object làm key thì chúng sẽ hoạt động như thế nào?




Ta có ví dụ sau:


const a = {};
const b = { key: "b" };
const c = { key: "c" };

a[b] = 123;
a[c] = 456;

console.log(a[b]);


  • A: 123
  • B: 456
  • C: undefined
  • D: ReferenceError


Đáp án: B


Các Object key được tự động chuyển thành chuỗi. Ví chúng ta đang cố gắng đặt một object làm key cho object a, với giá trị 123.


Tuy nhiên, khi chúng ta xâu chuỗi một object, nó sẽ trở thành "[Object object]". Vì vậy, những gì chúng ta đang nói với Javascript ở đây đó là a["Object object"] = 123.


Sau đó chúng ta lại làm lại tương tự một lần nữa.


c là một object khác mà chúng ta đang ngầm xâu chuỗi. Vì vậy, a["Object object"] = 456 


Sau đó chúng ta log a[b], thực sự là a["Object object"]. Và chúng ta đã đặt nó bằng 456, vậy kết quả nhận được là 456.



Câu hỏi 30: Tìm hiểu một chút về stack trong Javascript.



Ví dụ:


const foo = () => console.log("First");
const bar = () => setTimeout(() => console.log("Second"));
const baz = () => console.log("Third");

bar();
foo();
baz();


Lựa chọn đáp án đúng nhất:


  • A: First Second Third
  • B: First Third Second
  • C: Second First Third
  • D: Second Third First


Đáp án: B


Chúng ta có một hàm setTimeout và gọi nó trước. Tuy nhiên, nó đã được log cuối cùng.


Điều này là do trong các trình duyệt, chúng ta không chỉ có runtime engine, chúng ta cũng có một thứ gọi là WebAPI. WebAPI cung cấp cho chúng ta hàm setTimeout để bắt đầu, và ví dụ như DOM.


Sau khi callback được đẩy lên WebAPI, chính hàm setTimeout (nhưng không phải là callback!) Được bật ra khỏi stack.


Bây giờ, foo được gọi và 'First' đang được log.


foo được bật ra khỏi stack, và baz được gọi. 'Third' được log


WebAPI không thể chờ đẩy nhiệm vụ vào vào stack bất cứ khi nào nó sẵn sàng. Thay vào đó, nó đẩy hàm callback đến một thứ gọi là hàng đợi (queue).


Đây là nơi một vòng lặp sự kiện bắt đầu hoạt động. Một vòng lặp sự kiện nhìn vào stack và nhiệm vụ trong 
hàng đợi. Nếu stack trống, nó sẽ lấy nhiệm vụ đầu tiên trên hàng đợi và đẩy nó lên stack.


Lúc này bar được gọi, 'Second' được log và nó bật ra khỏi stack.



Câu hỏi 31: Envet.target gì xảy ra khi click vào button?



Chúng ta có ví dụ sau:


<div onclick="console.log('first div')">
  <div onclick="console.log('second div')">
    <button onclick="console.log('button')">
      Click!
    </button>
  </div>
</div>


  • A: first div
  • B: secon div
  • C: button
  • D: Một mảng của tất cả các div lồng nhau

Đáp án: C


Phần tử lồng nhau sâu nhất gây ra sự kiện là mục tiêu của sự kiện. Bạn có thể ngừng bubbling bằng event.stopPropagation.



Câu hỏi 32: Khi bấm vào đoạn văn bản thì log ra cái gì?



Đoạn code như sau:


<div onclick="console.log('div')">
  <p onclick="console.log('p')">
    Click here!
  </p>
</div>


  • A: p div
  • B: div p
  • C: p
  • D: div

Đáp án: A


Nếu chúng ta click vào p, chúng ta sẽ thấy hai bản ghi: pdiv.


Trong quá trình truyền bá sự kiện, có 3 giai đoạn: bắt giữ (capturing), nhắm mục tiêu (target) và sủi bọt (bubbling).


Theo mặc định, các trình xử lý sự kiện (event handlers) được thực thi trong giai đoạn sủi bọt (trừ khi bạn đặt useCapture thành true). Nó đi từ phần tử lồng sâu nhất ra bên ngoài.



Câu hỏi 33: Sự khác nhau của hàm call và hàm bind là gì?



Chúng ta có đoạn code sau:


const person = { name: "Lydia" };

function sayHi(age) {
  console.log(`${this.name} is ${age}`);
}

sayHi.call(person, 21);
sayHi.bind(person, 21);


Bạn chọn đáp án nào?



  • A: undefined is 21 Lydia is 21
  • B: function function
  • C: Lydia is 21 Lydia is 21
  • D: Lydia is 21 function


Đáp án: D


Đối với với cả hai trường hợp, chúng ta có thể truyền object mà chúng ta muốn this tham chiếu đến. Tuy nhiên, .call được thực thi ngay lập tức!


Bạn có thể hiểu hàm call là: Gọi hàm và cho phép bạn truyền vào một object và các đối số phân cách nhau bởi dấu phẩy.


VD: function.call(thisArg, arg1, arg2, ...)



Còn hàm bind là: Trả về một hàm số mới, cho phép bạn truyền vào một object và các đối số phân cách nhau bởi dấu phẩy.


VD: var newFunction = fun.bind(thisArg[, arg1[, arg2[, ...]]])



Vì .bind trả về một copy của function, nhưng với một bối cảnh bị ràng buộc (bound context)! Nó không được thực thi ngay lập tức.


Câu hỏi 34: typeof sayHi() là gì?



function sayHi() {
  return (() => 0)();
}

typeof sayHi();



  • A: "object"
  • B: "number"
  • C: "function"
  • D: "undefined"


Đáp án: B


Hàm sayHi trả về giá trị trả về của hàm được gọi ngay lập tức (IIFE). Hàm này trả về 0, là loại 'number'.


FYI: Có 7 built-in types: null, undefined, boolean, number, string, object and symbol. "function" không phải là một kiểu, nhưng vì các hàm là các object nên nó thuộc loại object.



Câu 35: Giá trị nào dưới đây là falsy?



0;
new Number(0);
("");
(" ");
new Boolean(false);
undefined;


  • A: 0''undefined
  • B: 0new Number(0)''new Boolean(false)undefined
  • C: 0''new Boolean(false)undefined
  • D: All of them are falsy


Đáp án: A


Như đã liệt kê 6 falsy ở câu hỏi số 4. Ngoài 6 falsy value này thì các loại khác đều là truthy value.


Hàm constructor giống như new Numbernew Boolean đều là truthy value.



Câu 36: Kiểu của Kiểu của nummber trả về kết quả gì?



Chúng ta có đoạn mã này:


console.log(typeof typeof 1);

 
Theo bạn thì đáp án là gì?


  • A: "number"
  • B: "string"
  • C: "object"
  • D: "undefined"


Đáp án: B


typeof 1 trả về "number". Do đó, typeof "number" trả về "string"



Câu hỏi 37: Set giá trị vượt quá độ dài của mảng trong Javascript thì xảy ra vấn đề gì?



const numbers = [1, 2, 3];
numbers[10] = 11;
console.log(numbers);


  • A: [1, 2, 3, 7 x null, 11]
  • B: [1, 2, 3, 11]
  • C: [1, 2, 3, 7 x empty, 11]
  • D: SyntaxError


Đáp án: C


Trong Java thì điều này không được phép. Nhưng trong Javascript thì khi bạn set một giá trị có index vượt quá độ dài của mảng, JavaScript sẽ tạo ra một thứ gọi là 'empty'.


Chúng thực sự có giá trị undefined, nhưng bạn sẽ thấy như là: [1, 2, 3, 7 x empty, 11]



tùy thuộc vào nơi bạn chạy nó (nó khác nhau đối với các trình duyệt, node, v.v.)


Câu 38: Chương trình Javascript sau trả về kết quả gì?



(() => {
  let x, y;
  try {
    throw new Error();
  } catch (x) {
    (x = 1), (y = 2);
    console.log(x);
  }
  console.log(x);
  console.log(y);
})();


  • A: 1 undefined 2
  • B: undefined undefined undefined
  • C: 1 1 2
  • D: 1 undefined undefined


Đáp án: A


Khối catch nhận đối số x. Biến này không giống như x khi chúng ta truyền đối số. Biến x này là block-scoped.


Sau đó, chúng ta đặt biến block-scoped này bằng 1 và đặt giá trị của biến y. Bây giờ, chúng ta log biến block-scoped x, kết quả bằng 1.


Bên ngoài khối catch, x vẫn là undefinedy là 2. Khi chúng ta muốn console.log(x) bên ngoài khối catch, nó trả về undefinedy trả về 2.


> Đọc thêm: Try catch trong JavaScript



Câu 39: Mọi thứ trong JavaScript đều là gì?



  • A: primitive or object
  • B: function or object
  • C: only objects
  • D: number or object


Đáp án: A


JavaScript chỉ có các kiểu primitive (Kiểu nguyên thủy) và objects.


Kiểu nguyên thủy bao gồm: booleannullundefinedbigintnumberstring, and symbol



Điều khác biệt giữa primitive với object là primitive không có bất kỳ thuộc tính hay phương thức nào. Tuy nhiên, bạn cần lưu ý rằng 'foo'.toUpperCase() ước tính là 'FOO' và không dẫn đến TypeError.


Điều này là do khi bạn cố gắng truy cập một thuộc tính hoặc phương thức trên một kiểu primitive như string, JavaScript sẽ bao bọc đối tượng bằng một wrapper classes.


Và sau đó ngay lập tức loại bỏ wrapper sau khi biểu thức được ước tính. Tất cả các primitive ngoại trừ null và undefined đều có hành vi này.



Câu hỏi 40: Bạn đã hiểu về reduce chưa?



[[0, 1], [2, 3]].reduce(
  (acc, cur) => {
    return acc.concat(cur);
  },
  [1, 2]
);


  • A: [0, 1, 2, 3, 1, 2]
  • B: [6, 1, 2]
  • C: [1, 2, 0, 1, 2, 3]
  • D: [1, 2, 6]


Đáp án: C


[1, 2] là giá trị ban đầu của chúng ta. Đây là giá trị chúng ta bắt đầu và giá trị đầu tiên của acc.


Trong vòng đầu tiên, acc là [1,2] và cur là [0, 1]. Chúng ta ghép chúng lại, kết quả là [1, 2, 0, 1].


Sau đó, [1, 2, 0, 1] là acc và [2, 3] là cur. Chúng ta nối chúng và nhận được kết quả [1, 2, 0, 1, 2, 3].


Nếu bạn chưa hiểu rõ, mình kiến nghị bạn nên tìm hiểu thêm về reduce trong JavaScript.


Nó là một phương thức rất thường sử dụng khi bạn học React.js



Câu hỏi 41: Câu hỏi về toán tử !! tính chất truthy và falsy của dữ liệu.



!!null;
!!"";
!!1;


  • A: false true false
  • B: false false true
  • C: false true true
  • D: true true false


Đáp án: B


null là falsy!null trả về true!true trả về false.
 

"" là falsy!"" trả về true!true trả về false.
 

1 là truthy!1 trả về false!false trả về true
 


Quá đơn giản phải không nào?


Câu 42: Phương thức setInterval trả về cái gì?



setInterval(() => console.log("Hi"), 1000);

  • A: Một id duy nhất
  • B: Số mili giây được chỉ định
  • C: passed function
  • D: undefined


Đáp án: A


Nó trả về một id duy nhất. Id này có thể được sử dụng để xóa khoảng nghỉ đó với hàm clearInterval().



Câu hỏi 43: Cách từng ký tự trong chuỗi đơn giản, ngắn gọn như thế nào?



Bạn thử chạy lệnh này xem:


[..."Lydia"];


Bạn đoán kết quả sẽ là gì?


  • A: ["L", "y", "d", "i", "a"]
  • B: ["Lydia"]
  • C: [[], "Lydia"]
  • D: [["L", "y", "d", "i", "a"]]


Đáp án: A


Một chuỗi là được ghép từ các ký tự. Toán tử spread ánh xạ mỗi ký tự thành một phần tử


Note: Nếu không sử dụng toán tử Spread. Bạn cũng có thể tách ký tự bằng phương thức split


> Đọc ngay: 15+ Javascript String Method thường gặp nhất
 

Chúc mừng bạn đã nâng cao thêm kỹ năng Lập trình Javascript của mình



Với 43 câu hỏi Javascript nâng cao, 43 vấn đề thường khiến các Lập trình viên Javascript, Lập trình viên phát triển website nhầm lẫn, khó nắm bắt Javascript trên đây.


Mình tin rằng những câu hỏi này sẽ giúp bạn load lại kiến thức Javascript và nâng cao tỷ lệ trúng tuyển của mình hơn.



  • Đừng quên giắt túi "Bảng cửu chương Git" khi đi phỏng vấn ở bất kỳ công ty công nghệ nào nhé!


Vẫn còn nhiều vấn đề mà chưa thể đi sâu hết trong một bài viết. Bạn có thể Google đề tìm hiểu sâu thêm nhé.



Tác giả - Lydia Hallie
 
 
---
HỌC VIỆN ĐÀO TẠO CNTT NIIT - ICT HÀ NỘI
Học Lập trình chất lượng cao (Since 2002). Học thực tế + Tuyển dụng ngay!
Đc: Tầng 3, 25T2, N05, Nguyễn Thị Thập, Cầu Giấy, Hà Nội
SĐT: 02435574074 - 0383.180086
Email: hello@niithanoi.edu.vn
Fanpage: https://facebook.com/NIIT.ICT/
 
#niit #icthanoi #niithanoi #niiticthanoi #hoclaptrinh #khoahoclaptrinh #hoclaptrinhjava #hoclaptrinhphp

Bình luận Facebook
Khóa học liên quan đến bài viết

KHÓA HỌC LẬP TRÌNH FRONT END VỚI REACT.JS

56 giờ
Học Lập trình Front end hiện đại với ReactJS. Học làm chủ HTML, CSS, JS và thư viện JavaScript phổ biến nhất hiện nay. Sẵn sàng đi thực tập / đi làm ngay sau khóa học.

Khóa học PHP Full stack [2023] cho người mới bắt đầu

96 giờ
Khóa học Lập trình PHP Full stack, phiên bản cập nhật lần thứ 8. Dạy Lập trình PHP bài bản từ Front end đến Back end + Laravel. Hướng dẫn làm 2 Dự Án Web lớn

KHÓA HỌC PYTHON HƯỚNG ĐỐI TƯỢNG

50 giờ
Khóa học giúp học viên sử dụng thành thạo ngôn ngữ Lập trình Python (3x). Hiểu và phát triển được Ứng dụng Web với Django Framework. Học thực hành với Giảng viên cao cấp.

Lập trình PHP với Laravel Framework

42 giờ
Khóa học Lập trình PHP với Laravel Framework được NIIT - ICT HÀ NỘI xây dựng nhằm hoàn thiện kỹ năng lập trình web các các bạn đã biết Lập trình Web PHP thuần.

Khóa học Java Full stack (IJFD)

104 giờ
Học lập trình Java Fullstack với khóa học được xây dựng theo lộ trình bài bản, từ JAVA CƠ BẢN đến JAVA WEB và nâng cao về JAVA FRAMEWORK như: Spring Boot, Hibernate
Mục lục
Đăng ký tư vấn
Nhân viên gọi điện tư vấn miễn phí sau khi đăng ký
Được cập nhật các ưu đãi sớm nhất
Hotline: 0383180086
Tên không được để trống
Số điện thoại không được để trống
Email không được để trống
Hãy đăng ký để nhận những thông tin mới nhất về học bổng mới nhất tại NIIT - ICT Hà Nội
top
Đóng lại Đăng ký học tại NIIT - ICT Hà Nội
6260+ học viên đã theo học tại NIIT - ICT Hà Nội và có việc làm tốt trong ngành lập trình. Nắm lấy cơ hội ngay hôm nay!
Chọn khóa học
  • KHÓA HỌC LẬP TRÌNH FRONT END VỚI REACT.JS
  • KHÓA HỌC LẬP TRÌNH PHP WEB
  • Khóa học PHP Full stack [2023] cho người mới bắt đầu
  • Khóa học BIG DATA với Hadoop và Spark
  • Khóa học Lập trình Android tại Hà Nội
  • [Tuyển sinh 2023] Lập trình viên Quốc tế DigiNxt
  • Khóa học Tiền lương & Phúc lợi (C&B Excel) tại Hà Nội
  • LẬP TRÌNH GAME
    • Khóa học Lập trình Game Unity
  • LẬP TRÌNH WEB FRONT END
    • KHÓA HỌC PYTHON HƯỚNG ĐỐI TƯỢNG
    • KHÓA HỌC ANGULAR & TYPESCRIPT (FRONT END)
  • LẬP TRÌNH WEB BACK END
    • LẬP TRÌNH JAVA WEB VỚI FRAME WORK
    • Lập trình Web với Django
    • Lập trình PHP với Laravel Framework
  • CHƯƠNG TRÌNH ĐÀO TẠO ỨNG DỤNG CÔNG NGHỆ
    • Khóa học Tiền lương & Phúc lợi (C&B Excel) tại TP HCM
  • LẬP TRÌNH WEB FULL STACK
    • Khóa học Java Full stack (IJFD)
  • LẬP TRÌNH MOBILE
    • FRONT-END VỚI REACTJS VÀ REACT NATIVE
    • Lập trình Android Nâng cao
  • ĐÀO TẠO CHO DOANH NGHIỆP
    • KHÓA HỌC BUSINESS ANALYSIC TỪ CƠ BẢN ĐẾN NÂNG CAO 2023
    • Khóa học Magento: Làm chủ CMS TMĐT lớn nhất
    • Khóa học IOT: Xây dựng Sản phẩm IOT với Raspberry Pi
    • Khóa học Automation Testing Chuyên nghiệp
  • KHÓA HỌC DỰ ÁN
    • Học sử dụng bộ Office: Word, Excel, Power Point, Mail chuyên nghiệp
  • KHÓA HỌC KHÁC
    • VBA Excel Toàn Tập (Cơ Bản - Nâng Cao)
    • VBA Excel Nâng cao
    • Khóa học JMeter: Performance Testing
    • Khóa học Tester đạt chuẩn Quốc tế ISTQB Foundation Level
    • Khoá Học Tester đạt chuẩn quốc tế ISTQB Advanced Level
Bạn chưa chọn khóa học cần đăng ký
Tên không được để trống
Số điện thoại không được để trống
Email không được để trống
Đăng ký học thành công!
Cảm ơn bạn đã đăng ký học tại NIIT - ICT HÀ NỘI!