本文详细介绍了JS基础知识和高级特性,并提供了一系列的代码示例和面试题解析,帮助读者巩固JS技能。此外,文章还分享了大厂面试中的常见题型和实战演练,特别是涵盖了js大厂面试真题的相关内容。
在JavaScript中,变量是用来存储数据的容器。JavaScript是一种动态类型语言,这意味着你不需要在声明变量时指定其类型,但是JavaScript的变量主要包含以下几种类型:
Number
、String
、Boolean
、null
、undefined
和 Symbol
(ES6新增的类型)。Object
,包括数组、函数等。// 基本数据类型 let numberValue = 42; // Number let stringValue = "Hello, World!"; // String let booleanValue = true; // Boolean let nullValue = null; // null let undefinedValue = undefined; // undefined let symbolValue = Symbol("symbol"); // Symbol // 引用数据类型 let arrayValue = [1, 2, 3]; // Array let objectValue = { key: "value" }; // Object let functionValue = function() {}; // Function
在JavaScript中,函数是第一类对象。这意味着函数可以赋值给变量,作为参数传递,以及作为返回值。此外,函数内部可以声明其他函数。JavaScript的作用域分为全局作用域和局部作用域。
// 全局作用域 let globalVar = "I'm global!"; function globalFunction() { console.log(globalVar); // 输出 "I'm global!" } globalFunction(); // 局部作用域 function localScope() { let localVar = "I'm local!"; console.log(localVar); // 输出 "I'm local!" } localScope(); // 函数内部声明的函数 function outerFunction() { let outerVar = "I'm outer!"; function innerFunction() { console.log(outerVar); // 输出 "I'm outer!" } innerFunction(); } outerFunction();
对象是JavaScript中最灵活的数据结构,可以存储各种类型的值。数组是对象的一个特殊类型,用于存储一组有序的值。
// 对象 let person = { name: "Alice", age: 30, sayHello: function() { console.log(`Hello, I'm ${this.name} and I'm ${this.age} years old.`); } }; person.sayHello(); // 输出 "Hello, I'm Alice and I'm 30 years old." // 数组 let fruits = ["apple", "banana", "cherry"]; console.log(fruits[1]); // 输出 "banana" fruits.push("orange"); console.log(fruits.length); // 输出 4
常见的JS面试题可以分为以下几类:
function uniqueArray(arr) { let result = []; let seen = new Set(); for (let i = 0; i < arr.length; i++) { if (!seen.has(arr[i])) { seen.add(arr[i]); result.push(arr[i]); } } return result; } console.log(uniqueArray([1, 2, 2, 3, 4, 4, 5])); // 输出 [1, 2, 3, 4, 5]
function bubbleSort(arr) { let len = arr.length; for (let i = 0; i < len - 1; i++) { for (let j = 0; j < len - 1 - i; j++) { if (arr[j] > arr[j + 1]) { [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]; // 交换元素 } } } return arr; } console.log(bubbleSort([5, 3, 8, 2, 9, 1])); // 输出 [1, 2, 3, 5, 8, 9]
function findMinMax(arr) { if (arr.length === 0) { return null; } let min = arr[0]; let max = arr[0]; for (let i = 1; i < arr.length; i++) { if (arr[i] < min) { min = arr[i]; } if (arr[i] > max) { max = arr[i]; } } return { min, max }; } console.log(findMinMax([5, 3, 8, 2, 9, 1])); // 输出 { min: 1, max: 9 }
function isPalindrome(str) { let cleanedStr = str.replace(/[^a-zA-Z0-9]/g, '').toLowerCase(); let reversedStr = cleanedStr.split('').reverse().join(''); return cleanedStr === reversedStr; } console.log(isPalindrome("A man, a plan, a canal: Panama")); // 输出 true
JavaScript的事件循环机制支持异步编程。异步编程可以提升程序的响应性和效率,常见的异步机制包括回调、Promise、Generator 和 Async/Await。
事件循环是一个不断执行回调函数的循环,主要用于处理异步任务,如I/O操作、定时器等。
console.log("Start"); setTimeout(() => { console.log("setTimeout"); }, 0); process.nextTick(() => { console.log("nextTick"); }); console.log("End");
输出:
Start End nextTick setTimeout
Promise是解决异步编程的一种方式,它提供了一种更清晰的回调链表示方法。
function delay(ms) { return new Promise((resolve) => { setTimeout(() => { resolve(`Resolved after ${ms} ms`); }, ms); }); } delay(1000).then((value) => { console.log(value); // 输出 "Resolved after 1000 ms" });
ES6引入了许多新特性,如模块化、类、解构赋值等。
ES6引入了 import
和 export
关键字来实现模块化。
// 导出模块 export const PI = 3.14159; export function square(x) { return x * x; } // 导入模块 import { PI, square } from './math.js'; console.log(PI); // 输出 3.14159 console.log(square(5)); // 输出 25
ES6引入了类的语法,使得面向对象编程更加清晰。
class Rectangle { constructor(width, height) { this.width = width; this.height = height; } area() { return this.width * this.height; } } let rect = new Rectangle(4, 5); console.log(rect.area()); // 输出 20
高阶函数是一种可以接受函数作为参数或返回函数的函数。闭包是一种可以访问自由变量的函数。
// 高阶函数 function add(n) { return function(m) { return n + m; }; } let addThree = add(3); console.log(addThree(4)); // 输出 7 // 闭包 function createCounter() { let count = 0; return function() { return ++count; }; } let counter = createCounter(); console.log(counter()); // 输出 1 console.log(counter()); // 输出 2
JavaScript中的错误主要分为以下几类:
let a = 10; console.log(b); // 报错 ReferenceError: b is not defined
let a = 10; a += "20"; // 报错 TypeError: unsupported operand type(s) for +=: 'number' and 'str'
Chrome DevTools 是一个非常强大的调试工具,可以用来查看和修改HTML、CSS、JavaScript代码,以及进行网络请求分析等。
function add(a, b) { return a + b; } let result = add(2, '3'); console.log(result); // 控制台输出 "23"
在Sources面板中,可以设置断点来逐步调试代码。
面试流程通常包括简历筛选、在线笔试、技术面试、HR面试和最终Offer阶段。技术面试是最重要的环节之一,通常分为电话面试、远程面试和现场面试。
面试前要保持积极的心态,相信自己的实力,同时也要准备充分。面试过程中要保持冷静,不要紧张,尽量发挥自己的最佳状态。
面试时要注意以下几点:
实际的面试过程中,建议多做模拟面试和实战练习。可以找朋友或同学一起模拟面试场景,互相提问和回答问题。此外,可以参考一些在线编程平台,如慕课网,多做一些练习题,提高自己的编程能力和面试技巧。
// 示例:实现一个链表 class ListNode { constructor(val, next = null) { this.val = val; this.next = next; } } function addTwoNumbers(l1, l2) { let dummyHead = new ListNode(0); let p = l1, q = l2; let carry = 0; let curr = dummyHead; while (p !== null || q !== null) { let x = (p !== null) ? p.val : 0; let y = (q !== null) ? q.val : 0; let sum = carry + x + y; carry = Math.floor(sum / 10); curr.next = new ListNode(sum % 10); curr = curr.next; if (p !== null) p = p.next; if (q !== null) q = q.next; } if (carry > 0) { curr.next = new ListNode(carry); } return dummyHead.next; }
通过不断练习和反馈,逐步提高自己的编程水平和面试技巧。
function deepCopy(obj) { if (typeof obj !== 'object') { return obj; } let copy = Array.isArray(obj) ? [] : {}; for (let key in obj) { if (obj.hasOwnProperty(key)) { copy[key] = deepCopy(obj[key]); } } return copy; } let original = { a: 1, b: { c: 3, d: 4 }, e: [5, 6, 7] }; let copy = deepCopy(original); console.log(original === copy); // 输出 false console.log(original.b === copy.b); // 输出 false console.log(original.e === copy.e); // 输出 false
function flattenArray(arr) { return arr.reduce((acc, val) => { return acc.concat(Array.isArray(val) ? flattenArray(val) : val); }, []); } let nestedArray = [1, [2, [3, 4], 5], 6]; console.log(flattenArray(nestedArray)); // 输出 [1, 2, 3, 4, 5, 6]
实际的面试过程中,建议多做模拟面试和实战练习。可以找朋友或同学一起模拟面试场景,互相提问和回答问题。此外,可以参考一些在线编程平台,如慕课网,多做一些练习题,提高自己的编程能力和面试技巧。
// 示例:实现一个链表 class ListNode { constructor(val, next = null) { this.val = val; this.next = next; } } function addTwoNumbers(l1, l2) { let dummyHead = new ListNode(0); let p = l1, q = l2; let carry = 0; let curr = dummyHead; while (p !== null || q !== null) { let x = (p !== null) ? p.val : 0; let y = (q !== null) ? q.val : 0; let sum = carry + x + y; carry = Math.floor(sum / 10); curr.next = new ListNode(sum % 10); curr = curr.next; if (p !== null) p = p.next; if (q !== null) q = q.next; } if (carry > 0) { curr.next = new ListNode(carry); } return dummyHead.next; }
通过不断练习和反馈,逐步提高自己的编程水平和面试技巧。