JavaScript面试题总结:精进你的技术栈
大家好,今天我们来聊一聊JavaScript的面试题,这些内容是我精心整理的,不仅方便自己复习,也希望能够帮助到正在准备面试的你。JavaScript作为前端开发的核心技术之一,其知识点的重要性不言而喻。接下来,让我们一起深入探索JS的世界。
1. 数据类型
在JS中,共有8种数据类型,包括Undefined、Null、Boolean、Number、String、Object、Symbol和BigInt。其中,Symbol和BigInt是ES6新增的数据类型。基本数据类型直接存储在栈中,而引用类型(如Object)则存储在堆中。
代码示例
console.log(typeof NaN); // 'number'
console.log(typeof Function); // 'function'
console.log(typeof Object); // 'function'
console.log(typeof {});// 'object'
2. 数据类型判断
typeof
:能判断所有值类型和函数,但不能精确判断null、对象和数组。instanceof
:能判断对象类型,不能判断基本数据类型。Object.prototype.toString.call()
:能判断所有原始数据类型和一些对象类型。
代码示例
console.log(Function instanceof Object); // true
console.log(Object instanceof Function);//true
3. 深拷贝与浅拷贝
深拷贝是完全复制一个对象,而浅拷贝只是复制对象的引用。深拷贝可以通过递归实现,而浅拷贝可以通过Object.assign
或展开运算符实现。
深拷贝代码示例
function deepClone(obj) {
if (typeof obj !== "object" || obj == null) {
return obj;
}
let result = Array.isArray(obj) ? [] : {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
result[key] = deepClone(obj[key]);
}
}
return result;
}
浅拷贝代码示例
var shallowObj = { ...obj1 };
4. IEEE 754与浮点数精度问题
JavaScript使用Number类型表示数字,遵循IEEE 754标准。由于浮点数的精度问题,我们常常遇到0.1 + 0.2 != 0.3
的情况。解决这个问题可以通过将数字转为整数进行计算,或者使用第三方库如Math.js。
精度问题代码示例
function add(num1, num2) {
const baseNum = Math.pow(10, Math.max((num1.toString().split('.')[1] || '').length, (num2.toString().split('.')[1] || '').length));
return (num1 * baseNum + num2 * baseNum) / baseNum;
}
5. 原型和原型链
每个JavaScript对象都有一个原型,对象会从原型“继承”属性。原型链是由相互关联的原型组成的链状结构。
原型链代码示例
console.log(Object.prototype.toString.call([])); // [object Array]
6. 作用域与作用域链
作用域决定了代码区块中变量和其他资源的可见性,而作用域链是多层执行上下文的变量对象构成的链表。
作用域链代码示例
var x = 10;
function fn() {
console.log(x);
}
function show(f) {
var x = 20;
(function() {
f(); //10,而不是20
})();
}
show(fn);
由于篇幅限制,我们将在下一篇文章中继续探讨闭包、call、apply、bind的实现以及new操作符的模拟等高级话题,并提供相应的代码示例。敬请期待!
JavaScript面试题总结(续):深入探索JS核心概念
接上篇文章,我们继续深入探讨JavaScript的核心概念,通过代码示例来加深理解。
7. 闭包
闭包是指那些能够访问自由变量的函数。在函数定义的地方,向上级作用域查找自由变量的值。
闭包代码示例
function createClosure() {
var outerVar = "I am outer";
return function() {
console.log(outerVar);
};
}
var innerFunc = createClosure();
innerFunc(); // 输出:I am outer
8. call、apply、bind的实现
这三个方法都是用来在特定的作用域中调用函数。通过模拟这些方法的实现,我们可以更好地理解JavaScript的作用域和函数调用机制。
call和apply代码示例
Function.prototype.myCall = function(context) {
if (typeof this !== "function") {
throw new Error("Type error");
}
context = context || window;
context.fn = this;
var args = [...arguments].slice(1);
var result = context.fn(...args);
delete context.fn;
return result;
};
Function.prototype.myApply = function(context) {
if (typeof this !== "function") {
throw new Error("Type error");
}
context = context || window;
context.fn = this;
var result;
if (arguments[1]) {
result = context.fn(...arguments[1]);
} else {
result = context.fn();
}
delete context.fn;
return result;
};
bind代码示例
Function.prototype.myBind = function(context) {
if (typeof this !== "function") {
throw new Error("Type error");
}
const args = [...arguments].slice(1);
const fn = this;
return function Fn() {
return fn.apply(
this instanceof Fn ? this : context,
args.concat(...arguments)
);
};
};
9. new的实现
通过模拟new
操作符的实现,我们可以深入理解JavaScript对象的创建过程。
new代码示例
function myNew(constructor, ...args) {
const obj = Object.create(constructor.prototype);
const result = constructor.apply(obj, args);
return typeof result === "object" && result !== null ? result : obj;
}
10. 异步:EventLoop、宏任务和微任务
JavaScript的异步行为是由EventLoop控制的,理解EventLoop对于掌握JavaScript的异步处理至关重要。
异步代码示例
setTimeout(() => {
console.log(1);
}, 0);
new Promise((resolve) => {
console.log(2);
resolve();
}).then(() => {
console.log(3);
});
console.log(4);
// 输出顺序:2 4 3 1
11. Promise
Promise是JavaScript中处理异步操作的重要机制,它代表了异步操作的最终完成(或失败)及其结果值。
Promise代码示例
class Promise {
constructor(excutor) {
this.PromiseState = 'pending';
this.PromiseResult = null;
this.callbacks = [];
try {
excutor(this.resolve, this.reject);
} catch (error) {
this.reject(error);
}
}
then(onResolved, onRejected) {
// 处理then方法的逻辑
}
catch(onRejected) {
return this.then(null, onRejected);
}
static resolve(value) {
// 处理resolve的逻辑
}
static reject(error) {
// 处理reject的逻辑
}
static all(promises) {
// 处理all的逻辑
}
static race(promises) {
// 处理race的逻辑
}
}
在这篇文章中,我们继续深入探讨了JavaScript的闭包、call/apply/bind的实现、new操作符的模拟以及异步处理机制。这些概念是JavaScript面试中的热点问题,掌握它们对于提升你的技术栈至关重要。希望这些代码示例能够帮助你更好地理解和掌握这些知识点。我们下期再见!
JavaScript面试题总结(终):掌握异步处理与ES6+新特性
在前两篇文章中,我们深入探讨了JavaScript的基础概念和核心机制。本文将继续深入,重点讨论JavaScript的异步处理细节以及ES6+的新特性,这些都是面试中的高频考点。
12. async/await 和 Promise 的关系
async/await
是处理异步操作的新语法,它建立在Promise
之上,使得异步代码的编写更加直观和简洁。
async/await 代码示例
async function fetchData() {
try {
const data = await fetch('https://api.example.com/data');
const json = await data.json();
console.log(json);
} catch (error) {
console.error('Fetching data failed:', error);
}
}
13. 浏览器的垃圾回收机制
JavaScript的垃圾回收主要依赖于标记清除算法,了解垃圾回收机制对于优化内存使用和性能调优非常重要。
垃圾回收代码示例
// 通过循环引用创建内存泄漏
function leakMemory() {
var a = {};
var b = {};
a.instance = b;
b.instance = a;
}
// 忘记释放不再使用的大对象
var largeObj = new Array(1000000).join('a');
leakMemory();
14. 继承
JavaScript中的继承可以通过多种方式实现,包括组合继承、原型继承、寄生式继承和寄生组合继承等。
继承代码示例
// 组合继承
function SuperType(name) {
this.name = name;
this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function() {
console.log(this.name);
};
function SubType(name, age) {
SuperType.call(this, name);
this.age = age;
}
SubType.prototype = Object.create(SuperType.prototype);
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function() {
console.log(this.age);
};
var instance = new SubType("Kimi", 30);
instance.sayName(); // "Kimi"
instance.sayAge(); // 30
15. 模块化
ES6引入了模块化的标准,通过import
和export
关键字,我们可以更便捷地管理代码的依赖关系。
模块化代码示例
// mathUtils.js
export function add(x, y) {
return x + y;
}
export const pi = 3.14159;
// app.js
import { add, pi } from './mathUtils.js';
console.log(add(2, 3)); // 5
console.log(pi); // 3.14159
16. 防抖与节流
防抖和节流是控制函数执行频率的常用技术,尤其在处理输入、滚动和窗口调整等事件时非常有用。
防抖代码示例
function debounce(fn, delay) {
let timeoutId = null;
return function() {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
fn.apply(this, arguments);
}, delay);
};
}
// 使用防抖
const debouncedAlert = debounce(alert, 2000);
input.addEventListener('input', debouncedAlert.bind(null, 'Input changed!'));
节流代码示例
function throttle(fn, limit) {
let lastFunc;
let lastRan;
return function() {
if (!lastRan) {
fn.apply(this, arguments);
lastRan = Date.now();
} else {
clearTimeout(lastFunc);
lastFunc = setTimeout(function() {
if ((Date.now() - lastRan) >= limit) {
fn.apply(null, arguments);
lastRan = Date.now();
}
}, limit - (Date.now() - lastRan));
}
}
}
// 使用节流
window.addEventListener('resize', throttle(function() {
console.log('Resize event handler called', new Date());
}, 1000));
17. ES6/ES7新特性
ES6和ES7引入了许多新特性,如let
、const
、箭头函数、模板字符串、Set
和Map
等,这些新特性极大地丰富了JavaScript的表达能力。
ES6/ES7代码示例
// 箭头函数
const sum = (a, b) => a + b;
// 模板字符串
const name = "Kimi";
console.log(`Hello, ${name}!`);
// Set
const mySet = new Set();
mySet.add(1).add(2).add(2);
console.log(mySet.size); // 2
// Map
const myMap = new Map();
myMap.set('key', 'value');
console.log(myMap.get('key')); // 'value'
本系列文章到这里就结束了。我们从基础的数据类型讲到了原型链,再到异步处理和ES6+的新特性,这些都是JavaScript面试中的重点和难点。希望这些内容能够帮助你在面试中游刃有余,也为你的日常开发工作提供参考。掌握这些知识点,你将能够更好地理解和使用JavaScript这门强大的语言。祝你技术精进,面试成功!
JavaScript面试题总结(四):探索高级技巧与性能优化
在前面的系列文章中,我们详细探讨了JavaScript的基础知识、异步处理和ES6+新特性。本文将聚焦于JavaScript的高级技巧和性能优化,这些是面试中展现你技术深度的绝佳机会。
18. 函数柯里化
函数柯里化是一种技术,允许我们预先填充一个或多个参数,然后返回一个新的函数,这个新函数可以接收剩余的参数。
柯里化代码示例
const add = a => b => a + b;
const add5 = add(5);
console.log(add5(10)); // 输出 15
19. 抽象语法树(AST)
抽象语法树(AST)是源代码的树状表现形式,它在代码解析、转换和优化中扮演着重要角色。
AST处理代码示例
// 使用Babel解析代码为AST
const babel = require('@babel/core');
const code = 'const x = 5;';
const ast = babel.parse(code, {
sourceType: 'module',
plugins: []
});
console.log(ast);
20. Babel编译原理
Babel通过将ES6+代码转换为AST,然后转换为ES5代码,使得现代JavaScript代码能够在旧的环境中运行。
Babel转换代码示例
// 使用Babel转换代码
const code = 'const x = 5;';
const transformedCode = babel.transform(code, {
presets: ['@babel/preset-env']
}).code;
console.log(transformedCode);
21. 性能优化
JavaScript性能优化是一个广泛的话题,包括但不限于代码层面的优化、内存泄漏的检测和处理、以及使用Web Workers等。
性能优化代码示例
// 使用requestAnimationFrame进行动画性能优化
function animate() {
requestAnimationFrame(animate);
// 动画逻辑
}
animate();
22. Web存储
Web存储包括localStorage、sessionStorage和cookie,它们在不同的场景下有不同的应用。
Web存储代码示例
// 使用localStorage
localStorage.setItem('username', 'Kimi');
const username = localStorage.getItem('username');
console.log(username); // 输出 'Kimi'
// 使用sessionStorage
sessionStorage.setItem('sessionKey', 'sessionValue');
// 使用cookie
document.cookie = "username=Kimi; expires=Thu, 18 Dec 2024 12:00:00 UTC; path=/";
23. 设计模式
在JavaScript中应用设计模式,如MVVM、观察者模式和发布/订阅模式,可以帮助我们构建更加模块化和可维护的代码。
MVVM代码示例
// 简化的MVVM示例
class Observer {
constructor(data) {
this.data = data;
this.observers = [];
}
observe(fn) {
this.observers.push(fn);
}
notify() {
this.observers.forEach(fn => fn());
}
get(name) {
return this.data[name];
}
set(name, value) {
this.data[name] = value;
this.notify();
}
}
const obs = new Observer({ name: 'Kimi' });
obs.observe(() => console.log(obs.get('name')));
obs.set('name', 'New Name');
24. 算法和数据结构
掌握基本的算法和数据结构对于任何开发人员都是必要的,JavaScript也不例外。从排序算法到查找算法,这些都是面试中常见的问题。
算法代码示例
// 快速排序
function quickSort(arr) {
if (arr.length <= 1) return arr;
const pivot = arr[0];
const left = [];
const right = [];
for (let i = 1; i < arr.length; i++) {
if (arr[i] < pivot) left.push(arr[i]);
else right.push(arr[i]);
}
return quickSort(left).concat(pivot, quickSort(right));
}
console.log(quickSort([3, 6, 2, 7, 1, 8, 5, 4, 9]));
本系列文章到此结束。我们从JavaScript的基础知识出发,逐步深入到高级技巧和性能优化,希望这些内容能够帮助你在技术道路上更进一步。掌握这些知识点,你将能够在面试中展现出你的技术深度,同时也能在日常开发中写出更高效、更优雅的代码。祝你在技术的道路上越走越远!
JavaScript面试题总结(五):探索框架与工具链
在前几篇文章中,我们深入探讨了JavaScript的核心技术和概念。本文将聚焦于现代JavaScript开发中常用的框架和工具链,这些是构建现代Web应用的基石。
25. React
React是一个用于构建用户界面的JavaScript库,它由Facebook维护。React以其组件化和虚拟DOM而闻名。
React代码示例
import React from 'react';
class Greeting extends React.Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
export default Greeting;
26. Vue.js
Vue.js是一个渐进式JavaScript框架,用于构建用户界面。Vue的核心库只关注视图层,易于学习和集成。
Vue代码示例
<template>
<div>
<h1>{{ message }}</h1>
</div>
</template>
<script>
export default {
data() {
return {
message: 'Hello from Vue!'
};
}
}
</script>
27. Angular
Angular是一个由Google维护的平台和框架,用于构建客户端应用程序。它提供了一套完整的解决方案,包括模板、表单处理、依赖注入等。
Angular代码示例
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `<h1>{{ title }}</h1>`,
})
export class AppComponent {
title = 'Hello from Angular!';
}
28. Webpack
Webpack是一个模块打包器,用于将项目中的所有依赖项(JavaScript、CSS、图片等)打包成一个或多个bundle。
Webpack配置代码示例
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
}
};
29. Babel
Babel是一个JavaScript编译器,用于将ES6+代码转换为向后兼容的JavaScript版本,以便在当前和旧版浏览器中运行。
Babel配置代码示例
{
"presets": [
"@babel/preset-env",
"@babel/preset-react"
],
"plugins": [
"@babel/plugin-proposal-class-properties"
]
}
30. TypeScript
TypeScript是JavaScript的超集,它添加了类型系统和一些其他特性,使得开发大型应用程序更加健壮和可靠。
TypeScript代码示例
interface GreetingProps {
name: string;
}
const Greeting = ({ name }: GreetingProps) => {
return <h1>Hello, {name}!</h1>;
};
export default Greeting;
31. Jest
Jest是一个由Facebook开发的JavaScript测试框架,它专注于简化单元测试的编写和运行。
Jest测试代码示例
test('adds 1 + 2 to equal 3', () => {
expect(1 + 2).toBe(3);
});
32. Node.js
Node.js是一个基于Chrome V8引擎的JavaScript运行时,它允许JavaScript在服务器端运行。
Node.js代码示例
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello, World!');
});
server.listen(3000, () => {
console.log('Server running on port 3000');
});
本系列文章到此结束。我们从JavaScript的核心技术和概念出发,逐步深入到现代JavaScript开发中常用的框架和工具链。希望这些内容能够帮助你在技术道路上更进一步。掌握这些知识点,你将能够在面试中展现出你的技术广度,同时也能在日常开发中构建更加强大和高效的Web应用。祝你在技术的道路上越走越远!