>  기사  >  웹 프론트엔드  >  2018년 최신 JavaScript 면접 질문 26개와 답변 소개

2018년 최신 JavaScript 면접 질문 26개와 답변 소개

不言
不言앞으로
2018-11-20 15:09:5512898검색

2018년 최신 JavaScript 면접 질문 26개와 답변 소개

이 글은 2018년 최신 자바스크립트 면접 질문 26개와 답변을 소개합니다. 확실한 참고할만한 가치가 있는 친구들이 참고하시길 바랍니다. 당신에게 도움이 될 것입니다.

Stack Overflow의 2018년 연례 설문조사에 따르면 JavaScript는 6년 연속 가장 일반적으로 사용되는 프로그래밍 언어였습니다. 따라서 우리는 JavaScript가 풀 스택 개발 기술의 초석이 되었고, JavaScript와 관련된 질문이 풀 스택 개발 인터뷰에 필연적으로 포함될 것이라는 현실을 직시해야 합니다. FullStack.Cafe는 독자들이 다음 꿈의 직업을 찾을 수 있도록 돕기 위해 가장 일반적인 JavaScript 인터뷰 질문과 답변을 편집했습니다.

관련 기사 추천 : 2020년 js 면접 질문 중 가장 완벽한 모음(최신) , 프론트엔드 인터뷰 질문 (2020)

Q1: JavaScript에서 강제는 무엇을 의미하나요?

Difficulty: 0

JavaScript에서는 서로 다른 두 내장 유형 간의 변환을 캐스트라고 합니다. 캐스팅은 JavaScript에서 명시적 형식과 암시적 형식의 두 가지 형태로 제공됩니다.

명시적 캐스트의 예:

var a = "42";
var b = Number( a );
a;                // "42"
b;                // 42 -- 是个数字!

암시적 캐스트의 예:

var a = "42";
var b = a * 1;    // "42" 隐式转型成 42 
a;                // "42"
b;                // 42 -- 是个数字!

Q2: 무엇을 합니까? JavaScript의 범위는 무엇을 의미합니까?

난이도: 1

JavaScript에서는 모든 함수에 자체 범위가 있습니다. 범위는 기본적으로 변수의 모음이며 이름으로 해당 변수에 액세스하는 방법에 대한 규칙입니다. 함수 내의 코드만 함수 범위 내의 변수에 액세스할 수 있습니다.

동일한 범위 내 변수 이름은 고유해야 합니다. 범위는 다른 범위 내에 중첩될 수 있습니다. 범위가 다른 범위 내에 중첩된 경우 가장 안쪽 범위의 코드는 다른 범위의 변수에 액세스할 수 있습니다.

Q3: JavaScript의 평등을 설명하세요.

난이도: 1

JavaScript에는 엄격한 비교와 유형 변환 비교가 있습니다.

    # 🎜🎜#
  • 엄격한 비교(예: ===)는 캐스트를 허용하지 않고 두 값이 동일한지 확인합니다.

  • 추상적 비교(예: == ) 캐스팅이 허용되는 경우 두 값이 동일한지 확인합니다.

var a = "42";
var b = 42;
a == b;            // true
a === b;        // false
몇 가지 간단한 규칙:

  • 비교되는 값 중 하나라도 true이거나 false , == 대신 ===를 사용하세요.

  • 비교되는 값 중 하나라도 특정 값(0, "" 또는 []), ==가 아닌 ===를 사용해야 합니다.

  • 다른 상황에서는 ==를 사용하는 것이 안전합니다. 안전할 뿐만 아니라 많은 경우 코드를 단순화하고 읽기 쉽게 만들 수 있습니다.

Q4: 콜백 함수가 무엇인지 설명하고 간단한 예를 들어보세요.

난이도: 2

콜백 함수는 다른 함수에 매개변수로 전달되어 사용할 수 있는 함수입니다. 특정 작업 완료 후 실행됩니다. 다음은 특정 작업이 완료된 후 콘솔에 메시지를 인쇄하는 간단한 콜백 함수의 예입니다.

function modifyArray(arr, callback) {
  // 对 arr 做一些操作
  arr.push(100);
  // 执行传进来的 callback 函数
  callback();
}

var arr = [1, 2, 3, 4, 5];

modifyArray(arr, function() {
  console.log("array has been modified", arr);
});

Q5: "엄격한 사용" 기능은 무엇인가요?

Difficulty: 2

use strict는 JavaScript 코드 상단이나 함수 상단에 표시됩니다. 더 안전한 JavaScript 코드를 작성하는 데 도움이 됩니다. 실수로 전역 변수를 생성하면 오류가 발생하여 경고가 표시됩니다. 예를 들어, 다음 프로그램은 오류를 발생시킵니다:

function doSomething(val) {
  "use strict"; 
  x = val + 10;
}
x가 정의되지 않았고 전역 범위의 값이 할당되었기 때문에 오류가 발생하며, strict를 사용하는 것은 허용되지 않습니다. 다음과 같은 작은 변경으로 이 오류가 해결되었습니다.

function doSomething(val) {
  "use strict"; 
  var x = val + 10;
}

Q6: JavaScript에서 null 및 정의되지 않음을 설명합니다.

Difficulty: 2

JavaScript에는 null과 정의되지 않은 두 가지 기본 유형이 있습니다. 서로 다른 의미를 나타냅니다.

  • 초기화되지 않은 항목: 정의되지 않음

  • 현재 사용할 수 없는 항목: 널.

Q7: 다음 작업을 수행할 수 있는 함수를 작성하세요.

Difficulty: 2

var addSix = createBase(6);
addSix(10); // 返回 16
addSix(21); // 返回 27
createBase 함수에 전달된 값을 저장하는 클로저를 만들 수 있습니다. 반환된 내부 함수는 외부 함수에서 생성되고 내부 함수는 외부 함수의 변수(이 경우 baseNumber 변수)에 액세스할 수 있는 클로저가 됩니다.

function createBase(baseNumber) {
  return function(N) {
    // 我们在这里访问 baseNumber,即使它是在这个函数之外声明的。
    // JavaScript 中的闭包允许我们这么做。
    return baseNumber + N;
  }
}

var addSix = createBase(6);
addSix(10);
addSix(21);

Q8: JavaScript의 값과 유형을 설명합니다.

Difficulty: 2

  • JavaScript에 값이 입력되었지만 변수가 입력되지 않았습니다. JavaScript는 다음과 같은 기본 제공 유형을 제공합니다. #

    boolean
  • null 및 정의되지 않음
  • object
  • symbol(ES6의 새로운 기능)

Q9:解释事件冒泡以及如何阻止它?

难度:1

事件冒泡是指嵌套最深的元素触发一个事件,然后这个事件顺着嵌套顺序在父元素上触发。

防止事件冒泡的一种方法是使用 event.cancelBubble 或 event.stopPropagation()(低于 IE 9)。

Q10:JavaScript 中的 let 关键字有什么用?

难度:2

除了可以在函数级别声明变量之外,ES6 还允许你使用 let 关键字在代码块({..})中声明变量。

Q11:如何检查一个数字是否为整数?

难度:2

检查一个数字是小数还是整数,可以使用一种非常简单的方法,就是将它对 1 进行取模,看看是否有余数。

function isInt(num) {
  return num % 1 === 0;
}

console.log(isInt(4)); // true
console.log(isInt(12.2)); // false
console.log(isInt(0.3)); // false

Q12:什么是 IIFE(立即调用函数表达式)?

难度:3

它是立即调用函数表达式(Immediately-Invoked Function Expression),简称 IIFE。函数被创建后立即被执行:

(function IIFE(){
    console.log( "Hello!" );
})();
// "Hello!"

在避免污染全局命名空间时经常使用这种模式,因为 IIFE(与任何其他正常函数一样)内部的所有变量在其作用域之外都是不可见的。

Q13:如何在 JavaScript 中比较两个对象?

难度:3

对于两个非原始值,比如两个对象(包括函数和数组),== 和 === 比较都只是检查它们的引用是否匹配,并不会检查实际引用的内容。

例如,默认情况下,数组将被强制转型成字符串,并使用逗号将数组的所有元素连接起来。所以,两个具有相同内容的数组进行 == 比较时不会相等:

var a = [1,2,3];
var b = [1,2,3];
var c = "1,2,3";

a == c;        // true
b == c;        // true
a == b;        // false

对于对象的深度比较,可以使用 deep-equal 这个库,或者自己实现递归比较算法。

Q14:你能解释一下 ES5 和 ES6 之间的区别吗?

难度:3

  • ECMAScript 5(ES5):ECMAScript 的第 5 版,于 2009 年标准化。这个标准已在所有现代浏览器中完全实现。

  • ECMAScript 6(ES6)或 ECMAScript 2015(ES2015):第 6 版 ECMAScript,于 2015 年标准化。这个标准已在大多数现代浏览器中部分实现。

  • 以下是 ES5 和 ES6 之间的一些主要区别:

  • 箭头函数和字符串插值:

const greetings = (name) => {
    return `hello ${name}`;
}

const greetings = name => `hello ${name}`;
  • 常量

常量在很多方面与其他语言中的常量一样,但有一些需要注意的地方。常量表示对值的“固定引用”。因此,在使用常量时,你实际上可以改变变量所引用的对象的属性,但无法改变引用本身。

const NAMES = [];
NAMES.push("Jim");
console.log(NAMES.length === 1); // true
NAMES = ["Steve", "John"]; // error
  • 块作用域变量。

新的 ES6 关键字 let 允许开发人员声明块级别作用域的变量。let 不像 var 那样可以进行提升。

  • 默认参数值

默认参数允许我们使用默认值初始化函数。如果省略或未定义参数,则使用默认值,也就是说 null 是有效值。

// 基本语法
function multiply (a, b = 2) {
   return a * b;
}
multiply(5); // 10
  • 类定义和继承

ES6 引入了对类(关键字 class)、构造函数(关键字 constructor)和用于继承的 extend 关键字的支持。

  • for…of 操作符

for…of 语句将创建一个遍历可迭代对象的循环。

  • 用于对象合并的 Spread 操作

const obj1 = { a: 1, b: 2 }
const obj2 = { a: 2, c: 3, d: 4}
const obj3 = {...obj1, ...obj2}
  • promise

promise 提供了一种机制来处理异步操作结果。你可以使用回调来达到同样的目的,但是 promise 通过方法链接和简洁的错误处理带来了更高的可读性。

const isGreater = (a, b) => {
return new Promise ((resolve, reject) => {
  if(a > b) {
    resolve(true)
  } else {
    reject(false)
  }
  })
}
isGreater(1, 2)
.then(result => {
  console.log('greater')
})
.catch(result => {
  console.log('smaller')
})
  • 模块导出和导入

const myModule = { x: 1, y: () => { console.log('This is ES5') }}
export default myModule;

import myModule from './myModule';

问题 15:解释 JavaScript 中“undefined”和“not defined”之间的区别。

难度:3

在 JavaScript 中,如果你试图使用一个不存在且尚未声明的变量,JavaScript 将抛出错误“var name is not defined”,让后脚本将停止运行。但如果你使用 typeof undeclared_variable,它将返回 undefined。

在进一步讨论之前,先让我们理解声明和定义之间的区别。

“var x”表示一个声明,因为你没有定义它的值是什么,你只是声明它的存在。

var x; // 声明 x
console.log(x); // 输出: undefined

“var x = 1”既是声明又是定义(我们也可以说它是初始化),x 变量的声明和赋值相继发生。在 JavaScript 中,每个变量声明和函数声明都被带到了当前作用域的顶部,然后进行赋值,这个过程被称为提升(hoisting)。

当我们试图访问一个被声明但未被定义的变量时,会出现 undefined 错误。

var x; // 声明
if(typeof x === 'undefined') // 将返回 true

当我们试图引用一个既未声明也未定义的变量时,将会出现 not defined 错误。

console.log(y);  // 输出: ReferenceError: y is not defined

Q16:匿名和命名函数有什么区别?

难度:3

var foo = function() { // 赋给变量 foo 的匿名函数
    // ..
};

var x = function bar(){ // 赋给变量 x 的命名函数 bar
    // ..
};

foo(); // 实际执行函数
x();

Q17:Javascript 中的“闭包”是什么?举个例子?

难度:4

闭包是在另一个函数(称为父函数)中定义的函数,并且可以访问在父函数作用域中声明和定义的变量。

闭包可以访问三个作用域中的变量:

  • 在自己作用域中声明的变量;

  • 在父函数中声明的变量;

  • 在全局作用域中声明的变量。

var globalVar = "abc";

// 自调用函数
(function outerFunction (outerArg) { // outerFunction 作用域开始
  // 在 outerFunction 函数作用域中声明的变量
  var outerFuncVar = 'x';    
  // 闭包自调用函数
  (function innerFunction (innerArg) { // innerFunction 作用域开始
    // 在 innerFunction 函数作用域中声明的变量
    var innerFuncVar = "y";
    console.log(         
      "outerArg = " + outerArg + "\n" +
      "outerFuncVar = " + outerFuncVar + "\n" +
      "innerArg = " + innerArg + "\n" +
      "innerFuncVar = " + innerFuncVar + "\n" +
      "globalVar = " + globalVar);
  // innerFunction 作用域结束
  })(5); // 将 5 作为参数
// outerFunction 作用域结束
})(7); // 将 7 作为参数

innerFunction 是在 outerFunction 中定义的闭包,可以访问在 outerFunction 作用域内声明和定义的所有变量。除此之外,闭包还可以访问在全局命名空间中声明的变量。

上述代码的输出将是:

outerArg = 7
outerFuncVar = x
innerArg = 5
innerFuncVar = y
globalVar = abc

Q18:如何在 JavaScript 中创建私有变量?

难度:4

要在 JavaScript 中创建无法被修改的私有变量,你需要将其创建为函数中的局部变量。即使这个函数被调用,也无法在函数之外访问这个变量。例如:

function func() {
  var priv = "secret code";
}

console.log(priv); // throws error

要访问这个变量,需要创建一个返回私有变量的辅助函数。

function func() {
  var priv = "secret code";
  return function() {
    return priv;
  }
}

var getPriv = func();
console.log(getPriv()); // => secret code

Q19:请解释原型设计模式。

难度:4

原型模式可用于创建新对象,但它创建的不是非初始化的对象,而是使用原型对象(或样本对象)的值进行初始化的对象。原型模式也称为属性模式。

原型模式在初始化业务对象时非常有用,业务对象的值与数据库中的默认值相匹配。原型对象中的默认值被复制到新创建的业务对象中。

经典的编程语言很少使用原型模式,但作为原型语言的 JavaScript 在构造新对象及其原型时使用了这个模式。

Q20:判断一个给定的字符串是否是同构的。

难度:4

如果两个字符串是同构的,那么字符串 A 中所有出现的字符都可以用另一个字符替换,以便获得字符串 B,而且必须保留字符的顺序。字符串 A 中的每个字符必须与字符串 B 的每个字符一对一对应。

  • paper 和 title 将返回 true。

  • egg 和 sad 将返回 false。

  • dgg 和 add 将返回 true。

isIsomorphic("egg", 'add'); // true
isIsomorphic("paper", 'title'); // true
isIsomorphic("kick", 'side'); // false

function isIsomorphic(firstString, secondString) {

  // 检查长度是否相等,如果不相等, 它们不可能是同构的
  if (firstString.length !== secondString.length) return false

  var letterMap = {};

  for (var i = 0; i < firstString.length; i++) {
    var letterA = firstString[i],
        letterB = secondString[i];

    // 如果 letterA 不存在, 创建一个 map,并将 letterB 赋值给它
    if (letterMap[letterA] === undefined) {
      letterMap[letterA] = letterB;
    } else if (letterMap[letterA] !== letterB) {
      // 如果 letterA 在 map 中已存在, 但不是与 letterB 对应,
      // 那么这意味着 letterA 与多个字符相对应。
      return false;
    }
  }
  // 迭代完毕,如果满足条件,那么返回 true。
  // 它们是同构的。
  return true;
}

Q21:“Transpiling”是什么意思?

难度:4

对于语言中新加入的语法,无法进行 polyfill。因此,更好的办法是使用一种工具,可以将较新代码转换为较旧的等效代码。这个过程通常称为转换(transpiling),就是 transforming + compiling 的意思。

通常,你会将转换器(transpiler)加入到构建过程中,类似于 linter 或 minifier。现在有很多很棒的转换器可选择:

  • Babel:将 ES6+ 转换为 ES5

  • Traceur:将 ES6、ES7 转换为 ES5

Q22:“this”关键字的原理是什么?请提供一些代码示例。

难度:4

在 JavaScript 中,this 是指正在执行的函数的“所有者”,或者更确切地说,指将当前函数作为方法的对象。

function foo() {
    console.log( this.bar );
}

var bar = "global";

var obj1 = {
    bar: "obj1",
    foo: foo
};

var obj2 = {
    bar: "obj2"
};

foo();             // "global"
obj1.foo();        // "obj1"
foo.call( obj2 );  // "obj2"
new foo();         // undefined

Q23:如何向 Array 对象添加自定义方法,让下面的代码可以运行?

难度:4

var arr = [1, 2, 3, 4, 5];
var avg = arr.average();
console.log(avg);

JavaScript 不是基于类的,但它是基于原型的语言。这意味着每个对象都链接到另一个对象(也就是对象的原型),并继承原型对象的方法。你可以跟踪每个对象的原型链,直到到达没有原型的 null 对象。我们需要通过修改 Array 原型来向全局 Array 对象添加方法。

Array.prototype.average = function() {
  // 计算 sum 的值
  var sum = this.reduce(function(prev, cur) { return prev + cur; });
  // 将 sum 除以元素个数并返回
  return sum / this.length;
}

var arr = [1, 2, 3, 4, 5];
var avg = arr.average();
console.log(avg); // => 3

Q24:什么是 JavaScript 中的提升操作?

难度:4

提升(hoisting)是 JavaScript 解释器将所有变量和函数声明移动到当前作用域顶部的操作。有两种类型的提升:

  • 变量提升——非常少见

  • 函数提升——更常见

无论 var(或函数声明)出现在作用域的什么地方,它都属于整个作用域,并且可以在该作用域内的任何地方访问它。

var a = 2;
foo();                   // 因为`foo()`声明被"提升",所以可调用

function foo() {
    a = 3;
    console.log( a );    // 3
    var a;               // 声明被"提升"到 foo() 的顶部
}

console.log( a );    // 2

Q25:以下代码输出的结果是什么?

难度:4

0.1 + 0.2 === 0.3

这段代码的输出是 false,这是由浮点数内部表示导致的。0.1 + 0.2 并不刚好等于 0.3,实际结果是 0.30000000000000004。解决这个问题的一个办法是在对小数进行算术运算时对结果进行舍入。

Q26:请描述一下 Revealing Module Pattern 设计模式。

难度:5

暴露模块模式(Revealing Module Pattern)是模块模式的一个变体,目的是维护封装性并暴露在对象中返回的某些变量和方法。如下所示:

var Exposer = (function() {
  var privateVariable = 10;

  var privateMethod = function() {
    console.log('Inside a private method!');
    privateVariable++;
  }

  var methodToExpose = function() {
    console.log('This is a method I want to expose!');
  }

  var otherMethodIWantToExpose = function() {
    privateMethod();
  }

  return {
      first: methodToExpose,
      second: otherMethodIWantToExpose
  };
})();

Exposer.first();        // 输出: This is a method I want to expose!
Exposer.second();       // 输出: Inside a private method!
Exposer.methodToExpose; // undefined

它的一个明显的缺点是无法引用私有方法。

相关学习推荐:javascript视频教程

위 내용은 2018년 최신 JavaScript 면접 질문 26개와 답변 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 segmentfault.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제