ES新增语法和优化用法

1、空值合并赋值操作符 ??= 

在 ECMAScript 2021 (ES12) 中作为逻辑赋值运算符提案的一部分正式引入。

只在当前值为 null 或 undefined 时,它才会赋予一个新的值。
 user.name = user.name ?? 'Anonymous';
 user.name ??= 'Anonymous';

替换掉以下写法

 if (user.name === null || user.name === undefined) {
   user.name = 'Anonymous';
 }
以下写法会替换掉空值和0,false
 user.name = user.name || 'Anonymous';  // Replaces '', 0, false too

2、柯里化(Currying)

柯里化是一种函数的转换,它是指将一个函数从可调用的 f(a, b, c) 转换为可调用的 f(a)(b)(c)。

它可以让你在函数中预设参数,从而使代码更加模块化和可组合。可以解决重复传参的问题,并提高函数功能的适用性。
function curriedAdd(a){
    return function(b){
        return function(c){
            return a + b + c
        }
    }
}

 const applyDiscount = (discount) => (price) => price - (price * discount / 100);
const applyTax = (taxRate) => (price) => price + (price * taxRate / 100);
const twentyPercentOff = applyDiscount(20);
const applyTenPercentTax = applyTax(10);

console.log(twentyPercentOff(100)); // 80
 console.log(applyTenPercentTax(100)); // 110

 console.log(applyTenPercentTax(twentyPercentOff(100))); // 88

 3、解构赋值别名

 const apiResponse = {
     first_name: 'John',
     address: {
         city: 'New York',
     }
 };
 const {
     first_name: firstName,
     address: {
         city: hometown,
     }
 } = apiResponse;
 console.log(firstName); // John
 console.log(hometown); // New York

4、防抖与节流

核心目的是减少函数执行的频率,从而提高程序的性能和响应速度。

函数防抖关注一定时间连续触发的事件只在最后执行一次(适用于搜索框、窗口resize),而函数节流侧重于一段时间内只执行一次(适用于滚动加载,点击提交)。
防抖是在事件被触发delay秒后再执行回调,如果在这delay秒内又被触发,则重新计时。
 function debounce(func, delay) {
   let timeoutId;
   return function(...args) {
     clearTimeout(timeoutId);
     timeoutId = setTimeout(() => func.apply(this, args), delay);
   };
 }

 const search = debounce((query) => {
   console.log(`Searching for ${query}`);
   // Imagine an API call here
 }, 300);

 document.getElementById('searchInput').addEventListener('input', (event) => {
   search(event.target.value);
 });
函数节流的目的,是为了限制函数一段时间内只能执行一次。
function throttle(func, interval) {
   let lastCall = 0;
   return function(...args) {
     const now = Date.now();
     if (now - lastCall >= interval) { //超过设定时间,才执行
       lastCall = now;
       func.apply(this, args);
     }
   };
 }

 const handleScroll = throttle(() => {
   console.log('Scrolled');
   // Imagine complex calculations or DOM updates here
 }, 300);

 window.addEventListener('scroll', handleScroll);

5、memoization 是一种优化技术

如果没有采用记忆化技术,每次调用斐波那契函数都会重复计算相同的值多次,导致时间复杂度呈指数级增长。

 const memoize = (fn) => {
   const cache = {};
   return (...args) => {
     const key = JSON.stringify(args);
     if (!cache[key]) {
       cache[key] = fn(...args);
     }
     return cache[key];
   };
 };

 const fibonacci = memoize((n) => {
   if (n <= 1) return n;
   return fibonacci(n - 1) + fibonacci(n - 2);
 });

 console.log(fibonacci(40)); // 102334155

6、代理对象

创建代理,从而能够拦截并重新定义基本操作,如属性查找、赋值、枚举、函数调用等。这为向对象添加自定义行为提供了一种强大的方式。

const user = {
   name: 'John',
   age: 30
 };

 const handler = {
   get: (target, prop) => {
     console.log(`Getting ${prop}`);
     return target[prop];
   },

   set: (target, prop, value) => {
     if (prop === 'age' && typeof value !== 'number') {
       throw new TypeError('Age must be a number');
     }

     console.log(`Setting ${prop} to ${value}`);

     target[prop] = value;
     return true;
   }
 };

 const proxyUser = new Proxy(user, handler); //创建代理

 console.log(proxyUser.name); // Getting name, John

 proxyUser.age = 35; // Setting age to 35 拦截后重新定义

7、生成器函数function*

生成器函数是通过function*语法定义的特殊函数,它可以在执行过程中暂停,并在稍后恢复执行。yield关键字使生成器函数的执行暂停,并将yield关键字后面的表达式的值返回给生成器的调用者。

function* countAppleSales() {
const saleList = [3, 7, 5];
for (let i = 0; i < saleList.length; i++) {
yield saleList[i];
}
}

const appleStore = countAppleSales();

console.log(appleStore.next()); // { value: 3, done: false }

console.log(appleStore.next()); // { value: 7, done: false }

8、structuredClone 深度克隆对象

结构化克隆会创建对象的深层复制,确保嵌套的对象也被复制。这种方法避免了 JSON.parse(JSON.stringify(obj)) 的限制,如函数, undefined 和循环引用。

 const clonedObj = structuredClone(obj);

9、获取数据报错处理

解构失败

const handleData = (data)=> {
  const { user } = data;
  const { id, name } = user || {};
}

handleData({user: null})

数组

const handleData = (data)=> {
  const { userList } = data;
  if(Array.isArray(userList)){
    const newList = userList.map((item)=> item.name)
  }
}

handleData({userList: 123})

对象

const handleData = (data)=> {
  const { userList } = data;
  const newList = userList.map((item)=> {
    const { id, name, age } = item || {};
    return `用户id是${id},用户名字是${name},用户年龄是${age}岁了`
  });
}

handleData({userList: [null]})

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注