interview
javascript-frontend-basics
isNaN 和 Number.isNaN 函数有什么区别

前端 JavaScript 基础面试题, isNaN 和 Number.isNaN 函数有什么区别?

前端 JavaScript 基础面试题, isNaN 和 Number.isNaN 函数有什么区别?

QA

Step 1

Q:: isNaN 和 Number.isNaN 函数有什么区别?

A:: isNaN 是全局函数,用于判断传入的值是否是 NaN(Not-a-Number)。它首先会尝试将传入的值转换为一个数字,然后判断其是否是 NaN。而 Number.isNaN 是 ES6 中新增的一个方法,它只对数值进行判断,不会进行类型转换。具体来说,如果传入的值不是类型为 Number 的 NaN,则返回 false。示例如下:


console.log(isNaN('hello')); // true
console.log(Number.isNaN('hello')); // false
console.log(isNaN(NaN)); // true
console.log(Number.isNaN(NaN)); // true

Step 2

Q:: 解释 JavaScript 中的原型链是什么?

A:: 在 JavaScript 中,每个对象都有一个私有属性(称之为 [[Prototype]]),指向另一个对象或 null。这个被指向的对象就是这个对象的原型。原型对象也有自己的原型,层层向上直到一个对象的原型为 null 为止。null 没有原型,作为原型链的终点。通过原型链,一个对象可以继承另一个对象的属性和方法。示例如下:


function Person(name) {
  this.name = name;
}
Person.prototype.greet = function() {
  console.log('Hello, ' + this.name);
};
let john = new Person('John');
john.greet(); // Hello, John

Step 3

Q:: 解释 JavaScript 中的闭包(closure)是什么?

A:: 闭包是指那些能够访问自由变量的函数。换句话说,闭包可以让你在一个内部函数中访问其外部函数的作用域。闭包是由函数和创建该函数的词法环境组合而成的。示例如下:


function outerFunction() {
  let outerVariable = 'I am outside!';
  function innerFunction() {
    console.log(outerVariable);
  }
  return innerFunction;
}
let myClosure = outerFunction();
myClosure(); // I am outside!

用途

面试这些内容是为了考察候选人对 JavaScript 基础知识的理解和掌握程度。在实际生产环境中,这些概念非常重要,理解它们能够帮助开发者编写更加健壮、易于维护的代码。例如,区分 isNaN 和 Number`.`isNaN 可以避免类型转换带来的意外错误,理解原型链可以更好地使用继承和创建对象,掌握闭包有助于编写模块化的代码和实现数据的封装。\n

相关问题

🦆
什么是 JavaScript 中的作用域scope?

作用域是指程序中变量、函数和对象的可访问范围。在 JavaScript 中,有全局作用域和局部作用域(函数作用域和块级作用域)。变量的作用域决定了它们在哪些代码段可以被访问。ES6 引入了块级作用域,使用 let 和 const 声明的变量在块级作用域内是局部的。示例如下:


let globalVar = 'I am global';
function scopeTest() {
  let localVar = 'I am local';
  console.log(globalVar); // I am global
  console.log(localVar); // I am local
}
console.log(globalVar); // I am global
console.log(localVar); // ReferenceError: localVar is not defined

🦆
解释 JavaScript 中的事件循环Event Loop是什么?

事件循环是 JavaScript 处理异步操作的机制。JavaScript 是单线程的,通过事件循环来处理异步任务,如 I/O 操作、计时器等。事件循环的运行过程包括:从任务队列中提取任务,执行任务,继续提取任务,直到任务队列为空。事件循环使得 JavaScript 能够高效地处理并发操作而不会阻塞主线程。示例如下:


console.log('Start');
setTimeout(() => {
  console.log('Timeout callback');
}, 0);
console.log('End');
// Output:
// Start
// End
// Timeout callback

🦆
解释 JavaScript 中的异步编程及其实现方式

JavaScript 中的异步编程主要通过回调函数、Promises 和 async/await 实现。回调函数是最基本的异步编程方式,但容易出现回调地狱。Promises 提供了一种更优雅的方式来处理异步操作,能够链式调用和处理错误。async/await 是基于 Promises 的语法糖,使得异步代码看起来像同步代码,增强了可读性。示例如下:


// 使用回调函数
function fetchData(callback) {
  setTimeout(() => {
    callback('Data received');
  }, 1000);
}
fetchData((data) => {
  console.log(data);
});

// 使用 Promise
function fetchDataPromise() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('Data received');
    }, 1000);
  });
}
fetchDataPromise().then((data) => {
  console.log(data);
});

// 使用 async/await
async function fetchDataAsync() {
  let data = await fetchDataPromise();
  console.log(data);
}
fetchDataAsync();