Xoắn não với phỏng vấn JavaScript 6

Posted on June 14th, 2018

Xin chào bạn đến bài viết Xoắn não với phỏng vấn JavaScript 6, hôm nay mình lại tiếp tục chia sẻ với bạn những câu hỏi phỏng vấn JavaScript rất hay.

Mời bạn theo dõi bài viết!

Xoắn não với phỏng vấn JavaScript 6 - Câu 1

let foo = function bar() {
  return "hello";
}

console.log(typeof bar);

Hỏi console in ra kết quả như thế nào? Tại sao?

Đáp án: undefined

Giải thích:

Cách khai báo hàm số như trên được gọi là Named function expression, tức là bạn đặt tên cho function expression. Khi đó, bạn có thể sử dụng hàm số ngay bên trong nội dung của hàm.

Ví dụ:

var math = {
  'factit': function factorial(n) {
    console.log(n)
    if (n <= 1)
      return 1;
    return n * factorial(n - 1);
  }
};

math.factit(3)
// => 3;2;1;

Ngược lại, khi bạn không sử dụng Named function expression thì ví dụ trên phải sửa thành:

var math = {
  'factit': function(n) {
    console.log(n)
    if (n <= 1)
      return 1;
    return n * this.factit(n - 1);
  }
};

math.factit(3)
// => 3;2;1;

Vậy Named function expression có đặc điểm gì?

Named function expression có đặc điểm là phạm vi sử dụng của nó chỉ ở bên trong hàm số.

Quay lại câu hỏi trên, bar sẽ chỉ có ý nghĩa ở bên trong hàm số, ra bên ngoài thì bar sẽ là undefined.

let foo = function bar() {
  console.log(typeof bar);

  return "hello";
}

foo();                    // => function
console.log(typeof bar);  // => undefined

Tóm lại, đáp án của câu hỏi 1 là undefined.

Ngoài ra, bạn có thể xem thêm tại đây để hiểu rõ hơn về Named function expression.

Xoắn não với phỏng vấn JavaScript 6 - Câu 2

let person = {
  name: "foo"
};

Object.preventExtensions(person);

person.name = "bar";
person.job  = "teacher";

console.log(person);

Hỏi console in ra kết quả như thế nào? Tại sao?

Đáp án: {name: "bar"}

Giải thích:

Object.preventExtensions ngăn chặn việc thêm thuộc tính vào object.

Do đó, việc thêm thuộc tính person.job = "teacher" sẽ không có ý nghĩa. Vì vậy, kết quả của câu hỏi sẽ là: {name: "bar"}.

Ngoài ra, nếu bạn sử dụng code trên ở chế độ strict mode thì bạn sẽ nhận được thông báo lỗi: TypeError: Cannot add property job, object is not extensible.

"use strict";
let person = {
  name: "foo"
};

Object.preventExtensions(person);

person.name = "bar";
person.job  = "teacher";

console.log(person);
// => TypeError: Cannot add property job, object is not extensible

Xoắn não với phỏng vấn JavaScript 6 - Câu 3

let person = {
  name: "foo"
};

Object.preventExtensions(person);
person.__proto__.sayHi = function() {
  console.log("Hi");
}

console.log(person.sayHi());

Hỏi console in ra kết quả như thế nào? Tại sao?

Đáp án: Hi

Giải thích:

Object.preventExtensions() chỉ ngăn chặn việc thêm thuộc tính vào bản thân object. Đối với prototype của object thì bạn vẫn có thể thêm vào.

Trong câu hỏi này, mình đã thêm thuộc tính sayHi vào prototype của đối tượng person. Điều này là hoàn toàn hợp lệ, nên bạn sẽ nhận được kết quả là Hi.

Xoắn não với phỏng vấn JavaScript 6 - Câu 4

let person = {
  name: "foo"
};

Object.preventExtensions(person);
person.__proto__ = { job: "teacher" };

console.log(person.job);

Hỏi console in ra kết quả như thế nào? Tại sao?

Đáp án: TypeError: #<Object> is not extensible

Giải thích:

Một đặc điểm quan trọng nữa của Object.preventExtensions() là: nó làm cho __proto__ trở thành immutable – tức là bạn có thể thay đổi giá trị của nó, nhưng không thể gán nó cho một object mới.

Trong khi đó, câu lệnh person.__proto__ = { job: "teacher" } đã gán object mới cho __proto__ của person.

Vì vậy, bạn sẽ nhận được lỗi như trên.

Xoắn não với phỏng vấn JavaScript 6 - Câu 5

let a = { x : 1, y : 2 };
let b = { y : 3, z : 4 };

Object.assign(a, b);
console.log(a, b);

Hỏi console in ra kết quả như thế nào? Tại sao?

Đáp án: {x: 1, y: 3, z: 4} {y: 3, z: 4}

Giải thích:

Phương thức Object.assign được định nghĩa như sau:

The Object.assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object. It will return the target object.

Dịch ra là:

Object.assign() được sử dụng để sao chép các giá trị của tất cả thuộc tính có thể liệt kê từ một hoặc nhiều đối tượng nguồn đến một đối tượng đích. Nó sẽ trả về đối tượng đích đó.

Trong câu hỏi trên:

  • Các thuộc tính x, y, z đều là enumerable.
  • a là đối tượng đích, b là đối tượng nguồn.

Do đó, các thuộc tính của b sẽ được copy sang a và b vẫn giữ nguyên. Trường hợp thuộc tính của a và b giống nhau (thuộc tính y) thì giá trị của thuộc tính đích sẽ bị ghi đè bởi giá trị của thuộc tính nguồn.

Xoắn não với phỏng vấn JavaScript 6 - Câu 6

let a = Object.create({ foo: 1 }, {
  bar: { value: 2 },
  baz: { value: 3, enumerable: true }
});

let b = Object.assign({}, a);
console.log(b);

Hỏi console in ra kết quả như thế nào? Tại sao?

Đáp án: {baz: 3}

Giải thích:

Khi sử dụng Object.create để tạo object như trên thì { foo: 1 } sẽ là __proto__ của object mới. Nên nó sẽ không được sao chép thông qua Object.assign.

Tiếp theo là việc định nghĩa các thuộc tính cho object:

{
  bar: { value: 2 },
  baz: { value: 3, enumerable: true }
}

Thuộc tính bar không chỉ rõ giá trị của enumerable nên nó sẽ lấy giá trị mặc định là false. Do đó, thuộc tính bar cũng sẽ không được sao chép thông qua Object.assign.

Còn lại thuộc tính baz, giá trị enumerable của nó là true. Nên thuộc tính này sẽ được sao chép thông qua Object.assign.

Vì vậy, đối tượng b chỉ có 1 thuộc tính là baz và kết quả thu được là {baz: 3}.

Kết luận

Trên đây là 6 câu hỏi phỏng vấn JavaScript cũng rất hay. Nếu bạn có cùng nhận xét với mình thì vui lòng để lại bình luận xuống phía dưới nhé!

Xin chào và hẹn gặp lại bạn trong bài viết tiếp theo, thân ái!


★ Nếu bạn thấy bài viết này hay thì hãy theo dõi mình trên Facebook để nhận được thông báo khi có bài viết mới nhất nhé: