[Front-end interview questions] 2023 front-end interview questions - JS chapter

There are always ups and downs in a person's life. It will not always rise like the rising sun, nor will it always be miserable. Repeated ups and downs are training for a person. Therefore, those who are floating above do not need to be proud; those who are sinking below do not need to be pessimistic. We must be frank and humble, optimistic and enterprising, and move forward. ——Konosuke Matsushita

Hello everyone, my name is Jiang Chen. In today's Internet environment, everyone must have felt it to some extent. In this impetuous society, only by constantly maintaining one's character can one perceive different gains and encourage each other.

A collection of the latest interview questions in 2023, so be prepared at all times.

This article was first published on WeChat public account: Wild Programmer Jiang Chen

Everyone is welcome to like, collect and follow

Article list

Please briefly describe this in JavaScript

in JS thisis a relatively complex concept that cannot be explained clearly in a few sentences. Roughly speaking, how the function is called determines thisthe value of . I have read a lot of thisarticles on the Internet about , and Arnav Aggrawal wrote it more clearly. thisThe value complies with the following rules:

Use the keyword when calling a function new, and the inside the function thisis a brand new object.
If the apply、callor bindmethod is used to call or create a function, the within the function thisis the object passed into these methods as a parameter.
When a function is called as a method on an object, within the function thisis the object that called the function. For example, when obj.method()is called, inside the function thiswill be bound to objthe object.
If the calling function does not comply with the above rules, then thisthe value of points to the global object ( global object). In a browser environment thisthe value of points to windowthe object, but in strict mode ( 'use strict'), thisthe value of undefined.
If more than one of the above rules is met, the higher rule (number 1 is the highest, number 4 is the lowest) will determine thisthe value of .
If the function is ES2015an arrow function in , all rules above are ignored and thisare set to the context in which it was created.

Tell me what you know about AMD and CommonJS.

They are all ways to implement a module system. Until ES2015the emergence of , JavaScriptthere was no module system. CommonJSis synchronous, while AMD(Asynchronous Module Definition)it is obvious from the full name that it is asynchronous. CommonJSis designed with server-side development in mind, while AMDsupports asynchronous loading of modules, which is more suitable for browsers.

I find AMDthe syntax to be very verbose and CommonJScloser to importthe usage of declaration statements in other languages. In most cases, I think AMDthere is no need to use it, because if you JavaScriptbundle everything into a file, you will not get the benefits of asynchronous loading. In addition, CommonJSthe syntax is closer to Nodethe style of writing modules. JavaScriptWhen switching between front-end and back-end development, the context switching overhead is smaller.

I'm happy to see ES2015that the module loading scheme supports both synchronous and asynchronous, and we can finally use only one scheme. While it's not yet fully rolled out in browsers and Node, we can convert it using transcoding tools.

Please explain why the following code cannot be used as an IIFE: function foo(){ }();. What modifications need to be made to make it an IIFE?

IIFE (Immediately Invoked Function Expressions) stands for Immediately Invoked Function Expressions. JavaScriptThe parser will function foo(){ }();parse into function foo(){ }和();. Among them, the former is a function declaration; the latter (a pair of parentheses) is an attempt to call a function without specifying a name, so it will throw an Uncaught SyntaxError: Unexpected token )error.

The modification method is: add another pair of brackets, there are two forms: (function foo(){ })()and (function foo(){ }()). The above function will not be exposed to the global scope. If you do not need to refer to itself within the function, you can omit the name of the function.

You may use voidoperator: void function foo(){ }();. However, this approach is problematic. The value of the expression is undefined, so if your IIFEhas a return value, don't use this approach. For example

const foo = void (function bar() {
  return 'foo';
})();

console.log(foo); // undefined

What is the difference between null, undefined and undeclared variables? How to check and judge these status values?

When you assign a value to a variable without declaring it with var、letor in advance const, the variable is an undeclared variable ( undeclared variables). Undeclared variables will leave the current scope and become variables defined in the global scope. In strict mode, assigning a value to an undeclared variable will throw ReferenceErroran error. Like using global variables, using undeclared variables is also a very bad practice and should be avoided whenever possible. To check for them, place the code that uses them in try/catcha statement.

function foo() {
  x = 1; // 在严格模式下,抛出 ReferenceError 错误
}

foo();
console.log(x); // 1

When a variable has been declared but not assigned a value, the variable's value is undefined. If the execution result of a function is assigned to a variable, but the function does not return any value, then the value of the variable is undefined. To check it, use strict equality ( ===); alternatively typeof, it returns 'undefined'a string. Note that you cannot use non-strict equality ( ==) to check because nullusing non-strict equality will also return if the variable value is true.

var foo;
console.log(foo); // undefined
console.log(foo === undefined); // true
console.log(typeof foo === 'undefined'); // true

console.log(foo == null); // true. 错误,不要使用非严格相等!

function bar() {}
var baz = bar();
console.log(baz); // undefined

nullCan only be assigned to variables explicitly. It represents a null value, which is different from being explicitly assigned undefined. To check the predicate nullvalue, use the strict equality operator. Note that, as before, you cannot use non-strict equality ( ==) to check, because undefinedusing non-strict equality will also return if the variable value is true.

var foo = null;
console.log(foo === null); // true

console.log(foo == undefined); // true. 错误,不要使用非严格相等!

As a personal habit, I never use undeclared variables. If variables are defined that are not used yet, I will explicitly assign values ​​to them after declaring them asnull

What is a closure and why are we using it?

A closure is a combination of a function and the lexical environment in which the function is declared. The domain used in lexical scope is determined by where the variable is declared in the code. A closure is a function that can still access the scope of the outer (enclosing) function even if it is returned by the outer function.

Why use closures?

  • Use closures to privatize data or mock private methods. This approach is also called module mode ( module pattern).
  • Partial argument function ( partial applications) currying ( currying).

Please explain the main difference between .forEach loop and .map() loop. Under what circumstances are they used?

To understand the difference between the two, let’s look at what they do.

forEach

  • Iterate over the elements in an array.
  • Execute callback for each element.
  • No return value.
const a = [1, 2, 3];
const doubled = a.forEach((num, index) => {
  // 执行与 num、index 相关的代码
});

// doubled = undefined

map

  • Iterate over the elements in an array
  • A new array is created by "map" each element to a new element by calling a function on each element.
const a = [1, 2, 3];
const doubled = a.map((num) => {
  return num * 2;
});

// doubled = [2, 4, 6]

.forEach.map()The main difference between and is that .map()returns a new array. If you want to get a result without changing the original array, use .map(). If you only need to make iterative modifications on an array, use forEach.

What are the typical application scenarios of anonymous functions?

Anonymous functions can be used in IIFEs to encapsulate code in the local scope so that the variables they declare are not exposed to the global scope.

(function () {
  // 一些代码。
})();

Anonymous functions can be used as callback functions that are used only once and do not need to be used elsewhere. When handlers are defined inside the program that calls them, the code is more self-contained and readable, and the trouble of finding the location of the function body of the handler is saved.

setTimeout(function () {
  console.log('Hello world!');
}, 1000);

Anonymous functions can be used in functional programming or Lodash (similar to callback functions).

const arr = [1, 2, 3];
const double = arr.map(function (el) {
  return el * 2;
});
console.log(double); // [2, 4, 6]

What is the difference between .call and .apply?

.calland are .applyboth used to call a function, the first parameter will be used as thisthe value within the function. However, .callaccepts comma-separated parameters as the next parameter, while .applyaccepts an array of parameters as the next parameter. A simple memory method callis to associate the C in to comma separation ( comma-separated), applyand associate the A in to array ( array).

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

console.log(add.call(null, 1, 2)); // 3
console.log(add.apply(null, [1, 2])); // 3

Please explain the usage of Function.prototype.bind.

Excerpted from MDN:

The bind() method creates a new function, and when called, sets its this keyword to the supplied value. When calling the new function, it provides a given sequence of arguments before any supply.

In my experience, thisit is very useful to bind the value of into a method of a class that you want to pass to other functions. ReactThis is often done in components .

Please explain Ajax in as much detail as possible.

Ajax (asynchronous JavaScript and XML) is a Web development technology that uses many Web technologies on the client to create asynchronous Web applications. With Ajax, Web applications can send and retrieve data to and from the server asynchronously (in the background) without interfering with the display and behavior of existing pages. By separating the data exchange layer from the presentation layer, Ajax allows web pages and extended Web applications to dynamically change content without reloading the entire page. In fact, XML is now often replaced by JSON because of JavaScript's native support for JSON.

XMLHttpRequest APIOften used for asynchronous communication. There are also recently popular ones fetch API.

What are the advantages and disadvantages of using Ajax?

advantage
  • Better interactivity. New content from the server can be changed dynamically without reloading the entire page.
  • Reduces connections to the server since scripts and styles only need to be requested once.
  • Status can be maintained on a page. JavaScript variables and DOM state are maintained because the main container page is not reloaded.
  • Basically includes most of the advantages of SPA.
shortcoming
  • Dynamic web pages are difficult to collect.
  • Has no effect if JavaScript has been disabled in the browser.
  • Some web crawlers do not execute JavaScript and will not see content loaded by JavaScript.
  • Basically includes most of the shortcomings of SPA

Please explain how JSONP works and why is it not true Ajax?

JSONP (JSON with padding) is a method commonly used to bypass cross-domain restrictions in web browsers because Ajax does not allow cross-domain requests.

JSONP <script>sends cross-domain requests through tags, usually using callbackquery parameters, such as: https://example.com?callback=printData. The server then wraps the data in a printDatafunction called and returns it to the client.

<!-- https://mydomain.com -->
<script>
  function printData(data) {
    console.log(`My name is ${data.name}!`);
  }
</script>

<script src="https://example.com?callback=printData"></script>
// 文件加载自 https://example.com?callback=printData
printData({name: 'Yang Shun'});

The client must have the function in its global scope printData, and the function will be executed by the client when a response is received from the cross-domain.

JSONP may have some security implications. Since JSONP is a pure JavaScript implementation, it can do everything JavaScript can do, so the provider of JSONP data needs to be trusted.

Nowadays, Cross-Origin Resource Sharing (CORS) is the recommended mainstream method, and JSONP has been regarded as a more hacky method.

Please explain variable hoisting.

Variable hoisting is a term used to explain the behavior of variable declarations in code. varVariables declared or initialized using the keyword "raise" the declaration statement to the top of the current scope. However, only declarations will trigger hoisting, assignment statements (if any) will remain intact. Let's explain it with a few examples.

// 用 var 声明得到提升
console.log(foo); // undefined
var foo = 1;
console.log(foo); // 1

// 用 let/const 声明不会提升
console.log(bar); // ReferenceError: bar is not defined
let bar = 2;
console.log(bar); // 2

Function declarations hoist the function body, but function expressions (written in the form of variable declarations) only have variable declarations hoisted.

// 函数声明
console.log(foo); // [Function: foo]
foo(); // 'FOOOOO'
function foo() {
  console.log('FOOOOO');
}
console.log(foo); // [Function: foo]

// 函数表达式
console.log(bar); // undefined
bar(); // Uncaught TypeError: bar is not a function
var bar = function () {
  console.log('BARRRR');
};
console.log(bar); // [Function: bar]

Please describe event bubbling.

When an event fires on a DOM element, if there is an event listener, it will try to handle the event and then the event bubbles up to its parent element and the same thing happens. Finally until the event reaches the ancestor element. Event bubbling is the principle of implementing event delegation (event delegation).

andWhat is the difference between =

==is an abstract equality operator, while ===is a strict equality operator. ==The operator performs necessary type conversions before comparison. ===The operator does not perform type conversion, so if the two values ​​are not of the same type, they are returned directly false. When using ==, some special things can happen, such as:

1 == '1'; // true
1 == [1]; // true
1 == true; // true
0 == ''; // true
0 == '0'; // true
0 == false; // true

My advice is to never use ==the operator except for convenience when comparing with nullor , if is or will returnundefineda == nullanullundefinedtrue

var a = null;
console.log(a == null); // true
console.log(a == undefined); // true

Please explain about JavaScript's Same Origin Policy.

The same-origin policy prevents JavaScript from making cross-origin requests. A source is defined as a combination of URI, hostname, and port number. This policy prevents malicious scripts on a page from accessing sensitive data on another web page through the page's Document Object Model.

How familiar are you with Promises and their polyfills?

Understand how it works. PromiseIs an object that may produce a result at some time in the future: the result of a successful operation or the reason for its failure (for example, a network error occurred). PromiseMay be in one of three states: fulfilled, rejectedor pending. Users can Promiseadd callback functions to handle the results of successful operations or the reasons for failure.

Some common ones polyfillare Polyfill $.deferred, Q, and Bluebird, but not all polyfills are compliant with the specification. ES2015 supports Promises, and polyfills are generally not needed now.

What are the advantages and disadvantages of Promise instead of callback function?

advantage

  • Avoid unreadable callback hell.
  • Sequential asynchronous code written using .then() is simple and easy to read.
  • Writing parallel asynchronous code becomes easy with Promise.all().

shortcoming

  • Slightly increases the complexity of the code (this is debatable).
  • In older browsers that do not support ES2015, a polyfill needs to be introduced to use it.

Please explain the difference between synchronous and asynchronous functions.

Synchronous functions block, while asynchronous functions do not block. In a synchronous function, after the statement is completed, the next statement is executed. In this case, the program can be evaluated exactly in the order of statements, and if one of the statements takes a long time, the program's execution will stall for a long time.

Asynchronous functions usually accept a callback as a parameter and continue execution to the next line immediately after calling the asynchronous function. The callback function is only called when the asynchronous operation completes and the call stack is empty. Heavy load operations such as loading data from a web server or querying a database should be completed asynchronously so that the main thread can continue to perform other operations without blocking until the time-consuming operation completes (in the browser, the interface will freeze) .

What is an event loop? What is the difference between call stack and task queue?

The event loop is a single-threaded loop that monitors the call stack and checks if any work is about to be completed in the task queue. If the call stack is empty and there is a callback function in the task queue, the callback function is dequeued and pushed into the call stack for execution.

What is the difference between creating variables using let, var and const?

The scope of a variable declared with varis its current execution context, which can be a nested function or a variable declared outside any function. letand constare block-scoped, meaning they can only be accessed within the nearest set of curly braces (in a function, if-else block, or for loop).

function foo() {
  // 所有变量在函数中都可访问
  var bar = 'bar';
  let baz = 'baz';
  const qux = 'qux';

  console.log(bar); // bar
  console.log(baz); // baz
  console.log(qux); // qux
}

console.log(bar); // ReferenceError: bar is not defined
console.log(baz); // ReferenceError: baz is not defined
console.log(qux); // ReferenceError: qux is not defined
if (true) {
  var bar = 'bar';
  let baz = 'baz';
  const qux = 'qux';
}

// 用 var 声明的变量在函数作用域上都可访问
console.log(bar); // bar
// let 和 const 定义的变量在它们被定义的语句块之外不可访问
console.log(baz); // ReferenceError: baz is not defined
console.log(qux); // ReferenceError: qux is not defined

varWill hoist the variable, which means the variable can be used before it is declared. letand constwill not promote the variable, and an error will be reported if used in advance.

console.log(foo); // undefined

var foo = 'foo';

console.log(baz); // ReferenceError: can't access lexical declaration 'baz' before initialization

let baz = 'baz';

console.log(bar); // ReferenceError: can't access lexical declaration 'bar' before initialization

const bar = 'bar';

Repeating varthe statement with will not cause an error, but letwith and constwill.

var foo = 'foo';
var foo = 'bar';
console.log(foo); // "bar"

let baz = 'baz';
let baz = 'qux'; // Uncaught SyntaxError: Identifier 'baz' has already been declared

letconstThe difference between and is that letmultiple assignments are allowed, while constonly one is allowed.

// 这样不会报错。
let foo = 'foo';
foo = 'bar';

// 这样会报错。
const baz = 'baz';
baz = 'qux';

Can you give an example of using an arrow function and how it differs from other functions

An obvious advantage is that arrow functions can simplify the syntax of creating functions. We do not need to add functionkeywords in front of arrow functions. And the arrow function thiswill be automatically bound to the context of the current scope, which is different from ordinary functions. The value of a normal function thiscan only be determined when it is executed. This feature of arrow functions is particularly useful for callback functions, especially for Reactcomponents.

What is the definition of higher-order function?

A higher-order function is a function that takes one or more functions as parameters, is used for data processing, and may also return a function as a result. Higher-order functions are used to abstract repetitive operations. A typical example is mapthat it takes an array and a function as arguments. mapUse this function to convert each element in an array and return a new array containing the converted elements. Other common examples in JavaScript are forEach, filterand reduce. Higher-order functions are not only used when you need to operate arrays, but there are also many use cases where functions return new functions. Function.prototype.bindJust an example.

Map example

Suppose we have an array of names and we need to convert each character to uppercase.

const names = ['irish', 'daisy', 'anna'];

The method without using higher-order functions is this:

const transformNamesToUppercase = function (names) {
  const results = [];
  for (let i = 0; i < names.length; i++) {
    results.push(names[i].toUpperCase());
  }
  return results;
};
transformNamesToUppercase(names); // ['IRISH', 'DAISY', 'ANNA']

Use .map(transformerFn)to make your code more concise

const transformNamesToUppercase = function (names) {
  return names.map((name) => name.toUpperCase());
};
transformNamesToUppercase(names); // ['IRISH', 'DAISY', 'ANNA']

Please give an example of destructuring an object or array.

Destructuring is a new feature in ES6, which provides a concise and convenient way to extract the values ​​​​of an object or array and put them into different variables.

Array destructuring

// 变量赋值
const foo = ['one', 'two', 'three'];

const [one, two, three] = foo;
console.log(one); // "one"
console.log(two); // "two"
console.log(three); // "three"
// 变量交换
let a = 1;
let b = 3;

[a, b] = [b, a];
console.log(a); // 3
console.log(b); // 1

Object destructuring

// 变量赋值
const o = {p: 42, q: true};
const {p, q} = o;

console.log(p); // 42
console.log(q); // true

Can you give an example of a curry function? What are its benefits?

Currying is a pattern in which a function with multiple arguments is broken into multiple functions that, when called in series, accumulate all required arguments one at a time. This technique helps write functional style code, making the code more readable and compact. It's worth noting that for a function to be curryed, it needs to start with a function and then break it down into a series of functions, each of which takes a parameter.

function curry(fn) {
  if (fn.length === 0) {
    return fn;
  }

  function _curried(depth, args) {
    return function (newArgument) {
      if (depth - 1 === 0) {
        return fn(...args, newArgument);
      }
      return _curried(depth - 1, [...args, newArgument]);
    };
  }

  return _curried(fn.length, []);
}

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

var curriedAdd = curry(add);
var addFive = curriedAdd(5);

var result = [0, 1, 2, 3, 4, 5].map(addFive); // [5, 6, 7, 8, 9, 10]

Guess you like

Origin blog.csdn.net/weixin_42439919/article/details/133065999