Skip to content

代码片段

深拷贝

js
// 一个简单的深拷贝函数,去掉了一些胶水部分
// 用户态输入一定是一个 Plain Object,并且所有 value 也是 Plain Object
function deepClone(obj) {
  const keys = Object.keys(obj);
  return keys.reduce((memo, current) => {
    const value = obj[current];
    if (typeof value === "object") {
      return {
        ...memo,
        [current]: deepClone(value)
      };
    }
    return {
      ...memo,
      [current]: value
    };
  }, {});
}
let a = {
  val: 1,
  desc: {
    text: "a"
  }
};

let b = deepClone(a);

b.val = 2;
console.log(a.val); // 1
console.log(b.val); // 2

b.desc.text = "b";
console.log(a.desc.text); // 'a'
console.log(b.desc.text); // 'b'
// 一个简单的深拷贝函数,去掉了一些胶水部分
// 用户态输入一定是一个 Plain Object,并且所有 value 也是 Plain Object
function deepClone(obj) {
  const keys = Object.keys(obj);
  return keys.reduce((memo, current) => {
    const value = obj[current];
    if (typeof value === "object") {
      return {
        ...memo,
        [current]: deepClone(value)
      };
    }
    return {
      ...memo,
      [current]: value
    };
  }, {});
}
let a = {
  val: 1,
  desc: {
    text: "a"
  }
};

let b = deepClone(a);

b.val = 2;
console.log(a.val); // 1
console.log(b.val); // 2

b.desc.text = "b";
console.log(a.desc.text); // 'a'
console.log(b.desc.text); // 'b'

柯里化1

js
// 实现一个add方法,使计算结果能够满足如下预期:

function add() {
  // 第一次执行时,定义一个数组专门用来存储所有的参数
  // let _args = Array.prototype.slice.call(arguments);
  let _args = Array.from(arguments);
  console.log("_args=" + _args);
  // 在内部声明一个函数,利用闭包的特性保存_args并收集所有的参数值
  let _adder = function () {
    _args.push(...arguments);
    return _adder;
  };

  // 利用toString隐式转换的特性,当最后执行时隐式转换,并计算最终的值返回
  _adder.toString = () => _args.reduce((a, b) => a + b);
  return _adder;
}

add(1)(2)(3); // 6
// add(1, 2, 3)(4); // 10
// add(1)(2)(3)(4)(5); // 15
// add(2, 6)(1); // 9

const curry = (fn, arr = []) => {
  return (...args) => {
    //判断参数总数是否和fn参数个数相等
    if ([...arr, ...args].length === fn.length) {
      return fn(...arr, ...args); //拓展参数,调用fn
    } else {
      return curry(fn, [...arr, ...args]); //迭代,传入现有的所有参数
    }
  };
};
//test
function sum(a, b, c, d, e) {
  console.log("curry success");
  console.log([a, b, c, d, e]);
}
let sumFn = curry(sum);
sumFn(1)(2)(3)(5, 4); //6
sumFn(1)(2, 3)(4)(5); //6
// 实现一个add方法,使计算结果能够满足如下预期:

function add() {
  // 第一次执行时,定义一个数组专门用来存储所有的参数
  // let _args = Array.prototype.slice.call(arguments);
  let _args = Array.from(arguments);
  console.log("_args=" + _args);
  // 在内部声明一个函数,利用闭包的特性保存_args并收集所有的参数值
  let _adder = function () {
    _args.push(...arguments);
    return _adder;
  };

  // 利用toString隐式转换的特性,当最后执行时隐式转换,并计算最终的值返回
  _adder.toString = () => _args.reduce((a, b) => a + b);
  return _adder;
}

add(1)(2)(3); // 6
// add(1, 2, 3)(4); // 10
// add(1)(2)(3)(4)(5); // 15
// add(2, 6)(1); // 9

const curry = (fn, arr = []) => {
  return (...args) => {
    //判断参数总数是否和fn参数个数相等
    if ([...arr, ...args].length === fn.length) {
      return fn(...arr, ...args); //拓展参数,调用fn
    } else {
      return curry(fn, [...arr, ...args]); //迭代,传入现有的所有参数
    }
  };
};
//test
function sum(a, b, c, d, e) {
  console.log("curry success");
  console.log([a, b, c, d, e]);
}
let sumFn = curry(sum);
sumFn(1)(2)(3)(5, 4); //6
sumFn(1)(2, 3)(4)(5); //6

柯里化2

js
function curryingHelper(fn, ...args) {
  //第一个括号里的
  return function(...args2) {
    //第二个括号里的args2
    let _totalArgs = args.concat(args2);
    return fn.apply(this, _totalArgs);
  };
}
function betterCurryingHelper(fn, len=fn.length) {
  return function(...args2) {
    let allArgsFulfilled = args2.length >= len;//后面参数大于方法参数就停止便利

    // 如果参数全部满足,就可以终止递归调用
    if (allArgsFulfilled) {
      return fn.apply(this, args2);
    } else {
      let argsNeedFulfilled = [fn].concat(...args2);
      return betterCurryingHelper(
        curryingHelper.apply(this, argsNeedFulfilled),
        len- args2.length
      );
    }
  };
}
function showMsg(name, age, fruit) {
  console.log(
    `My name is ${name}, I'm ${age} years old,  and I like eat ${fruit}`
  );
}
let betterShowMsg = betterCurryingHelper(showMsg);
betterShowMsg("dreamapple", 22, "apple"); // My name is dreamapple, I'm 22 years old,  and I like eat apple
betterShowMsg("dreamapple", 22)("apple"); // My name is dreamapple, I'm 22 years old,  and I like eat apple
betterShowMsg("dreamapple")(22, "apple"); // My name is dreamapple, I'm 22 years old,  and I like eat apple
betterShowMsg("dreamapple")(22)("apple"); // My name is dreamapple, I'm 22 years old,  and I like eat apple
function curryingHelper(fn, ...args) {
  //第一个括号里的
  return function(...args2) {
    //第二个括号里的args2
    let _totalArgs = args.concat(args2);
    return fn.apply(this, _totalArgs);
  };
}
function betterCurryingHelper(fn, len=fn.length) {
  return function(...args2) {
    let allArgsFulfilled = args2.length >= len;//后面参数大于方法参数就停止便利

    // 如果参数全部满足,就可以终止递归调用
    if (allArgsFulfilled) {
      return fn.apply(this, args2);
    } else {
      let argsNeedFulfilled = [fn].concat(...args2);
      return betterCurryingHelper(
        curryingHelper.apply(this, argsNeedFulfilled),
        len- args2.length
      );
    }
  };
}
function showMsg(name, age, fruit) {
  console.log(
    `My name is ${name}, I'm ${age} years old,  and I like eat ${fruit}`
  );
}
let betterShowMsg = betterCurryingHelper(showMsg);
betterShowMsg("dreamapple", 22, "apple"); // My name is dreamapple, I'm 22 years old,  and I like eat apple
betterShowMsg("dreamapple", 22)("apple"); // My name is dreamapple, I'm 22 years old,  and I like eat apple
betterShowMsg("dreamapple")(22, "apple"); // My name is dreamapple, I'm 22 years old,  and I like eat apple
betterShowMsg("dreamapple")(22)("apple"); // My name is dreamapple, I'm 22 years old,  and I like eat apple

柯里化es6版本

js
const curry = (fn, ...args) =>
    // 函数的参数个数可以直接通过函数数的.length属性来访问
    args.length >= fn.length // 这个判断很关键!!!
        // 传入的参数大于等于原始函数fn的参数个数,则直接执行该函数
        ? fn(...args)
        /**
         * 传入的参数小于原始函数fn的参数个数时
         * 则继续对当前函数进行柯里化,返回一个接受所有参数(当前参数和剩余参数) 的函数
         */
        : (..._args) => curry(fn, ...args, ..._args);

function add1(x, y, z) {
  return x + y + z;
}
const add = curry(add1);
console.log(add(1, 2, 3));
console.log(add(1)(2)(3));
console.log(add(1, 2)(3));
console.log(add(1)(2, 3));
const curry = (fn, ...args) =>
    // 函数的参数个数可以直接通过函数数的.length属性来访问
    args.length >= fn.length // 这个判断很关键!!!
        // 传入的参数大于等于原始函数fn的参数个数,则直接执行该函数
        ? fn(...args)
        /**
         * 传入的参数小于原始函数fn的参数个数时
         * 则继续对当前函数进行柯里化,返回一个接受所有参数(当前参数和剩余参数) 的函数
         */
        : (..._args) => curry(fn, ...args, ..._args);

function add1(x, y, z) {
  return x + y + z;
}
const add = curry(add1);
console.log(add(1, 2, 3));
console.log(add(1)(2)(3));
console.log(add(1, 2)(3));
console.log(add(1)(2, 3));

debunce和throttle

js
const debounce = (fn, delay) => {
  let timer = null;
  return (...args) => {
    clearTimeout(timer);
    console.log(this);
    timer = setTimeout(() => {
      fn.apply(this, args);
    }, delay);
  };
};

const throttle = (fn, delay = 500) => {
  let flag = true;
  return (...args) => {
    if (!flag) return;
    flag = false;
    setTimeout(() => {
      fn.apply(this, args);
      flag = true;
    }, delay);
  };
};

function con(...args) {
  console.log(args);
  console.log("hello");
}
throttle(con, 2000);
const debounce = (fn, delay) => {
  let timer = null;
  return (...args) => {
    clearTimeout(timer);
    console.log(this);
    timer = setTimeout(() => {
      fn.apply(this, args);
    }, delay);
  };
};

const throttle = (fn, delay = 500) => {
  let flag = true;
  return (...args) => {
    if (!flag) return;
    flag = false;
    setTimeout(() => {
      fn.apply(this, args);
      flag = true;
    }, delay);
  };
};

function con(...args) {
  console.log(args);
  console.log("hello");
}
throttle(con, 2000);

deepfreeze

js
function deepFreeze(object) {
  let propNames = Object.getOwnPropertyNames(object);
  for (let name of propNames) {
    let value = object[name];
    object[name] =
      value && typeof value === "object" ? deepFreeze(value) : value;
  }
  return Object.freeze(object);
}
//? hlsdfjsdlkfs
//x dkfdlsfj k
let person = {
  name: "Leonardo",
  profession: {
    name: "developer",
  },
};
deepFreeze(person);
person.profession.name = "doctor"; // TypeError: Cannot assign to read only property 'name' of object
function deepFreeze(object) {
  let propNames = Object.getOwnPropertyNames(object);
  for (let name of propNames) {
    let value = object[name];
    object[name] =
      value && typeof value === "object" ? deepFreeze(value) : value;
  }
  return Object.freeze(object);
}
//? hlsdfjsdlkfs
//x dkfdlsfj k
let person = {
  name: "Leonardo",
  profession: {
    name: "developer",
  },
};
deepFreeze(person);
person.profession.name = "doctor"; // TypeError: Cannot assign to read only property 'name' of object

不可复制

vue

<template>
  <p id="h">和律师费</p>
  <p id="h1">和律师费</p>
  <p id="h2">和律师费</p>
  <p id="h3">和律师费</p>
  <input type="text" />
</template>

<script setup lang="ts">
// 禁止右键菜单
document.body.oncontextmenu = (e) => {
  console.log(e, '右键')
  return false
  // e.preventDefault();
}
// 禁止文字选择。
document.body.onselectstart = (e) => {
  console.log(e, '文字选择')
  return false
  // e.preventDefault();
}
// 禁止复制
document.body.oncopy = (e) => {
  console.log(e, 'copy')
  return false
  // e.preventDefault();
}
// 禁止剪切
document.body.oncut = (e) => {
  console.log(e, 'cut')
  return false
  // e.preventDefault();
}
// 禁止粘贴
document.body.onpaste = (e) => {
  console.log(e, 'paste')
  return false
  // e.preventDefault();
}
window.onload = function f1() {
  f2()
}

function f2() {
  console.log('hello')
  arraytest()
}

function arraytest() {
  for (let i = 1; i < 100; i++) {
    console.log((i + i) ^ 2)
  }
}
console.log('代码执行结束')
document.body.onpaste = (e) => {
  let clipboardData = e.clipboardData || window.clipboardData // 兼容处理
  console.log('要粘贴的数据', clipboardData.getData('text'))
}
</script>

<template>
  <p id="h">和律师费</p>
  <p id="h1">和律师费</p>
  <p id="h2">和律师费</p>
  <p id="h3">和律师费</p>
  <input type="text" />
</template>

<script setup lang="ts">
// 禁止右键菜单
document.body.oncontextmenu = (e) => {
  console.log(e, '右键')
  return false
  // e.preventDefault();
}
// 禁止文字选择。
document.body.onselectstart = (e) => {
  console.log(e, '文字选择')
  return false
  // e.preventDefault();
}
// 禁止复制
document.body.oncopy = (e) => {
  console.log(e, 'copy')
  return false
  // e.preventDefault();
}
// 禁止剪切
document.body.oncut = (e) => {
  console.log(e, 'cut')
  return false
  // e.preventDefault();
}
// 禁止粘贴
document.body.onpaste = (e) => {
  console.log(e, 'paste')
  return false
  // e.preventDefault();
}
window.onload = function f1() {
  f2()
}

function f2() {
  console.log('hello')
  arraytest()
}

function arraytest() {
  for (let i = 1; i < 100; i++) {
    console.log((i + i) ^ 2)
  }
}
console.log('代码执行结束')
document.body.onpaste = (e) => {
  let clipboardData = e.clipboardData || window.clipboardData // 兼容处理
  console.log('要粘贴的数据', clipboardData.getData('text'))
}
</script>

去重

ts
function useFilter() {
  let str =
    // 长度为14的数组
    [4, 5, 56, 56, 78, 23, 4, 5, 6, 90, 56, 34]

  let res = []
  str.forEach((item, index) => {
    if (!res.includes(item)) {
      res.push(item)
    }
  })
  console.log(res)
}
function useIndexof() {
  let str =
    // 长度为14的数组
    [4, 5, 56, 56, 78, 23, 4, 5, 6, 90, 56, 34]
  let result = []
  str.forEach((item, index) => {
    if (str.indexOf(item) === index) {
      result.push(item)
    }
  })
  console.log(result)
}
function useReduce() {
  let str =
    // 长度为14的数组
    [4, 5, 56, 56, 78, 23, 4, 5, 6, 90, 56, 34]
  let unique = (arr) => {
    if (!Array.isArray(arr)) return
    return arr.reduce(
      (prev, cur) => (prev.includes(cur) ? prev : [...prev, cur]),
      [],
    )
  }
  console.log(unique(str))
  // 打印数组长度20:[false, "true", Infinity, true, 0, [],  [], {b: 2, a: 1}, {b: 2, a: 1}, {}, {}, "false", "0", null, undefined, {a: 1, b: 2}, {a: 1, b: 2}, NaN, function(){}, function(){}]
}

function useSet() {
  let str =
    // 长度为14的数组
    [4, 5, 56, 56, 78, 23, 4, 5, 6, 90, 56, 34]

  let s = [...new Set(str)]
  console.log(s)
}
function useFilter() {
  let str =
    // 长度为14的数组
    [4, 5, 56, 56, 78, 23, 4, 5, 6, 90, 56, 34]

  let res = []
  str.forEach((item, index) => {
    if (!res.includes(item)) {
      res.push(item)
    }
  })
  console.log(res)
}
function useIndexof() {
  let str =
    // 长度为14的数组
    [4, 5, 56, 56, 78, 23, 4, 5, 6, 90, 56, 34]
  let result = []
  str.forEach((item, index) => {
    if (str.indexOf(item) === index) {
      result.push(item)
    }
  })
  console.log(result)
}
function useReduce() {
  let str =
    // 长度为14的数组
    [4, 5, 56, 56, 78, 23, 4, 5, 6, 90, 56, 34]
  let unique = (arr) => {
    if (!Array.isArray(arr)) return
    return arr.reduce(
      (prev, cur) => (prev.includes(cur) ? prev : [...prev, cur]),
      [],
    )
  }
  console.log(unique(str))
  // 打印数组长度20:[false, "true", Infinity, true, 0, [],  [], {b: 2, a: 1}, {b: 2, a: 1}, {}, {}, "false", "0", null, undefined, {a: 1, b: 2}, {a: 1, b: 2}, NaN, function(){}, function(){}]
}

function useSet() {
  let str =
    // 长度为14的数组
    [4, 5, 56, 56, 78, 23, 4, 5, 6, 90, 56, 34]

  let s = [...new Set(str)]
  console.log(s)
}

一些技巧

ts
/**
 * 1. 确保数组值
 * @type {any[]}
 */
const array = Array(5).fill(``)
console.log(array)
/*2. 获取数组唯一值*/
const cars = [`Mazda`, `Ford`, `Renault`, `Opel`, `Mazda`]
const uniqueWithArrayFrom = Array.from(new Set(cars))
console.log(uniqueWithArrayFrom)

const uniqueWithSpreadOperator = [...new Set(cars)]
console.log(uniqueWithSpreadOperator)

// Merging objects
const product = { name: `Milk`, packaging: `Plastic`, price: `5$` }
const manufacturer = { name: `Company Name`, address: `The Company Address` }
/*3.使用展开运算符合并对象和对象数组*/
const productManufacturer = { ...product, ...manufacturer }
console.log(productManufacturer)

// Merging an array of objects into one
const cities = [
  { name: `Paris`, visited: `no` },
  { name: `Lyon`, visited: `no` },
  { name: `Marseille`, visited: `yes` },
  { name: `Rome`, visited: `yes` },
  { name: `Milan`, visited: `no` },
  { name: `Palermo`, visited: `yes` },
  { name: `Genoa`, visited: `yes` },
  { name: `Berlin`, visited: `no` },
  { name: `Hamburg`, visited: `yes` },
  { name: `New York`, visited: `yes` },
]

const result = cities.reduce(
  (accumulator, item) => ({
    ...accumulator,
    [item.name]: item.visited,
  }),
  {},
)

console.log(result)
/*数组map的方法*/
const cityNames = Array.from(cities, ({ name }) => name)
console.log(cityNames)
//有条件的对象属性
const getUser = (emailIncluded) => ({
  name: `John`,
  surname: `Doe`,
  ...(emailIncluded && { email: 'john@doe.com' }),
})

const user = getUser(true)
console.log(user) // Outputs { name: "John", surname: "Doe", email: "john@doe.com" }

const userWithoutEmail = getUser(false)
console.log(userWithoutEmail) // Outputs { name: "John", surname: "Doe" }
//结构原始数据
const rawUser = {
  name: `John`,
  surname: `Doe`,
  email: `john@doe.com`,
  displayName: `SuperCoolJohn`,
  joined: `2016-05-05`,
  image: `path-to-the-image`,
  followers: 45,
}
const user3 = {}
let userDetails = {}
;({ name: user.name, surname: user.surname, ...userDetails } = rawUser)
console.log(user3)
console.log(userDetails)
//动态属性名
const dynamic = `email`
const user4 = {
  name: `John`,
  [dynamic]: `john@doe.com`,
}
console.log(user4)
//字符串差值
const user5 = {
  name: `John`,
  surname: `Doe`,
  details: {
    email: `john@doe.com`,
    displayName: `SuperCoolJohn`,
    joined: `2016-05-05`,
    image: `path-to-the-image`,
    followers: 45,
  },
}

const printUserInfo = (user) => {
  const text = `The user is ${user.name} ${user.surname}. Email: ${user.details.email}. Display Name: ${user.details.displayName}. ${user.name} has ${user.details.followers} followers.`
  console.log(text)
}

printUserInfo(user5)
/**
 * 1. 确保数组值
 * @type {any[]}
 */
const array = Array(5).fill(``)
console.log(array)
/*2. 获取数组唯一值*/
const cars = [`Mazda`, `Ford`, `Renault`, `Opel`, `Mazda`]
const uniqueWithArrayFrom = Array.from(new Set(cars))
console.log(uniqueWithArrayFrom)

const uniqueWithSpreadOperator = [...new Set(cars)]
console.log(uniqueWithSpreadOperator)

// Merging objects
const product = { name: `Milk`, packaging: `Plastic`, price: `5$` }
const manufacturer = { name: `Company Name`, address: `The Company Address` }
/*3.使用展开运算符合并对象和对象数组*/
const productManufacturer = { ...product, ...manufacturer }
console.log(productManufacturer)

// Merging an array of objects into one
const cities = [
  { name: `Paris`, visited: `no` },
  { name: `Lyon`, visited: `no` },
  { name: `Marseille`, visited: `yes` },
  { name: `Rome`, visited: `yes` },
  { name: `Milan`, visited: `no` },
  { name: `Palermo`, visited: `yes` },
  { name: `Genoa`, visited: `yes` },
  { name: `Berlin`, visited: `no` },
  { name: `Hamburg`, visited: `yes` },
  { name: `New York`, visited: `yes` },
]

const result = cities.reduce(
  (accumulator, item) => ({
    ...accumulator,
    [item.name]: item.visited,
  }),
  {},
)

console.log(result)
/*数组map的方法*/
const cityNames = Array.from(cities, ({ name }) => name)
console.log(cityNames)
//有条件的对象属性
const getUser = (emailIncluded) => ({
  name: `John`,
  surname: `Doe`,
  ...(emailIncluded && { email: 'john@doe.com' }),
})

const user = getUser(true)
console.log(user) // Outputs { name: "John", surname: "Doe", email: "john@doe.com" }

const userWithoutEmail = getUser(false)
console.log(userWithoutEmail) // Outputs { name: "John", surname: "Doe" }
//结构原始数据
const rawUser = {
  name: `John`,
  surname: `Doe`,
  email: `john@doe.com`,
  displayName: `SuperCoolJohn`,
  joined: `2016-05-05`,
  image: `path-to-the-image`,
  followers: 45,
}
const user3 = {}
let userDetails = {}
;({ name: user.name, surname: user.surname, ...userDetails } = rawUser)
console.log(user3)
console.log(userDetails)
//动态属性名
const dynamic = `email`
const user4 = {
  name: `John`,
  [dynamic]: `john@doe.com`,
}
console.log(user4)
//字符串差值
const user5 = {
  name: `John`,
  surname: `Doe`,
  details: {
    email: `john@doe.com`,
    displayName: `SuperCoolJohn`,
    joined: `2016-05-05`,
    image: `path-to-the-image`,
    followers: 45,
  },
}

const printUserInfo = (user) => {
  const text = `The user is ${user.name} ${user.surname}. Email: ${user.details.email}. Display Name: ${user.details.displayName}. ${user.name} has ${user.details.followers} followers.`
  console.log(text)
}

printUserInfo(user5)
ts
{
  /**
   * @Author  yanni
   * @Description    //TODO
   * 1.使用 Array.includes 来处理多个条件
   * @Date  18:32 2019/7/14
   * @Modified By:
   */
  console.log(`__________1.使用 Array.includes 来处理多个条件_________________`)
  // bad
  const testbad = (fruit: string) => {
    if (fruit === `apple` || fruit === `strawberry`) {
      console.log(`red`)
    }
  }
  // good
  const testgood = (fruit: string) => {
    // 条件提取到数组中
    const redFruits = [`apple`, `strawberry`, `cherry`, `cranberries`]

    if (redFruits.includes(fruit)) {
      console.log(`red`)
    }
  }
}
{
  console.log(`__________2.减少嵌套,提前使用 return 语句_________________`)
  /**
   * @Author  yanni
   * @Description    //TODO
   * 2.减少嵌套,提前使用 return 语句
   * @Date  18:33 2019/7/14
   * @Modified By:
   */
  //good
  const testredfruit = (fruit: string, quantity: number | undefined) => {
    const redFruits = [`apple`, `strawberry`, `cherry`, `cranberries`]

    // 条件 1:fruit 必须有值
    if (fruit) {
      // 条件 2:必须为红色
      if (redFruits.includes(fruit)) {
        console.log(`red`)

        // 条件 3:数量必须大于 10
        if (quantity > 10) {
          console.log(`big quantity`)
        }
      }
    } else {
      throw new Error(`No fruit!`)
    }
  }

  // 测试结果
  // testredfruit(null); // 抛出错误:No fruits
  testredfruit(`apple`) // 打印:red
  testredfruit(`apple`, 20) // 打印:red,big quantity

  /* 在发现无效条件时提前 return */
  // better
  const test2 = (fruit, quantity) => {
    const redFruits = [`apple`, `strawberry`, `cherry`, `cranberries`]

    // 条件 1:提前抛出错误
    if (!fruit) throw new Error(`No fruit!`)

    // 条件2:必须为红色
    if (redFruits.includes(fruit)) {
      console.log(`red`)

      // 条件 3:数量必须大于 10
      if (quantity > 10) {
        console.log(`big quantity`)
      }
    }
  }
  //best
  /* 在发现无效条件时提前 return */

  const test3 = (fruit: string, quantity: number) => {
    const redFruits = [`apple`, `strawberry`, `cherry`, `cranberries`]

    if (!fruit) throw new Error(`No fruit!`) // 条件 1:提前抛出错误
    if (!redFruits.includes(fruit)) return // 条件 2:当 fruit 不是红色的时候,提前 return

    console.log(`red`)

    // 条件 3:必须是大量存在
    if (quantity > 10) {
      console.log(`big quantity`)
    }
  }
}
{
  console.log(`_________3.使用函数的默认参数 和 解构____________________`)
  const testfrout = (fruit, quantity = 1) => {
    // i如果没有提供 quantity 参数,则默认为 1
    if (!fruit) return
    console.log(`We have ${quantity} ${fruit}!`)
  }

  // 测试结果
  testfrout(`banana`) // We have 1 banana!
  testfrout(`apple`, 2) // We have 2 apple!
}
{
  console.log(
    `___________4.选择 Map / Object 字面量,而不是Switch语句_________________`,
  )
  //bad
  function testapple1(color) {
    // 使用 switch case 语句,根据颜色找出对应的水果
    switch (color) {
      case `red`:
        return [`apple`, `strawberry`]
      case `yellow`:
        return [`banana`, `pineapple`]
      case `purple`:
        return [`grape`, `plum`]
      default:
        return []
    }
  }

  //测试结果
  testapple1(null) // []
  testapple1(`yellow`) // ['banana', 'pineapple']
  //good
  // 使用对象字面量,根据颜色找出对应的水果
  const fruitColor = {
    red: [`apple`, `strawberry`],
    yellow: [`banana`, `pineapple`],
    purple: [`grape`, `plum`],
  }

  function testapple2(color) {
    return fruitColor[color] || []
  }
  //best
  // 使用 Map ,根据颜色找出对应的水果
  const fruitColorMap = new Map()
    .set(`red`, [`apple`, `strawberry`])
    .set(`yellow`, [`banana`, `pineapple`])
    .set(`purple`, [`grape`, `plum`])

  function testapple3(color) {
    return fruitColorMap.get(color) || []
  }
  console.log(
    `我们是不是应该禁止使用 switch 语句呢? 不要局限于此。 就个人而言,我尽可能使用对象字面量,但我不会设置硬规则来阻止使用 switch ,是否使用应该根据你的场景而决定`,
  )
  const fruits = [
    { name: `apple`, color: `red` },
    { name: `strawberry`, color: `red` },
    { name: `banana`, color: `yellow` },
    { name: `pineapple`, color: `yellow` },
    { name: `grape`, color: `purple` },
    { name: `plum`, color: `purple` },
  ]

  function testapple4(color) {
    // 使用 Array filter  ,根据颜色找出对应的水果

    return fruits.filter((f) => f.color === color)
  }
}
{
  console.log(`________________________________________________`)
  const fruits1 = [
    { name: `apple`, color: `red` },
    { name: `banana`, color: `yellow` },
    { name: `grape`, color: `purple` },
  ]

  function test3() {
    // 条件:简短方式,所有的水果都必须是红色
    const isAllRed = fruits1.every((f) => f.color === `red`)

    console.log(isAllRed) // false
  }
  const fruits2 = [
    { name: `apple`, color: `red` },
    { name: `banana`, color: `yellow` },
    { name: `grape`, color: `purple` },
  ]

  function testredfruit() {
    // 条件:是否存在红色的水果
    const isAnyRed = fruits2.some((f) => f.color == `red`)

    console.log(isAnyRed) // true
  }
}

export {}
{
  /**
   * @Author  yanni
   * @Description    //TODO
   * 1.使用 Array.includes 来处理多个条件
   * @Date  18:32 2019/7/14
   * @Modified By:
   */
  console.log(`__________1.使用 Array.includes 来处理多个条件_________________`)
  // bad
  const testbad = (fruit: string) => {
    if (fruit === `apple` || fruit === `strawberry`) {
      console.log(`red`)
    }
  }
  // good
  const testgood = (fruit: string) => {
    // 条件提取到数组中
    const redFruits = [`apple`, `strawberry`, `cherry`, `cranberries`]

    if (redFruits.includes(fruit)) {
      console.log(`red`)
    }
  }
}
{
  console.log(`__________2.减少嵌套,提前使用 return 语句_________________`)
  /**
   * @Author  yanni
   * @Description    //TODO
   * 2.减少嵌套,提前使用 return 语句
   * @Date  18:33 2019/7/14
   * @Modified By:
   */
  //good
  const testredfruit = (fruit: string, quantity: number | undefined) => {
    const redFruits = [`apple`, `strawberry`, `cherry`, `cranberries`]

    // 条件 1:fruit 必须有值
    if (fruit) {
      // 条件 2:必须为红色
      if (redFruits.includes(fruit)) {
        console.log(`red`)

        // 条件 3:数量必须大于 10
        if (quantity > 10) {
          console.log(`big quantity`)
        }
      }
    } else {
      throw new Error(`No fruit!`)
    }
  }

  // 测试结果
  // testredfruit(null); // 抛出错误:No fruits
  testredfruit(`apple`) // 打印:red
  testredfruit(`apple`, 20) // 打印:red,big quantity

  /* 在发现无效条件时提前 return */
  // better
  const test2 = (fruit, quantity) => {
    const redFruits = [`apple`, `strawberry`, `cherry`, `cranberries`]

    // 条件 1:提前抛出错误
    if (!fruit) throw new Error(`No fruit!`)

    // 条件2:必须为红色
    if (redFruits.includes(fruit)) {
      console.log(`red`)

      // 条件 3:数量必须大于 10
      if (quantity > 10) {
        console.log(`big quantity`)
      }
    }
  }
  //best
  /* 在发现无效条件时提前 return */

  const test3 = (fruit: string, quantity: number) => {
    const redFruits = [`apple`, `strawberry`, `cherry`, `cranberries`]

    if (!fruit) throw new Error(`No fruit!`) // 条件 1:提前抛出错误
    if (!redFruits.includes(fruit)) return // 条件 2:当 fruit 不是红色的时候,提前 return

    console.log(`red`)

    // 条件 3:必须是大量存在
    if (quantity > 10) {
      console.log(`big quantity`)
    }
  }
}
{
  console.log(`_________3.使用函数的默认参数 和 解构____________________`)
  const testfrout = (fruit, quantity = 1) => {
    // i如果没有提供 quantity 参数,则默认为 1
    if (!fruit) return
    console.log(`We have ${quantity} ${fruit}!`)
  }

  // 测试结果
  testfrout(`banana`) // We have 1 banana!
  testfrout(`apple`, 2) // We have 2 apple!
}
{
  console.log(
    `___________4.选择 Map / Object 字面量,而不是Switch语句_________________`,
  )
  //bad
  function testapple1(color) {
    // 使用 switch case 语句,根据颜色找出对应的水果
    switch (color) {
      case `red`:
        return [`apple`, `strawberry`]
      case `yellow`:
        return [`banana`, `pineapple`]
      case `purple`:
        return [`grape`, `plum`]
      default:
        return []
    }
  }

  //测试结果
  testapple1(null) // []
  testapple1(`yellow`) // ['banana', 'pineapple']
  //good
  // 使用对象字面量,根据颜色找出对应的水果
  const fruitColor = {
    red: [`apple`, `strawberry`],
    yellow: [`banana`, `pineapple`],
    purple: [`grape`, `plum`],
  }

  function testapple2(color) {
    return fruitColor[color] || []
  }
  //best
  // 使用 Map ,根据颜色找出对应的水果
  const fruitColorMap = new Map()
    .set(`red`, [`apple`, `strawberry`])
    .set(`yellow`, [`banana`, `pineapple`])
    .set(`purple`, [`grape`, `plum`])

  function testapple3(color) {
    return fruitColorMap.get(color) || []
  }
  console.log(
    `我们是不是应该禁止使用 switch 语句呢? 不要局限于此。 就个人而言,我尽可能使用对象字面量,但我不会设置硬规则来阻止使用 switch ,是否使用应该根据你的场景而决定`,
  )
  const fruits = [
    { name: `apple`, color: `red` },
    { name: `strawberry`, color: `red` },
    { name: `banana`, color: `yellow` },
    { name: `pineapple`, color: `yellow` },
    { name: `grape`, color: `purple` },
    { name: `plum`, color: `purple` },
  ]

  function testapple4(color) {
    // 使用 Array filter  ,根据颜色找出对应的水果

    return fruits.filter((f) => f.color === color)
  }
}
{
  console.log(`________________________________________________`)
  const fruits1 = [
    { name: `apple`, color: `red` },
    { name: `banana`, color: `yellow` },
    { name: `grape`, color: `purple` },
  ]

  function test3() {
    // 条件:简短方式,所有的水果都必须是红色
    const isAllRed = fruits1.every((f) => f.color === `red`)

    console.log(isAllRed) // false
  }
  const fruits2 = [
    { name: `apple`, color: `red` },
    { name: `banana`, color: `yellow` },
    { name: `grape`, color: `purple` },
  ]

  function testredfruit() {
    // 条件:是否存在红色的水果
    const isAnyRed = fruits2.some((f) => f.color == `red`)

    console.log(isAnyRed) // true
  }
}

export {}

Released under the MIT License.