Javascript 高效开发工具函数

6 篇文章 0 订阅
3 篇文章 0 订阅

数组

对象

函数

字符串

数字

浏览器

环境

一、数组

multArray二维数组转换

将数组(array)拆分成多个子数组,并将这些子数组组成一个新数组。

multArray(array, count)

参数

  • array需要处理的数组
  • count = 8子数组需要的长度

示例

multArray([1, 2, 3, 4, 5, 6], 2)
=> [[1, 2], [3, 4], [5, 6]]

multArray(['a', 'b', 'c', 'd'], 3)
=> [['a', 'b', 'c'], ['d']]

源码

multArray([1, 2, 3, 4, 5, 6], 2)
=> [[1, 2], [3, 4], [5, 6]]

multArray(['a', 'b', 'c', 'd'], 3)
=> [['a', 'b', 'c'], ['d']]

源码

/**
 * @description: 
 * @param {*} arr
 * @param {*} count
 * @return {*}
 */
const multArray = (arr, count = 2) => {
    let pages = [];
    arr.forEach((item, index) => {
        const page = Math.floor(index / count);
        (!pages[page]) && (pages[page] = []);
        pages[page].push(item);
    });
    return pages;
};

flatten扁平化数组

将多层嵌套数组(array)拆分成一个数组

flatten(array)

参数

  • array多层嵌套数组

示例

flatten([1, [2], [3], [4, 5]])

// [1, 2, 3, 4, 5]

源码

/**
 * @description: 扁平化
 * @param {*} arr The array
 * @return {*} array
 */
// 扁平化  Map 方法
const flatten = arr => [].concat(...arr.map(item => (Array.isArray(item) ? flatten(item) : item)));

// 扁平化  reduce 方法
const flatten = arr => arr.reduce((a, i) => a.concat(Array.isArray(i) ? flatten(i) : i), []);

flattenDeep指定层级扁平化数组

将多层嵌套数组(array)拆分成指定层级数组

flattenDeep(array, depth)

参数

  • array多层嵌套数组 depth = 减少的嵌套层级数

示例

flattenDeep(['a', ['b', ['c', ['d']], 'e']], 1)
// => ['a', 'b', ['c', ['d']], 'e']

// ES6方法 `flat(depth)`
['a', ['b', ['c', ['d']], 'e']].flat(1)
// => ['a', 'b', ['c', ['d']], 'e']

源码

 /**
  * @description: 扁平化数组
  * @param {*} arr
  * @param {*} depth
  * @return {*} array
  */ 
const flattenDeep = (arr, depth = 1) => arr.reduce((a, i) => a.concat(depth > 1 && Array.isArray(i) ? flatten(i, depth - 1) : i), []);

isArrayEqual检查两个数组各项相等

比较两个数组内的各项值是否相等,返回一个Boolean

isArrayEqual(arrOne, arrTwo)

参数

  • arrOne 要检查的数组
  • arrTwo 要检查的数组

示例

isArrayEqual([6, 5, 2, 4, 1, 3], [1, 2, 3, 4, 5, 6])
// => true

isArrayEqual([6, 5, 2, 7, 1, 3], [1, 2, 3, 4, 5, 6])
// => false

源码

/**
 * @description: 检查两个数组各项相等
 * @param {*} arr The array
 * @param {*} arr The array
 * @return {*} boolean
 */
const isArrayEqual = (a, b, res = true) => {
    if (a.length !== b.length) return (res = false);
    const s = new Set(b);
    if (a.find(x => !s.has(x))) return (res = false);
    return res;
};

allEqual检查数组各项相等

allEqual(array)

参数

  • array 要检查的数组

示例

allEqual([1, 2, 3, 4, 5, 6])
// => false

allEqual([1, 1, 1, 1])
// => true

源码

/**
 * @description: 筛选两个数组差异值
 * @param {*} arr The array
 * @return {*} array
 */
const allEqual = arr => arr.every(item => item === arr[0]);

diffArray具有唯一array值的数组

创建一个具有唯一 array 值的数组,每个值不包含在其他给定的数组中

diffArray(arrOne, arrTwo)

参数

  • arrOne 要检查的数组
  • arrTwo要排除的数组

示例

diffArray(['a', 2, 6, 7], ['a', 2, 9, 'b'])
// => [ 6, 7 ]

源码

/**
 * @description: 有唯一array值的数组
 * @param {*} arr The array
 * @return {*} array
 */
const diffArray = (a, b) => {
    const s = new Set(b);
    let arr = a.filter(x => !s.has(x));
    return arr;
}

haveArr具有共同array值的数组

创建一个具有共同 array 值的数组,每个值包含在其他给定的数组中

haveArr(arrOne, arrTwo)

参数

  • arrOne 要检查的数组
  • arrTwo要包含的数组

示例

haveArr([1, 2, 6, 7], [1, 2, 9, 5])
// => [ 1, 2 ]

源码

/**
 * @description: 具有共同`array`值的数组
 * @param {*} arr The array
 * @return {*} array
 */
const haveArr = (a, b) => {
    const s = new Set(b);
    return a.filter(x => s.has(x));
}
// ES6 includes
const haveArr = (arr, values) => arr.filter(v => values.includes(v));

uniqueArray数组去重

创建一个去重后的 array 数组副本

uniqueArray(array)

参数

  • array 要去重的数组

示例

uniqueArray([1, 2, 2, 3, 4, 4, 5])
// => [ 1, 2, 3, 4, 5 ]

源码

/**
 * @description: 数组去重
 * @param {*} arr The array
 * @return {*} array
 */
const uniqueArray = (...arr) => [...new Set(arr)];

const uniqueArray = (...arr) => Array.from(new Set(arr));

uniqueArrayObject数组对象去重

创建一个去重后的 array 数组对象副本

uniqueArrayObject(array)

参数

  • array 要去重的数组
  • key 要去重的对象属性值

示例

const responseList = [
    { id: 1, a: 1 },
    { id: 2, a: 2 },
    { id: 3, a: 3 },
    { id: 1, a: 4 },
    { id: 2, a: 2 },
    { id: 3, a: 3 },
    { id: 1, a: 4 },
    { id: 2, a: 2 },
    { id: 3, a: 3 },
    { id: 1, a: 4 },
    { id: 2, a: 2 },
    { id: 3, a: 3 },
    { id: 1, a: 4 },
]

uniqueArrayObject(responseList, 'id')

// => [ { id: 1, a: 1 }, { id: 2, a: 2 }, { id: 3, a: 3 } ]

源码

/**
 * @description: 数组对象去重
 * @param {*} arr The array
 * @return {*} array
 */
const uniqueArrayObject = (arr, key) => {
    return arr.reduce((acc, cur) => {
        const ids = acc.map(item => item[key]);
        return ids.includes(cur[key]) ? acc : [...acc, cur];
    }, []);
}

treeData生成树结构数据

该函数传入一个数组, 每项id对应其父级数据parent_id,返回一个树结构数组

treeData(array, id, parent_id)

参数

  • array 要生成树结构的数组
  • id 自定义属性名
  • parent_id 父级自定义属性名

示例

const comments = [
    { id: 1, parent_id: null },
    { id: 2, parent_id: 1 },
    { id: 3, parent_id: 1 },
    { id: 4, parent_id: 2 },
    { id: 5, parent_id: 4 },
]

treeData(comments)

// => [ { id: 1, parent_id: null, children: [ [Object], [Object] ] } ]

源码

/**
 * @description: 生成树结构数据
 * @param {*} arr The array
 * @return {*} array
 */
const treeData = (arr, id = null, link = 'parent_id') => arr.filter(item => item[link] === id).map(item => ({ ...item, children: treeData(arr, item.id) }));

flatArrFunc树结构数据生成数组

该函数传入一个树结构数组,返回一个数组

flatArrFunc(array)

参数

  • array 要遍历树结构的数组

示例

const list = [ { id: 1, parent_id: null, children: [ { id: 2, parent_id: 1, children: [ { id: 4, parent_id: 2, children: [ { id: 5, parent_id: 4, children: [] } ] } ] }, { id: 3, parent_id: 1, children: [] } ] } ]

flatArrFunc(list)

// => [{ id: 1, parent_id: null },{ id: 2, parent_id: 1 },{ id: 3, parent_id: 1 },{ id: 4, parent_id: 2 },{ id: 5, parent_id: 4 },]

源码

/**
 * @description: 树结构数据生成数组
 * @param {*} arr The array
 * @return {*} array
 */
const flatArrFunc = (list) => {
  let array = [];
  for (const item of list) {
    const json = { ...item };
    if (item.children) {
      delete json.children;
    }

    array.push(json);
    if (item.children && item.children.length) {
      array = [].concat(array, flatArrFunc(item.children));
    }
  }
  return array;
};

ascArr数组升序

返回升序后的新数组

sort()方法会改变原数组,默认按 unicode 码顺序排列

ascArr(array)

参数

  • array 要检查的排序数组

示例

ascArr([3, 2, 3, 4, 1])
// => [ 1, 2, 3, 3, 4 ]

源码

/**
 * @description: 数组升序
 * @param {*} arr The array
 * @return {*} array
 */
// 通过ES6 ...展开运算符浅拷贝一份新数组
const ascArr = arr => [...arr].sort((a, b) => a - b);

descArr数组降序

返回降序后的新数组

descArr(array)

参数

  • array 要检查的排序数组

示例

descArr([3, 2, 3, 4, 1])
// => [ 1, 2, 3, 3, 4 ]

源码

/**
 * @description: 数组降序
 * @param {*} arr The array
 * @return {*} array
 */
const descArr = arr => [...arr].sort((a, b) => b - a);

shuffle随机排序

创建一个随机的数组,使用Fisher-Yates算法随机排序数组的元素

shuffle(array)

参数

  • array 要随机的数组

示例

shuffle([2, 3, 1])
// => [3, 1, 2]

源码

/**
 * @description: 随机排序
 * @param {*} arr The array
 * @return {*} array
 */
const shuffle = ([...arr]) => {
    let m = arr.length;
    while (m) {
        const i = Math.floor(Math.random() * m--);
        [arr[m], arr[i]] = [arr[i], arr[m]];
    };
    return arr;
}

takeArray截取数组开始指定的元素

从 array 数组的最开始一个元素开始提取 n 个元素

takeArray(array, n)

参数

  • array要检索的数组。
  • n=要提取的元素n个数。

示例

takeArray([2, 3, 1], 2)
// => [2, 3]

源码

/**
 * @description:  截取数组开始指定的元素
 * @param {*} arr The array
 * @return {*} array
 */
const takeArray = (arr, n = 1) => arr.slice(0, n);

takeLastArray截取数组最后指定的元素

从 array 数组的最后一个元素开始提取 n 个元素

takeLastArray(array, n)

参数

  • array要检索的数组。
  • n=要提取的元素n个数。

示例

takeArray([2, 3, 1], 2)
// => [3, 1]

源码

/**
 * @description: 截取数组最后指定的元素
 * @param {*} arr The array
 * @return {*} array
 */
const takeLastArray = (arr, n = 1) => arr.slice(0, -n);

cloneArray克隆数组

浅拷贝一份数组副本

cloneArray(array)

参数

  • array要复制的数组

示例

cloneArray([1, 24])
// => [1, 24]

源码

/**
 * @description: 克隆数组
 * @param {*} arr The array
 * @return {*} array
 */
// ES6 ...
const cloneArray = arr => [...arr];

// ES6 Array.from
const cloneArray = arr => Array.from(arr);

// concat()
const cloneArray = arr => [].concat(arr);

// map()
const cloneArray = arr => arr.map(x => x);

maxArray数组中最大值

过滤原数组中所有的非假值元素,返回数组中的最大值

maxArray(array)

参数

  • array待处理的数组

示例

maxArray([0, -1, -2, -3, false])
// => 0

源码

/**
 * @description: 最大值
 * @param {*} arr The array
 * @return {*} array
 */
const maxArray = arr => Math.max(...arr.filter(v => Boolean(v) || v === 0));

minArray数组中最小值

过滤原数组中所有的非假值元素,返回数组中的最小值

minArray(array)

参数

  • array待处理的数组

示例

minArray([0, -1, -2, -3, false])
// => -3

源码

/**
 * @description: 最小值
 * @param {*} arr The array
 * @return {*} array
 */
const minArray = arr => Math.min(...arr.filter(v => Boolean(v) || v === 0));

validArray去除数组中的无效值

创建一个新数组,包含原数组中所有的非假值元素。例如false, null,0, "", undefined, 和 NaN 都是被认为是“假值”。

validArray(array)

参数

  • array待处理的数组

示例

minArray([0, 1, false, 2, '', 3])
// => [1, 2, 3]

源码

/**
 * @description: 去除数组中的无效值
 * @param {*} arr The array
 * @return {*} array
 */
const validArray = arr => arr.filter(Boolean);

二、对象

cloneObject克隆对象

浅拷贝一份对象副本

cloneObject(object)

参数

  • object要复制的对象

示例

const a = { x: 1, y: 1 }
const b = cloneObject(a)
// => a !== b

源码

/**
 * @description: 克隆对象
 * @param {*} object
 * @return {*}
 */
// ES6 ...
const cloneObject = (obj, temp = {}) => (temp = { ...obj });

// Object.assign()
const cloneObject = obj => Object.assign({}, obj);

三、函数

debounce函数防抖

在事件被触发 n 秒后再执行回调,如果在这 n 秒内又被触发,则重新计时。

debounce(fn, wait)

参数

  • fn 要防抖动的函数
  • wait=500需要延迟的毫秒数

示例

debounce(()=> { console.log('debounce') }, 1000)
// => 1秒后打印'debounce'

源码

/** *
 * 防抖
 * @parmas fn 回调函数
 * @parmas time 规定时间
 */
const debounce = (() => {
    let timer = {};
    return function (func, wait = 500) {
        let context = this; // 注意 this 指向
        let args = arguments; // arguments中存着e
        let name = arguments[0].name || 'arrow'; // 箭头函数
        if (timer[name]) clearTimeout(timer[name]);
        timer[name] = setTimeout(() => {
            func.apply(this, args);
        }, wait);
    };
})()

throttle函数节流

规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。

throttle(fn, wait)

参数

  • fn 要节流的函数
  • wait=500需要延迟的毫秒数

示例

throttle(() => {
    console.log('throttle')
}, 1000)
// 1秒多次触发打印一次`throttle`

源码

/** *
 * 节流(规定的时间才触发)
 * @parmas fn 结束完运行的回调
 * @parmas delay 规定时间
 */
export const throttle = (() => {
    let timeout = null;
    return function (func, wait) {
        let context = this;
        let args = arguments;
        if (!timeout) {
            timeout = setTimeout(() => {
                timeout = null;
                func.apply(context, args);
            }, wait);
        };
    };
})()

throttle(fn, 300)

typeFn类型判断

判断是否是 Array Object String Number类型

typeFn.type(value)

参数

  • type 数据类型
  • value要检验的值

示例

typeFn.String('1')
typeFn.Number(1)
typeFn.Boolean(false)
typeFn.Null(null)
typeFn.Array([1, 2])
typeFn.Object({ a: 1 })
typeFn.Function(() => {})

// => true

源码

/**
 * @description: 类型判断
 * @param {*}
 * @return {*}
 */
let typeFn = {};
const curring = (fn, arr = []) => {
    let len = fn.length;
    return (...args) => {
        arr = arr.concat(args);
        if (arr.length < len) {
            return curring(fn, arr);
        };
        return fn(...arr);
    };
};

const isType = (type, content) => Object.prototype.toString.call(content) === `[object ${type}]`;
['String', 'Number', 'Boolean', 'Null', 'Array', 'Object', 'Function'].forEach(item => {
    typeFn[item] = curring(isType)(item);
});

calcFn加减乘除运算

因为 JavaScript 遵循 IEEE 754 数学标准,使用 64 位浮点数进行运算。在进行十进制运算时会导致精度丢失。

calcFn.add(value1, value2, value3)

参数

  • addsubmuldiv运算符
  • value要计算的值

示例

解决 0.1+0.2 !== 0.3 问题
//加法
calcFn.add(0.1, 0.2) // 0.3

//减法
calcFn.sub(0.1, 0.2) // 0.1

//乘法
calcFn.mul(0.2, 0.3) // 0.06

// 乘法
calcFn.div(0.1, 0.2) // 0.5

源码

/**
 * @description: 加减乘除运算
 * @param {*}
 * @return {*}
 */
  const calcFn = {
    add() {
      let arg = Array.from(arguments);
      return arg.reduce((total, num) => accAdd(total, num));
    },
    sub() {
      let arg = Array.from(arguments);
      return arg.reduce((total, num) => accAdd(total, -num));
    },
    mul() {
      let arg = Array.from(arguments);
      return arg.reduce((total, num) => accMul(total, num));
    },
    div() {
      let arg = Array.from(arguments);
      return arg.reduce((total, num) => accDiv(total, num));
    },
  };

  const accAdd = (arg1, arg2) => {
    let r1, r2, m;
    try {
      r1 = arg1.toString().split('.')[1].length;
    } catch (e) {
      r1 = 0;
    }
    try {
      r2 = arg2.toString().split('.')[1].length;
    } catch (e) {
      r2 = 0;
    }
    m = Math.pow(10, Math.max(r1, r2));
    return (arg1 * m + arg2 * m) / m;
  };

  const accMul = (arg1, arg2) => {
    let m = 0;
    let s1 = arg1.toString();
    let s2 = arg2.toString();
    try {
      m += s1.split('.')[1].length;
    } catch (e) {}
    try {
      m += s2.split('.')[1].length;
    } catch (e) {}
    return Number(s1.replace('.', '')) * Number(s2.replace('.', '')) / Math.pow(10, m);
  };

  const accDiv = (arg1, arg2) => {
    let t1 = 0;
    let t2 = 0;
    let r1; let r2;
    try {
      t1 = arg1.toString().split('.')[1].length;
    } catch (e) {}
    try {
      t2 = arg2.toString().split('.')[1].length;
    } catch (e) {}
    r1 = Number(arg1.toString().replace('.', ''));
    r2 = Number(arg2.toString().replace('.', ''));
    return (r1 / r2) * Math.pow(10, t2 - t1);
  };

四、字符串

isNil值是否是nullundefined

isNil(value)

参数

  • value 要检验的值

示例

isNil(null)
isNil(undefined)
// => true

源码

/**
 * @description: 是否是`null`或者`undefined`
 * @param {*}
 * @return {*}
 */
const isNil = val => val?.toString() === 'undefined' || val?.toString() === 'null';

padStart遮住字符串

padStart(value, n, maskChar)

参数

  • value 要遮住字符串
  • n = 4 填充的长度
  • maskChar 填充字符

示例

padStart('18659808664')
// => 1865*******

源码

/**
 * @description: 遮住字符串
 * @param {*}
 * @return {*}
 */
const padStart = (str, n = 4, maskChar = '*') => str.slice(0, n).padStart(str.length, maskChar);

thousands数字每隔三位数加分号

thousands(number)

参数

  • number 数字或者浮点数

示例

thousands(12255552323)
// => 12,255,552,323

源码

/**
 * @description: 数字每隔三位数加分号
 * @param {*} arr The array
 * @return {*} array
 */
const thousands = num => num.toString().replace(num.toString().indexOf('.') > -1 ? /(\d)(?=(\d{3})+\.)/g : /(\d)(?=(\d{3})+$)/g, '$1,');

五、数字

randomNumber指定范围的随机整数

randomNumber(min, max)

参数

  • min 指定范围最小值
  • max 指定范围最大值

示例

randomNumber(0, 10)
// => 7
// => 2

源码

/**
 * @description: 指定范围的随机整数
 * @param {*} number
 * @return {*} array
 */
const randomNumber = (min = 0, max = 10) => Math.floor(Math.random() * (max - min + 1)) + min;

average求平均值

average(value1, value2, value3)

参数

  • value 数字

示例

average(...[1, 2, 3])
average(1, 2, 3)
// => 2

源码

/**
 * @description: 求平均值
 * @param {*} arr The array or number
 * @return {*} number
 */
const average = (...nums) => nums.reduce((acc, val) => acc + val, 0) / nums.length;

averageBy求数组对象内某对象的平均值

averageBy(array, fn)

参数

  • array 要迭代的数组
  • fn 迭代函数

示例

averageBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], o => o.n)
averageBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], 'n')
// => 5

源码

/**
 * @description: 检查数组对象各项相等
 * @param {*} arr The array
 * @return {*} array
 */
const averageBy = (arr, fn) => arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0) / arr.length;

aboutEqual两个值是否约等于

传入两个数字是否大致相等,误差在可接受范围内

aboutEqual(n1, n2, epsilon)

参数

  • n1 n2 要比较的数字
  • epsilon 误差可接受范围内

示例

aboutEqual(25, 2, 0.06)
// => false

源码

/**
 * @description: 两个值是否约等于
 * @param {*} arr The array
 * @return {*} array
 */
const aboutEqual = (n1, n2, epsilon = 0.001) => Math.abs(n1 - n2) < epsilon;

getLineSize计算两点之间的距离

勾股定理计算两点之间的距离

getLineSize = (x1, y1, x2, y2)

参数

  • x1 y1 x2 y2坐标点

示例

getLineSize(0, 0, 3, 4)
// => 5

源码

/**
 * @description: 计算两点之间的距离
 * @param {*} `x1 y1 x2 y2`坐标点
 * @return {*} number
 */
const getLineSize = (x1, y1, x2, y2) => Math.hypot(x2 - x1, y2 - y1);

sum数组中值总和

sum(value1, value2, value3)

参数

  • value1 value2 value3要迭代的数字

示例

sum(1, 2, 3, 4)
sum(...[1, 2, 3, 4])
// => 10

源码

/**
 * @description: 数组求和
 * @param {*} arr The array or number
 * @return {*} number
 */
const sum = (...arr) => [...arr].reduce((acc, val) => acc + val, 0);

六、浏览器

copyTextH5复制文本

copyText(content, callback)

参数

  • content要复制文字
  • callback 回调用户提示

示例

copyText(content, text => {
    this.$toast(text)
})

源码

const copyText = (content, callback) => {
    if (!document.queryCommandSupported('copy')) {
        // 为了兼容有些浏览器 queryCommandSupported 的判断
        console.log('浏览器不支持');
        return;
    };
    let textarea = document.createElement('textarea');
    textarea.value = content;
    textarea.readOnly = 'readOnly';
    document.body.appendChild(textarea);
    textarea.select(); // 选择对象
    textarea.setSelectionRange(0, content.length); // 核心
    let result = document.execCommand('copy'); // 执行浏览器复制命令
    callback && callback(result ? '复制成功~~' : '复制失败~~');
    textarea.remove();
}

getCurrentURL获取当前的 URL 地址

该函数返回当前页面的 URL 地址。

示例

getCurrentURL()
// =>

源码

const getCurrentURL = () => window.location.href;

scrollToTop返回顶部

平滑地滚动到当前页面的顶部。

示例

scrollToTop()
// => 当前页面的顶部

源码

const scrollToTop = () => {
    const c = document.documentElement.scrollTop || document.body.scrollTop;
    if (c > 0) {
        window.requestAnimationFrame(scrollToTop);
        window.scrollTo(0, c - c / 8);
    };
}

smoothScroll平滑滚动页面

平滑滚动到浏览器窗口的可见区域

示例

smoothScroll('#fooBar');
// => 平滑滚动到ID为fooBar的元素
smoothScroll ('.fooBar' );
// => 使用fooBar类平滑滚动到第一个元素

源码

const smoothScroll = element => document.querySelector(element).scrollIntoView({ behavior: 'smooth' });

5.isCurrentPage是否是当前页面

浏览器的选项卡是否是用户在浏览

示例

isCurrentPage()
// => true

源码

isCurrentPage = () => !document.hidden;

7.环境

1.isBrowser是否是浏览器

返回当前运行时环境是否为浏览器

示例

isBrowser()
// => true (browser)
// => false (Node)

源码

const isBrowser = () => ![typeof window, typeof document].includes('undefined');

2.isWechatBrowser判断微信浏览器还是普通h5

示例

isWechatBrowser()
// => true

源码

const isWechatBrowser = (() => {
    let ua = navigator.userAgent.toLowerCase();
    return /micromessenger/.test(ua);
})()

3.isMobile判断是否是移动端

示例

isMobile()
// => true

源码

const isMobile = () => /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jay·Yuen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值