JavaScript常用内容汇总

本文详细介绍CLI命令和npm的基本概念及应用场景,包括npm的安装、使用、依赖管理,以及如何利用CLI命令进行Babel安装、Express应用生成、Webpack使用和Vue项目创建,帮助开发者高效管理项目依赖。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、String&Number处理

1.indexOf()‌

返回子串首次出现的位置索引(区分大小写),未找到返回-1
'hello'.indexOf('l'); // 2

2. includes()‌

判断是否包含子串(ES6新增,返回布尔值)

'abc'.includes('b'); // true

3. slice(start, end)‌

截取指定区间(支持负数索引):

'javascript'.slice(0,4); // 'java'

4. split(separator)‌

按分隔符拆分为数组:

'a,b,c'.split(','); // ['a','b','c']

5. substring(start, end)‌

类似slice但不支持负数,自动交换参数

'substring'.substring(2,5); // 'bst'

6. toUpperCase()/toLowerCase()‌

全字母大小写转换:

'Hello'.toLowerCase(); // 'hello'

7. trim()‌

去除首尾空格(ES5+):

'  text  '.trim(); // 'text'

8. match(regexp)‌

正则匹配返回结果数组:

'2023-07-15'.match(/\d+/g); // ['2023','07','15']

9. replace(search, replacement)

替换子串(支持正则)

'foo bar'.replace('bar','baz'); // 'foo baz'

10. charAt(index)‌

获取指定位置字符

'abc'.charAt(1); // 'b'

11. repeat(count)‌

重复字符串(ES6)

'na'.repeat(2); // 'nana'

12. startsWith()/endsWith()‌

检测开头/结尾(ES6)

'file.txt'.endsWith('.txt'); // true

13. ‌codePointAt()‌

获取字符的Unicode码点(支持emoji)

'😊'.codePointAt(0); // 128522

14. normalize()‌

标准化Unicode字符(如去除变音符号)

'\u0041\u030A'.normalize(); // 'Å'

注意事项

  • 以上所有方法均‌不改变原字符串‌(字符串不可变)
  • 涉及正则的方法如match()、replace()可配合/g标志全局匹配
  • 优先使用ES6+方法(如includes()替代indexOf() !== -1)

15. 比较时间

const time1 = "2018-03-24 07:00:00";
const time2 = "2018-03-24 07:00:01";
time1 < time2;// true

16. 格式化money

const ThousandNum = num => num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")
ThousandNum(1000000);//'1,000,000'

17. 生成随机ID(可以加入当前时间的毫秒数)

const RandomId = len => Math.random().toString(36).substr(3, len);
const id = RandomId(10);//7f0w91zid

18. 生成随机HEX颜色值

const RandomColor = () => "#" + Math.floor(Math.random() * 0xffffff).toString(
const color = RandomColor();//#5003992

19. URLSearchParams API(现代浏览器推荐)

// 获取单个参数
const params = new URLSearchParams(window.location.search);
const value = params.get('参数名'); // 返回指定参数值或null:ml-citation{ref="2,5" data="citationList"}
// 获取所有参数(转换为对象)
const allParams = Object.fromEntries(params.entries());:ml-citation{ref="6,10" data="citationList"}

20. 生成星级

const StartScore = rate => "★★★★★☆☆☆☆☆".slice(5 - rate, 10 - rate);
const start = StartScore(3);//'★★★☆☆'

21. Number()‌

将字符串/布尔值等转换为数字:

Number("123") // 123
Number(true)  // 1

22. parseInt()/parseFloat()‌

解析字符串为整数/浮点数:

parseInt("10.5px") // 10
parseFloat("3.14") // 3.14

23. toFixed(digits)‌

保留指定位数小数(四舍五入):

3.1415.toFixed(2) // "3.14"

24. 取整方法

Math.ceil(3.1)   // 4(向上取整)
Math.floor(3.9)  // 3(向下取整)
Math.round(3.5)  // 4(四舍五入)
const num1 = ~~ 1.19;	//1
const num2 = 2.29 | 0;	//2
const num3 = 3.09 >> 0;	//3

25. 极值与随机数

Math.max(1, 3, 2) // 3
Math.random()     // [0,1)随机数

26. Number.isNaN()‌

严格检测NaN(比全局isNaN更安全):

Number.isNaN("NaN") // false

27. Number.isInteger()‌

检测是否为整数:

Number.isInteger(5.0) // true

28. ‌浮点数运算修正

使用库或放大为整数运算

function add(a, b) {
  const multiplier = 10 ** Math.max(
    a.toString().split('.')[1]?.length || 0,
    b.toString().split('.')[1]?.length || 0
  );
  return (a * multiplier + b * multiplier) / multiplier;
}

29. toLocaleString()‌

本地化千分位格式化:

1234567.89.toLocaleString() // "1,234,567.89"

注意事项

  • 浮点数计算建议使用 toFixed() 显示但避免用于计算
  • 大整数需用 BigInt 类型处理(如 9007199254740992n)
  • 货币计算推荐使用 decimal.js 等专业库

30. 零填充

const FillZero = (num, len) => num.toString().padStart(len, "0");
const num = FillZero(1234, 7);
console.log(num)  //0001234

31. 转number类型

const num1 = +null;//0
const num2 = +"";//0
const num3 = +false;//0
const num4 = +"169";//169
const timestamp = +new Date("2018-03-24");//1521849600000
//注意:仅对以上有效。

32. 精确小数

const RoundNum = (num, decimal) => Math.round(num * 10 ** decimal) / 10 ** decimal;
const num = RoundNum(1.2345, 2);// num => 1.23

33. 取最大值最小值

const arr = [5, 2, 9, 1, 7];
const max = Math.max(...arr); // 9
const min = Math.min(...arr); // 1

34. 生成范围随机数

function getRandomInt(min, max) {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min + 1)) + min;
}
const num = getRandomInt(min, max)//7

二、布尔值

1. 双重取反(!!)强制转换

使用!!value可将任意值转为布尔类型

console.log(!!"hello"); // true
console.log(!!0);       // false

原理:
第一次!将值转为布尔并取反。
第二次!还原为真实布尔值。

2. 六种假值(Falsy Values)

只有以下六种值会转为false

false, 0, "", null, undefined, NaN  // 其他值均为 true

3. 短路运算

// 条件执行
isReady && startProcess();  // 仅当 isReady=true 时执行
// 默认值设置
const name = inputName || "匿名用户"; 

4. 布尔值比较陷阱

避免直接比较布尔对象,优先使用字面量true/false,强制类型意识、避免隐式转换、代码语义透明化‌。

const boolObj = new Boolean(false);
console.log(boolObj == false);  // true (值相等)
console.log(boolObj === false); // false (类型不同) 

5. ‌字符串检测

"hello.js".endsWith(".js");  // true 
"Title:".startsWith("Title");  // true 

6. ‌数组包含检测

[1, 2, 3].includes(2); // true

7. 条件语句优化

// 优于 if(value !== null && value !== undefined)
if (value) { ... } 

8. 类型安全验证

function validate(input) {
  return typeof input === "boolean" ? input : false;
}

9. 确定数据类型

可确定的类型:undefined、null、string、number、boolean、array、object、symbol、date、regexp、function、asyncfunction、arguments、set、map、weakset、weakmap。

function DataType(tgt, type) {
    const dataType = Object.prototype.toString.call(tgt).replace(/\[object (\w+)\]/, "$1").toLowerCase();
    return type ? dataType === type : dataType;
}
DataType("test"); // "string"
DataType(20220314); // "number"
DataType(true); // "boolean"
DataType([], "array"); // true
DataType({}, "array"); // false

10. 检查是否为数组且是否为空

const arr = [];
const flag = Array.isArray(arr) && !arr.length;// flag => true

11.满足条件时执行

const flagA = true; 
const flagB = false;
(flagA || flagB) && Func(); 
(flagA || !flagB) && Func(); 
flagA && flagB && Func(); 
flagA && !flagB && Func();
//非假执行
const flag = false; // undefined、null、""、0、false、NaN
!flag && Func();
//数组不为空时执行
const arr = [0, 1, 2];
arr.length && Func();
//对象不为空时执行
const obj = { a: 0, b: 1, c: 2 };
Object.keys(obj).length && Func();

三、数组操作

1. 克隆数组

//浅拷贝方法4种(仅复制第一层)
const newArr = [...originalArr];//‌扩展运算符
const newArr = Array.from(originalArr);//Array.from()
const newArr = originalArr.slice();//slice()
const newArr = [].concat(originalArr);//concat()
//深拷贝方法两种(嵌套结构完全复制)
const newArr = JSON.parse(JSON.stringify(originalArr));//JSON 序列化‌(限制:无法处理函数/Symbol等特殊类型)
//递归深拷贝
function deepClone(arr) {
  return arr.map(item => Array.isArray(item) ? deepClone(item) : item);
}

2. 合并数组

const arr1 = [0, 1, 2];
const arr2 = [3, 4, 5];
const arr = [...arr1, ...arr2];//[0, 1, 2, 3, 4, 5]

3. 数组去重

const arr = [...new Set([0, 1, 1, null, null])];// [0, 1, null]

4. 混淆数组

const arr = [0, 1, 2, 3, 4, 5].slice().sort(() => Math.random() - .5);//[1, 5, 3, 2, 4, 0]

5. 清空数组

const arr = [0, 1, 2];
arr.length = 0;//[]

6. 截断数组

const arr = [0, 1, 2];
arr.length = 2;// [0, 1]

7. 交换数值

let a = 0;
let b = 1;
[a, b] = [b, a];//a b => 1 0

8. 过滤空值

空值:undefined,null,””,0,false,NaN

const arr = [undefined, null, "", 0, false, NaN, 1, 2].filter(Boolean);//[1,2]

9. 数组插入元素

//数组开头插入元素
let arr = [1, 2];
arr.unshift(0);
arr = [0].concat(arr);
arr = [0, ...arr];
//数组尾部插入元素
let arr = [0, 1]; 
arr.push(2);
arr.concat(2);
arr[arr.length] = 2;
arr = [...arr, 2];
//提示:高频操作建议使用 splice,比如websocket。需要保持原数组不变时优先选择扩展运算符方案。

10. 数组扁平化处理

//直接展开指定深度的嵌套数组(默认深度为1)
[1, [2, [3]]].flat(2); // [1, 2, 3]
//展开任意深度的嵌套数组
[1, [2, [3, [4]]]].flat(Infinity); // [1, 2, 3, 4]
//对象数组处理,支持对象属性的递归展开
function flattenObject(arr, key) {
  return arr.flatMap(item => 
    item[key] ? [item, ...flattenObject(item[key], key)] : [item]
  );
}
//利用 reduce 进行迭代展开
const flatten = arr => 
  arr.reduce((a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []);
//结合 some 和扩展运算符逐层展开
function flatten(arr) {
  while (arr.some(Array.isArray)) {
    arr = [].concat(...arr);
  }
  return arr;
}

11. 数组解构

//解构多层嵌套数组
const [color1, [color2, color2]] = ['red', ['green', 'blue']]; 
// color1='red', color2='green', color3='blue'
//解构数组成员别名
const arr = [0, 1, 2];
const { 0: a, 1: b, 2: c } = arr;//a b c => 0 1 2
//使用空逗号跳过不需要的元素
const [first, , third] = ['a', 'b', 'c']; // first='a', third='c'
//用 ... 捕获剩余元素:
const [head, ...tail] = [1, 2, 3]; // head=1, tail=[2,3]
// 解构不存在的数组元素时使用默认值
const colors = ['red'];
const [firstColor, secondColor = 'green'] = colors;
console.log(secondColor); // 'green'(因为colors[1]未定义)
//自定义迭代器实现类数组解构
const obj = { 
  *:ml-search[Symbol.iterator] { 
    yield 1; yield 2 
  } 
};
const [a, b] = obj; // 成功解构

12. 生成固定长度数组

//生成并填充固定长度的数组
const arr1 = Array(5).fill(0); // [0, 0, 0, 0, 0]
//生成指定长度的数组
const arr2 = [...new Array(3).keys()];//[0, 1, 2]
const arr3 = Array.from({length: 3}, (_, i) => i + 1); // [1, 2, 3]
const arr4 = [...Array(4)].map((_, i) => i * 2); // [0, 2, 4, 6]
const randomArr = Array(5).fill().map(() => Math.random());//[0.8482335137420847, 0.14620341731276887, 0.13255749533610994, 0.09141648742263153, 0.5173177360096568]
//生成二维矩阵
const matrix = Array(3).fill().map(() => Array(3).fill(0));//[[0, 0, 0],[0, 0, 0],[0, 0, 0]]

13. 随机选取数组元素

const arr = [1, 2, 3, 4, 5];
const randomItem = arr[Math.floor(Math.random() * arr.length)];
//封装为函数
function getRandomElement(array) {
  return array[Math.floor(Math.random() * array.length)];
}

14. 数组分组

//需要自定义分组逻辑时,通过累加器构建分组对象。
const groupBy = (arr, key) => 
  arr.reduce((acc, obj) => {
    const groupKey = obj[key];
    (acc[groupKey] || (acc[groupKey] = [])).push(obj);
    return acc;
  }, {});
//支持非字符串键值,使用 Map 存储分组结果
const map = new Map();
arr.forEach(item => {
  const key = item.department;
  if (!map.has(key)) map.set(key, []);
  map.get(key).push(item);
});
//Object.groupBy‌
const result = Object.groupBy(users, ({age}) => age);
//Map.groupBy‌
const result = Map.groupBy(users, ({gender}) => gender);

四、对象处理

1. 对象常用方法

分类方法名描述示例
属性操作Object.keys(obj)返回对象自身可枚举属性的键名数组Object.keys({a:1,b:2})['a','b']
Object.values(obj)返回对象自身可枚举属性的值数组Object.values({a:1,b:2})[1,2]
Object.entries(obj)返回对象自身可枚举属性的键值对数组Object.entries({a:1})[['a',1]]
obj.hasOwnProperty(key)检查对象是否包含特定自身属性(不包括原型链){a:1}.hasOwnProperty('a')true
Object.hasOwn(obj,key)更安全的属性检查方法(ES2022)Object.hasOwn({a:1},'a')true
对象操作Object.assign(target,...sources)合并多个对象(浅拷贝)Object.assign({a:1},{b:2}){a:1,b:2}
Object.defineProperty(obj,prop,descriptor)定义/修改对象属性特性Object.defineProperty(obj,'x',{value:1,writable:false})
Object.freeze(obj)冻结对象,使其不可修改Object.freeze(obj)后修改obj会静默失败或报错
Object.seal(obj)密封对象,防止添加/删除属性Object.seal(obj)后不能添加/删除属性
原型相关Object.create(proto)使用指定原型创建新对象const child = Object.create(parent)
Object.getPrototypeOf(obj)获取对象的原型Object.getPrototypeOf(array)Array.prototype
Object.setPrototypeOf(obj,proto)设置对象的原型(性能敏感,慎用)Object.setPrototypeOf(obj,newProto)
比较与转换Object.is(val1,val2)严格比较两个值是否相同(比===更准确)Object.is(NaN,NaN)true
JSON.stringify(obj)将对象转换为JSON字符串JSON.stringify({x:1})'{"x":1}'
JSON.parse(jsonStr)将JSON字符串解析为对象JSON.parse('{"a":1}'){a:1}
ES6+新增Object.fromEntries(iterable)将键值对数组转换为对象Object.fromEntries([['a',1]]){a:1}
展开运算符 ...对象浅拷贝/合并的现代语法const copy = {...obj}
const merged = {...obj1,...obj2}
可选链 ?.安全访问嵌套属性(ES2020)obj?.a?.b 当a不存在时返回undefined而不报错
空值合并 ??仅在null/undefined时使用默认值(ES2020)const val = obj.a ?? 10

2. 合并对象

//扩展运算符(ES6+推荐)【高性能浅拷贝】
const merged = {...obj1, ...obj2}; 
// 同名属性后者覆盖前者

//Object.assign()(ES5+)【中性能浅拷贝】
const merged = Object.assign({}, obj1, obj2);
// 第一个参数是目标对象(会修改它)

//手动深拷贝合并【低性能深拷贝】
function deepMerge(target, source) {
  for (let key in source) {
    if (source[key] instanceof Object) {
      target[key] = deepMerge(target[key] || {}, source[key]);
    } else {
      target[key] = source[key];
    }
  }
  return target;
}
//Lodash库的_.merge()【中性能深拷贝】
const merged = _.merge({}, obj1, obj2); 
// 自动处理嵌套对象合并

//JSON序列化(简易深拷贝)【最低性能深拷贝】
const merged = JSON.parse(JSON.stringify({
  ...obj1,
  ...obj2
}));

3. 删除对象无用属性

//使用对象解构,创建新对象删除
const obj = { a: 1, b: 2, c: 3, d: 4 };
// 删除单个属性
const { b, ...rest } = obj;
console.log(rest); // { a: 1, c: 3, d: 4 }
// 删除多个属性
const { a, d, ...newObj } = obj;
console.log(newObj); // { b: 2, c: 3 }

//使用 delete 操作符直接删除
const obj = { a: 1, b: 2, c: 3 };
// 删除单个属性
delete obj.b;
console.log(obj); // { a: 1, c: 3 }
// 批量删除属性
['a', 'c'].forEach(prop => delete obj[prop]);
console.log(obj); // {}

//使用 Lodash 库的 omit 方法
// 需要先安装 lodash
import _ from 'lodash';

const obj = { a: 1, b: 2, c: 3 };
const cleaned = _.omit(obj, ['a', 'c']);
console.log(cleaned); // { b: 2 }

4. 对象解构

// 基本解构
const person = {
  name: 'Alice',
  age: 25,
  profession: 'Developer'
};
const { name, age } = person;
console.log(name); // 'Alice'
console.log(age);  // 25

//嵌套解构
const user = {
  id: 1,
  name: 'John',
  address: {
    street: '123 Main St',
    city: 'New York',
    country: 'USA'
  }
};

// 解构嵌套的address对象
const { address: { city, country } } = user;
console.log(city);    // 'New York'
console.log(country); // 'USA'

//属性默认值
const { name, age, country = 'USA' } = person;
console.log(country); // 'USA' (当person.country不存在时)

//展开符
const { name, ...rest } = person;
console.log(rest); // { age: 25, profession: 'Developer' }

五、函数技巧

1. 箭头函数简化写法

// 传统函数
function add(a, b) {
  return a + b;
}
// 箭头函数简化
const add = (a, b) => a + b;
// 单参数可省略括号
const square = x => x * x;

2. 默认参数值

function greet(name = 'Guest') {
  console.log(`Hello, ${name}!`);
}
greet(); // Hello, Guest!
greet('Alice'); // Hello, Alice!

3. 剩余参数(Rest Parameters)

function sum(...numbers) {
  return numbers.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3)); // 6

4. 解构参数

function printUser({name, age, city = 'Unknown'}) {
  console.log(`${name}, ${age} years old from ${city}`);
}
printUser({name: 'Bob', age: 30}); // Bob, 30 years old from Unknown

5. 高阶函数

// 函数作为参数
const numbers = [1, 2, 3];
const doubled = numbers.map(num => num * 2); // [2, 4, 6]

// 函数返回函数
const multiplier = factor => number => number * factor;
const double = multiplier(2);
console.log(double(5)); // 10

6. 立即调用函数表达式(IIFE)

(function() {
  console.log('This runs immediately');
})();
// 带参数的IIFE
(function(name) {
  console.log(`Hello, ${name}!`);
})('Alice');

7. 闭包应用

function createCounter() {
  let count = 0;
  return {
    increment: () => ++count,
    getCount: () => count
  };
}
const counter = createCounter();
counter.increment();
console.log(counter.getCount()); // 1

8. this绑定控制

const person = {
  name: 'Alice',
  greet: function() {
    console.log(`Hello, ${this.name}!`);
  }
};

// 使用bind固定this
const greet = person.greet.bind(person);
setTimeout(greet, 100); // Hello, Alice!

// 箭头函数继承this
const person2 = {
  name: 'Bob',
  greet: function() {
    setTimeout(() => {
      console.log(`Hello, ${this.name}!`);
    }, 100);
  }
};
person2.greet(); // Hello, Bob!

9. 异步函数处理

// Promise链式调用
fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error(error));
// async/await简化
async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error(error);
  }
}

10. 函数缓存(Memoization)

function memoize(fn) {
  const cache = new Map();
  return (...args) => {
    const key = JSON.stringify(args);
    if (cache.has(key)) return cache.get(key);
    const result = fn(...args);
    cache.set(key, result);
    return result;
  };
}
// 使用示例
const expensiveCalc = n => {
  console.log('Calculating...');
  return n * 2;
};
const memoizedCalc = memoize(expensiveCalc);

console.log(memoizedCalc(5)); // Calculating... 10
console.log(memoizedCalc(5)); // 10 (从缓存读取)

11. 函数节流与防抖

// 节流
function throttle(fn, limit) {
  let inThrottle;
  return function(...args) {
    if (!inThrottle) {
      fn.apply(this, args);
      inThrottle = true;
      setTimeout(() => inThrottle = false, limit);
    }
  };
}
// 防抖
function debounce(fn, delay) {
  let timer;
  return function(...args) {
    clearTimeout(timer);
    timer = setTimeout(() => fn.apply(this, args), delay);
  };
}

12. 函数柯里化

函数柯里化(Currying)是一种将多参数函数转换为一系列单参数函数的技术。柯里化后的函数会逐步接收参数,直到接收到所有参数后才执行原函数。
基本概念

// 普通函数
function add(a, b, c) {
  return a + b + c;
}

// 柯里化后的函数
function curriedAdd(a) {
  return function(b) {
    return function(c) {
      return a + b + c;
    };
  };
}

// 调用方式对比
add(1, 2, 3);      // 6
curriedAdd(1)(2)(3); // 6

JavaScript 中柯里化的使用频率

柯里化在 JavaScript 中的使用情况:

  1. 使用频率中等

    • 函数式编程库(如 Lodash、Ramda)中常见
    • React 高阶组件等特定场景有应用
    • 日常业务代码中使用相对较少
  2. 适用场景

    • 需要部分应用参数的情况
    • 需要延迟执行的场景
    • 函数组合(function composition)时
    • 需要创建专用函数

柯里化的优势

  1. 参数复用
// 创建专用函数
const add5 = curriedAdd(5);
const add5And10 = add5(10);
add5And10(3); // 18
  1. 延迟执行
// 直到收到所有参数才执行
const log = level => message => `[${level}] ${message}`;
const errorLog = log('ERROR');
errorLog('Something went wrong'); // "[ERROR] Something went wrong"
  1. 函数组合更灵活
const compose = (...fns) => x => fns.reduceRight((v, f) => f(v), x);
const double = x => x * 2;
const increment = x => x + 1;

// 柯里化使组合更清晰
const transform = compose(double, increment);
transform(5); // 12 (先increment再double)

实际应用示例

  1. 事件处理
// 普通处理
button.addEventListener('click', (e) => handleClick(id, e));

// 柯里化处理
const handleClick = id => e => { /*...*/ };
button.addEventListener('click', handleClick(id));
  1. API请求
// 创建专用请求函数
const apiRequest = baseUrl => endpoint => params => 
  fetch(`${baseUrl}/${endpoint}`, { ...params });

const myApi = apiRequest('https://api.example.com');
const getUser = myApi('users');
getUser({ id: 123 });
  1. React高阶组件
// 柯里化高阶组件
const withStyles = styles => Component => props => (
  <Component {...props} styles={styles} />
);

// 使用
const StyledButton = withStyles(buttonStyles)(Button);

自动柯里化实现

function curry(fn) {
  return function curried(...args) {
    // 参数足够时执行原函数
    if (args.length >= fn.length) {
      return fn.apply(this, args);
    } 
    // 参数不足时返回新函数继续收集参数
    else {
      return function(...moreArgs) {
        return curried.apply(this, args.concat(moreArgs));
      };
    }
  };
}

// 使用示例
const curriedAdd = curry((a, b, c) => a + b + c);
curriedAdd(1)(2)(3); // 6
curriedAdd(1, 2)(3); // 6
curriedAdd(1, 2, 3); // 6

何时使用柯里化

推荐使用

  • 需要创建多个相似函数(参数部分相同)
  • 函数组合场景
  • 需要明确参数传递顺序时

不推荐使用

  • 性能敏感场景(柯里化有额外函数调用开销)
  • 参数数量不固定的函数
  • 团队不熟悉函数式编程时

柯里化是一种强大的技术,但应该根据实际需求谨慎使用,避免过度工程化。

六、DOM操作

1. 元素选择技巧

基础选择方法

// 通过ID获取
const element = document.getElementById('myId');

// 通过类名获取(返回HTMLCollection)
const elements = document.getElementsByClassName('myClass');

// 通过标签名获取(返回HTMLCollection)
const divs = document.getElementsByTagName('div');

// 通过CSS选择器获取(返回第一个匹配元素)
const item = document.querySelector('.item');

// 通过CSS选择器获取所有匹配元素(返回NodeList)
const items = document.querySelectorAll('.item');

现代选择技巧

// 在特定元素内查询
const container = document.getElementById('container');
const innerItems = container.querySelectorAll('.item');

// 获取表单元素
const formInputs = document.forms['myForm'].elements;

2. 元素内容操作

// 获取/设置文本内容
element.textContent = '新内容';
const text = element.textContent;

// 获取/设置HTML内容
element.innerHTML = '<strong>加粗文本</strong>';

// 获取/设置value(表单元素)
inputElement.value = '新值';

// 安全插入HTML(避免XSS)
element.insertAdjacentHTML('beforeend', '<p>安全插入</p>');

3. 元素属性操作

// 获取/设置标准属性
const href = link.getAttribute('href');
link.setAttribute('href', 'https://newurl.com');

// 获取/设置data属性
const user = element.dataset.userId;

// 切换类名
element.classList.add('active');
element.classList.remove('active');
element.classList.toggle('active');
element.classList.contains('active'); // 检查

// 直接修改样式
element.style.color = 'red';
element.style.backgroundColor = '#fff';

4. 元素创建与删除

// 创建新元素
const newDiv = document.createElement('div');

// 添加子元素
parentElement.appendChild(newDiv);

// 插入到特定位置
parentElement.insertBefore(newDiv, referenceElement);

// 克隆元素
const clonedElement = element.cloneNode(true); // 深度克隆

// 移除元素
parentElement.removeChild(element);
element.remove(); // 现代方法

5. 事件处理技巧

基本事件绑定

// 传统方式
element.onclick = function(e) { /*...*/ };

// 现代方式(可添加多个监听器)
element.addEventListener('click', function(e) {
  console.log(e.target); // 触发事件的元素
});

常用事件技巧

// 事件委托
document.getElementById('list').addEventListener('click', function(e) {
  if(e.target.classList.contains('item')) {
    // 处理.item元素的点击
  }
});

// 一次性事件
element.addEventListener('click', function handler(e) {
  // 处理逻辑
  e.currentTarget.removeEventListener('click', handler);
});

// 防抖事件
element.addEventListener('input', debounce(function(e) {
  // 输入停止后才执行
}, 300));

6. 页面结构遍历

// 获取父元素
const parent = element.parentNode;

// 获取子元素
const firstChild = element.firstElementChild;
const children = element.children; // HTMLCollection

// 获取兄弟元素
const nextSibling = element.nextElementSibling;
const prevSibling = element.previousElementSibling;

7. 表单操作技巧

// 获取表单数据
const formData = new FormData(formElement);
const username = formData.get('username');

// 监听表单提交
form.addEventListener('submit', function(e) {
  e.preventDefault(); // 阻止默认提交
  // 处理表单数据
});

// 表单验证
inputElement.addEventListener('input', function() {
  if(!inputElement.checkValidity()) {
    // 显示错误信息
  }
});

8. 性能优化技巧

// 批量DOM修改使用文档片段
const fragment = document.createDocumentFragment();
for(let i = 0; i < 100; i++) {
  const item = document.createElement('div');
  fragment.appendChild(item);
}
container.appendChild(fragment);

// 避免强制同步布局(布局抖动)
// 不好的做法:
for(let i = 0; i < items.length; i++) {
  items[i].style.width = box.offsetWidth + 'px';
}

// 好的做法:
const width = box.offsetWidth;
for(let i = 0; i < items.length; i++) {
  items[i].style.width = width + 'px';
}

9. 现代DOM API

// IntersectionObserver(检测元素可见性)
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if(entry.isIntersecting) {
      // 元素进入视口
    }
  });
});
observer.observe(element);

// MutationObserver(监听DOM变化)
const observer = new MutationObserver((mutations) => {
  mutations.forEach(mutation => {
    // 处理DOM变化
  });
});
observer.observe(element, { attributes: true, childList: true });

// 元素尺寸观察
const resizeObserver = new ResizeObserver(entries => {
  for(let entry of entries) {
    console.log('新尺寸:', entry.contentRect);
  }
});
resizeObserver.observe(element);

10. 实用代码片段

// 检查元素是否在视口中
function isInViewport(element) {
  const rect = element.getBoundingClientRect();
  return (
    rect.top >= 0 &&
    rect.left >= 0 &&
    rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
    rect.right <= (window.innerWidth || document.documentElement.clientWidth)
  );
}

// 平滑滚动到元素
function smoothScrollTo(element) {
  element.scrollIntoView({ 
    behavior: 'smooth',
    block: 'start'
  });
}

// 获取计算样式
function getStyle(element, property) {
  return window.getComputedStyle(element).getPropertyValue(property);
}

11.过滤 XSS

function FilterXss(content, allowedTags = ['b', 'i', 'em', 'strong']) {
    const temp = document.createElement("div");
    temp.textContent = content;
    let html = temp.innerHTML;
    
    // 保留白名单标签
    if (allowedTags.length) {
        const tagsRegex = new RegExp(
            `</?(?!(${allowedTags.join('|')})\\w+[^>]*>`, 
            'gi'
        );
        html = html.replace(tagsRegex, '');
    }
    
    // 移除危险属性
    html = html.replace(
        /( on\w+|href|src|style)=["'][^"']*["']/gi, 
        (match, attr) => {
            if (attr === 'href' || attr === 'src') {
                if (/javascript:/gi.test(match)) return '';
                if (attr === 'src' && !/^https?:\/\//.test(match)) return '';
            }
            return attr === 'style' ? '' : match;
        }
    );
    
    return html;
}

最佳实践建议

  1. 使用专业库:推荐使用成熟的XSS过滤库

  2. 根据输出上下文处理

    // HTML内容
    function filterHtml(content) {
        return DOMPurify.sanitize(content);
    }
    
    // HTML属性
    function filterAttr(value) {
        return String(value)
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#x27;');
    }
    
    // URL
    function filterUrl(url) {
        if (!/^https?:\/\//i.test(url)) return '#';
        return url;
    }
    
  3. 结合CSP:设置内容安全策略头提供额外保护

专业库使用示例

// 使用DOMPurify
const clean = DOMPurify.sanitize(dirtyHtml, {
    ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a'],
    ALLOWED_ATTR: ['href', 'title'],
    FORBID_ATTR: ['style', 'onclick']
});

// 使用xss库
const filtered = filterXSS(originalHtml, {
    whiteList: {
        a: ['href', 'title']
    },
    onIgnoreTagAttr: function(tag, name, value) {
        if (name === 'style') return '';
    }
});

总结:在生产环境中建议使用专业的XSS过滤库,并根据不同的输出上下文实施针对性的过滤策略。

在这里插入图片描述

npm ERR! code EPERM npm ERR! syscall rename npm ERR! path D:\A_nodejs\node_global\node_modules\cnpm\node_modules\.make-fetch-happen.DELETE\node_modules\@npmcli npm ERR! dest D:\A_nodejs\node_global\node_modules\cnpm\node_modules\make-fetch-happen\node_modules\@npmcli npm ERR! errno -4048 npm ERR! Error: EPERM: operation not permitted, rename 'D:\A_nodejs\node_global\node_modules\cnpm\node_modules\.make-fetch-happen.DELETE\node_modules\@npmcli' -> 'D:\A_nodejs\node_global\node_modules\cnpm\node_modules\make-fetch-happen\node_modules\@npmcli' npm ERR! [OperationalError: EPERM: operation not permitted, rename 'D:\A_nodejs\node_global\node_modules\cnpm\node_modules\.make-fetch-happen.DELETE\node_modules\@npmcli' -> 'D:\A_nodejs\node_global\node_modules\cnpm\node_modules\make-fetch-happen\node_modules\@npmcli'] { npm ERR! cause: [Error: EPERM: operation not permitted, rename 'D:\A_nodejs\node_global\node_modules\cnpm\node_modules\.make-fetch-happen.DELETE\node_modules\@npmcli' -> 'D:\A_nodejs\node_global\node_modules\cnpm\node_modules\make-fetch-happen\node_modules\@npmcli'] { npm ERR! errno: -4048, npm ERR! code: 'EPERM', npm ERR! syscall: 'rename', npm ERR! path: 'D:\\A_nodejs\\node_global\\node_modules\\cnpm\\node_modules\\.make-fetch-happen.DELETE\\node_modules\\@npmcli', npm ERR! dest: 'D:\\A_nodejs\\node_global\\node_modules\\cnpm\\node_modules\\make-fetch-happen\\node_modules\\@npmcli' npm ERR! }, npm ERR! errno: -4048, npm ERR! code: 'EPERM', npm ERR! syscall: 'rename', npm ERR! path: 'D:\\A_nodejs\\node_global\\node_modules\\cnpm\\node_modules\\.make-fetch-happen.DELETE\\node_modules\\@npmcli', npm ERR! dest: 'D:\\A_nodejs\\node_global\\node_modules\\cnpm\\node_modules\\make-fetch-happen\\node_modules\\@npmcli', npm ERR! parent: 'cnpm' npm ERR! } npm ERR! npm ERR! The operation was rejected by your operating system. npm ERR! It's possible that the file was already in use (by a text editor or antivirus), npm ERR! or that you l
03-28
<think>好的,我现在需要帮助用户解决在Windows上安装npm包时遇到的EPERM权限错误问题。首先,我要回顾用户提供的引用内容,看看有哪些解决方案已经被提到,然后整理出一个系统化的解决步骤。 根据引用内容,用户遇到的错误通常发生在修改npm的全局安装路径后,执行npm install时,尤其是在非管理员权限下。错误信息提到无法创建目录或重命名文件,这可能与文件夹权限不足有关。 首先,引用3提到,直接修改node_global和node_cache文件夹的权限,赋予用户完全控制权。这是一个常见的解决方法,因为安装过程中需要写入这些目录,如果权限不够就会报错。用户需要找到这两个文件夹,右键属性,调整安全设置,确保用户有完全控制权限。 然后,引用4和5都建议删除C:\Users\{账户}\下的.npmrc文件。这个文件可能包含旧的配置或缓存信息,导致权限冲突。需要注意的是,这个文件可能是隐藏的,所以用户需要显示隐藏文件才能找到并删除它。删除后重新运行npm命令可能会解决问题。 另外,引用3还提到以管理员身份运行命令提示符可以暂时解决问题,但这可能不是长久之计,因为每次都需要管理员权限。不过,这可以作为临时解决方案,同时检查文件夹权限是否正确。 可能还有其他原因,比如缓存问题。引用4提到用命令清除缓存,但用户表示直接删除文件更有效。不过,作为补充,可以建议用户尝试npm cache clean --force命令,虽然可能效果有限,但结合其他步骤可能会有帮助。 接下来,我需要将这些步骤整理成逻辑清晰的解决方案,确保用户能够逐步操作。需要强调检查文件夹权限、删除.npmrc文件、以管理员身份运行以及可能的缓存清理。同时,要提醒用户注意文件路径的正确性,尤其是隐藏文件的问题。 可能还需要考虑其他因素,例如防病毒软件或安全软件阻止了npm的操作,或者node.js安装目录本身的权限问题。但根据现有引用,主要问题集中在上述几个方面,因此优先处理这些步骤。 最后,生成相关问题,帮助用户深入理解问题,比如如何配置npm全局路径、处理其他npm错误,以及权限管理的最佳实践。这些问题有助于用户预防类似问题,并扩展他们的知识。</think>针对Windows系统下npm安装过程中出现的EPERM权限错误问题,以下是系统性解决方案: ### 分步解决方案 1. **修改全局目录权限** - 定位Node.js安装目录下的`node_global`和`node_cache`文件夹(默认路径:`D:\Program Files\nodejs`) - 右键文件夹 → 选择 **属性** → **安全** 选项卡 → 点击 **编辑** - 将当前用户的权限设置为 **完全控制**(勾选所有权限选项)[^3] 2. **删除用户目录下的.npmrc文件** - 打开路径 `C:\Users\{你的用户名}\`(例如`C:\Users\John`) - 显示隐藏文件(文件资源管理器 → 查看 → 勾选 **隐藏的项目**) - 删除 `.npmrc` 文件(此文件可能包含冲突的配置)[^4][^5] 3. **以管理员身份运行命令行** - 临时解决方法:右键点击命令提示符/PowerShell → 选择 **以管理员身份运行** - 执行安装命令如 `npm install -g 包名` 4. **清除npm缓存(补充措施)** - 在命令行中执行: ```bash npm cache clean --force ``` ### 原理说明 EPERM错误通常由以下原因引发: - **目录权限不足**:npm需要向`node_global`或`node_cache`写入文件时被系统拒绝 - **残留配置文件冲突**:旧版`.npmrc`可能包含错误路径或权限配置 - **缓存数据异常**:损坏的缓存文件导致操作中断 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值