返回

JavaScript 进阶能力,修炼你手写的知识点

前端

JavaScript 进阶手写知识点指南

1. new 操作符

概述: new 操作符用于创建 JavaScript 对象的实例,同时可以为新创建的对象自动执行构造函数。

原理: 当使用new操作符创建对象时,JavaScript引擎会执行以下步骤:

  • 创建一个新的空对象。
  • 为新对象分配内部属性[[Prototype]],该属性指向构造函数的原型对象。
  • 执行构造函数,并将构造函数的this指向新创建的对象。
  • 构造函数执行结束后,将新创建的对象返回给变量或表达式。

示例:

function Person(name, age) {
  this.name = name;
  this.age = age;
}

const person = new Person("John Doe", 30);

console.log(person.name); // "John Doe"
console.log(person.age); // 30

2. instanceof 操作符

概述: instanceof 操作符用于检测一个对象是否属于某个类的实例。

原理: instanceof 操作符通过以下步骤进行检测:

  • 获取对象的[[Prototype]]属性。
  • 检查对象的[[Prototype]]属性是否与给定类的原型对象相同。
  • 如果相同,则返回true,否则返回false。

示例:

function Person(name, age) {
  this.name = name;
  this.age = age;
}

const person = new Person("John Doe", 30);

console.log(person instanceof Person); // true
console.log(person instanceof Object); // true

3. 节流防抖

概述: 节流和防抖是两种常用的函数调用优化技术,用于控制函数的执行频率,防止函数被过度调用。

原理:

  • 节流:在一定时间间隔内,只允许函数执行一次。如果在该时间间隔内函数再次被调用,则忽略该调用。
  • 防抖:在一定时间间隔内,函数只执行一次。如果在该时间间隔内函数再次被调用,则取消上一次调用的计划执行,并重新开始计时。

示例:

// 节流函数
function throttle(func, wait) {
  let lastCall = 0;

  return function(...args) {
    const now = Date.now();

    if (now - lastCall >= wait) {
      lastCall = now;
      func.apply(this, args);
    }
  };
}

// 防抖函数
function debounce(func, wait) {
  let timerId = null;

  return function(...args) {
    clearTimeout(timerId);

    timerId = setTimeout(() => {
      func.apply(this, args);
    }, wait);
  };
}

4. 去重

概述: 去重是指从数组或对象中删除重复的元素,只保留唯一的元素。

原理: 去重的常用方法包括:

  • 借助 Set 对象:Set 对象可以自动去除重复元素。
  • 使用 indexOf 方法:通过 indexOf 方法查找重复元素,然后删除它们。
  • 使用 filter 方法:通过 filter 方法过滤掉重复元素。

示例:

// 使用 Set 对象去重
const arr = [1, 2, 3, 4, 5, 1, 2, 3];
const uniqueArr = [...new Set(arr)];

console.log(uniqueArr); // [1, 2, 3, 4, 5]

// 使用 indexOf 方法去重
const arr = [1, 2, 3, 4, 5, 1, 2, 3];
const uniqueArr = [];

for (let i = 0; i < arr.length; i++) {
  if (uniqueArr.indexOf(arr[i]) === -1) {
    uniqueArr.push(arr[i]);
  }
}

console.log(uniqueArr); // [1, 2, 3, 4, 5]

// 使用 filter 方法去重
const arr = [1, 2, 3, 4, 5, 1, 2, 3];
const uniqueArr = arr.filter((item, index) => arr.indexOf(item) === index);

console.log(uniqueArr); // [1, 2, 3, 4, 5]

5. call、apply、bind

概述: call、apply 和 bind 都是 JavaScript 中用来改变函数调用上下文的方法。

原理:

  • call 和 apply:这两种方法都允许你将一个函数的调用上下文设置为指定的对象。
  • bind:bind 方法返回一个新的函数,该函数的调用上下文被绑定到指定的对象上。

示例:

// call 方法
const obj = {
  name: "John Doe"
};

function greet() {
  console.log(`Hello, ${this.name}!`);
}

greet.call(obj); // "Hello, John Doe!"

// apply 方法
const obj = {
  name: "John Doe"
};

function greet() {
  console.log(`Hello, ${this.name}!`);
}

greet.apply(obj); // "Hello, John Doe!"

// bind 方法
const obj = {
  name: "John Doe"
};

function greet() {
  console.log(`Hello, ${this.name}!`);
}

const boundGreet = greet.bind(obj);

boundGreet(); // "Hello, John Doe!"

6. 深拷贝

概述: 深拷贝是指创建一个新对象,该对象包含原始对象的副本,包括原始对象的所有属性和嵌套对象。

原理: 深拷贝的常用方法包括:

  • 使用 JSON.parse() 和 JSON.stringify():这两种方法可以将对象转换为 JSON 字符串,然后再将 JSON 字符串解析回对象。
  • 使用递归:通过递归的方式,将原始对象的所有属性和嵌套对象复制到新对象中。

示例:

// 使用 JSON.parse() 和 JSON.stringify() 进行深拷贝
const obj = {
  name: "John Doe",
  age: 30,
  address: {
    street: "123 Main Street",
    city: "Anytown",
    state: "CA",
    zip: "12345"
  }
};

const copyObj = JSON.parse(JSON.stringify(obj));

console.log(copyObj);
// 使用递归进行深拷贝
const obj = {
  name: "John Doe",
  age: 30,
  address: {
    street: "123 Main Street",
    city: "Anytown",
    state: "CA",
    zip: "12345"
  }
};

function deepCopy(obj) {
  if (typeof obj === "object") {
    const copyObj = {};

    for (const key in obj) {
      copyObj[key] = deepCopy(obj[key]);
    }

    return copyObj;
  } else {
    return obj;
  }
}

const copyObj = deepCopy(obj);

console.log(copyObj);