前端性能优化:5.高性能的JavaScript代码

用户通过浏览器访问页面的过程,除了输入URL地址到所访问页面完成首屏渲染,更多的时候页面在相应与用户的交互。
高性能网站的要求不仅是执行顺畅无BUG,还希望对用户的页面操作能够更快速响应,而且在执行完任务的同时占用更少的资源。

5.1 数据存取

无论哪种计算机语言,说到底它们的作用都是对数据的存取与处理,JavaScript也不例外。若能在处理数据之前,更快速的读取到数据,那么必然会对程序执行性能产生积极的作用。本节建工数据的存取及作用域链的角度,探讨一些在JavaScript中能提升性能的方式。

5.1.1 数据存取方式
一般来说JavaScript有四种数据存取方式:

  1. 直接字面量:字面量不存储在特定位置也不需要索引,仅代表自身。包括布尔值、数字、字符串、对象、数组、函数、null、undefined及正则表达式。
  2. 变量:通过关键字const/let/var定义的数据存储单元。
  3. 数组元素:存储在数组对象内部,通过数组下标数字进行索引。
  4. 对象属性:存储在对象内部,通过对象的字符串名称进行索引。

数组元素和对象属性不仅可以是直接字面量的形式,还可以是由其他数组对象或对象属性组成的更为复杂的数据结构。从读取速度看,直接字面量与变量是非常快的,相比之下数组元素和对象属性由于需要索引,其读取速度也会因其组成结构的复杂度越高而越慢。

5.1.2 作用域和作用域链
ES6发布前JavaScript没有明确的块级作用域概念。它只有全局作用域和每个函数内的局部作用域。全局作用域就是无论此时执行的上下文是在函数内部还是函数外部的,都能访问到存在于全局作用域中的变量或对象;而定义存储在函数的局部作用域中的对象,只有在该函数内部执行上下文时才能够访问,而对函数外是不可见的。
对于能够访问到的数据,其在不同作用域中的查询也有先后顺序。这就涉及作用域链的概念。JavaScript引擎会在页面加载后创建一个全局的作用域,然后每碰到一个要执行的函数时,又会为其创建对应的作用域,最终不同的块级作用域和嵌套在内部的函数作用域,会形成一个作用域堆栈。
当前生效的作用于在堆栈的最顶端,由上往下就是当前执行上下文所能访问的作用域链。
例子:

function plus(num){
    return num +1;
}
const ret=plus(6);

函数plus的作用域链中仅有一个指向全局对象的作用域,其中包括this、函数对象plus及常量ret,而在执行到plus时,Js引擎会创建一个新的执行上下文和包含一些局部变量的活动对象。执行过程会先对num标识符进行解析,即从作用域链的最顶层依次向下查找,直至找到num标识符。

变量位于作用域链中的位置越深,被引擎访问到所需的时间就越长,所以我们应当留心对作用域链的管理。
前端性能优化:5.高性能的JavaScript代码_第1张图片

5.1.3 实战经验
1. 对局部变量的使用
如果一个非局部变量在函数中使用次数不止一次,则最好对这个局部变量进行存储。
例子:

function process(){
    const target = document.getElementById('target');
    const imgs = document.getElementById('img');
    for(let i = 0;i

函数process()中,首先通过document的两个不同的成员函数分别获取了特定的元素和元素列表,然后进行一些省略相关处理流程的操作。值得注意的是,document属于全局作用域的对象,位于作用域链最深处,在标识符解析过程中会被最后解析到。由于它在函数中使用了不止一次,所以可以考虑将其声明为一个局部变量,以提升其在作用域链中的查找顺序。
还值得注意的一点是,imgs.length执行了不止一遍。每次通过属性名或索引读取imgs的属性时,DOM都会重复执行一次对页面元素的查找,这个过程本身就会很缓慢。
改进后的代码:

function process(){
    const doc = document;
    const target = doc.getElementById('target');
    const imgs = doc.getElementById('img');
    const len = imgs.length;
    for(let i = 0;i

2. 作用域链的增长
前面讲到可以通过将频繁使用的位于较深作用域链层级中的数据,声明为局部变量来提升标识符解析与访问的速度。若能将全局变量提升到局部变量的访问高度,是否还能提升到比局部变量更高的位置呢?答案是肯定的,在当前局部变量作用域前增加新的活动变量作用域,但这种增长了作用域链的做法会造成过犹不及的效果。
比如with语句,它能将函数外层的变量提升到比当前函数局部变量还要搞的作用域链访问级别上,如下代码由于使用with的缘故,在语句中可直接访问param中的属性值,虽然方便但降低了show()函数原本局部变量的访问速度,所以应尽量少用。

const param = {
    name:'Tian',
    value:100
}
function show(){
    const content = 2;
    with(param){
        console.log('name is ${name}');
    }
}

另一个例子就是try-catch语句,catch代码块被用来处理捕获到的异常,但其中包含错误信息的error的作用域高于当前局部变量所在代码块,所以建议不要在catch语句中处理过多复杂的业务逻辑,会降低数据的访问速度。
3. 警惕闭包的使用

function mkFunc(){
    const name = 'A';
    return function showName(){
        console.log(name);
    }
}
const myFunc = mkFunc();
myFunc();

showName()函数就是一个闭包,它在mkFunc()函数执行时被创建,并能访问mkFunc()函数的局部变量name,为此便需要创建一个独立与mkFunc()函数的作用域链。
前端性能优化:5.高性能的JavaScript代码_第2张图片

一般的函数执行完成后,其中局部变量所占用的空间会被释放,但闭包的这种特性会延长父函数中局部变量的生命周期。也就意味着使用闭包可能会带来更大的内存开销及内存可能泄漏的影响。

5.2 流程控制

流程控制在业务代码中的比重是很大的,因此优化流程控制方面的代码,必然能有效地提升代码运行的速度。

5.2.1 条件判断
1. if-else和switch

通常地if-else如下:
if(value === 0){
    ......
} else if(value === 1){
    ......
} else if(value > 3 && value < 9){
    ......
}

在if-else地判断条件中,变量的取值可以是相应的离散值,也可以是不同的区间范围。
当取值全部为离散值时,可将if-else写成switch:

switch(value){
    case 0: ......; break;
    case 1:.......; break;
    case 2:......; break;
    default:......;
}

对于多个离散值的取值条件判断,switch可以清晰地表明判断条件和返回值之间的对应关系,同时也使它具有更好的代码可读性。
如果只有一两个条件的判断,通常if-else处理条件的时间会比switch更短,当判断条件多到两个以上时,switch效率更高。
2. if-else的优化
如果程序最终的执行路径时最后一个else if子语句,那么当执行到此处之前,其余所有条件判断必然都要经历一遍。耗时也会比之前所有判断条件执行耗时都久。
基于此便有了两种优化方式,第一种时开发者可以预先估计条件被匹配到的频率,按照频率的降序顺序来排列if-else语句,可以让匹配频率高的条件更快执行,从而在整体上降低程序花费在条件判断上的时间,比如

if (value === 8){
    // 匹配到8的概率最高
}else if (value === 7){
    // 匹配到7的概率仅次于8
}else if (value === 6){
    // 匹配到6的概率最低
}else {
    其他判断
}

第二种方式时利用二分法的思路,可能开发人员在编写相应的业务代码时,并不能预先估计出各种条件在多次执行时被匹配到的概率,但却能对取值区间的边界有明确的划分,那么便可以用二分取值范围来降低匹配条件的执行次数,比如

if (value < 4){
    if (value < 2){
        // 值在小于2时的情况
    }else {
        // 值在2或3之间
    }
}else {
    if (value < 6){
         // 值在4或5之间
    }else {
        //值在6到上界之间的取值  
    }
}

仅演示简单的数字区间,实际开发中需自行结合实际情况考虑。
3. 数组索引和对象属性
除了if-else和switch,利用数组的索引查询或对象的属性拆线呢也可以达到类似条件判断的目的,比如

//条件映射数组
const valueArray = [v0,v1,v2,v3,v4];
//提取对应数组索引的处理
valueArray[value];

由于数组中的每个元素既可以是对象,又可以是函数,那么便可将条件匹配的处理过程封装到数组的元素中,并用数组索引映射对应的value变量,通过匹配数组索引执行相应的处理过程。同样基于对象属性的映射方式,也能实现类似的条件查找行为,比如

//基于对象的属性映射
const valueMap = {
    'condition0': ()=>{......},
    'condition1': ()=>{......},
    'condition2': ()=>{......}
}
//提取对应对象属性的处理
valueMap[value];

基于对象属性的索引可以不局限于整数取值,它能匹配符合对象属性名命名规范的任何字符串形式,,与switch类似,其取值范围是离散值。当匹配条件的数量较小时,并不适合使用这种基于数组或对象的查找方式,因为查找数组或映射对象属性值往往比执行少量的条件判断语句要慢,只有当取值范围变得非常大时,这种查找方式的性能优势才会凸显出来。
4. 策略模式
策略模式就是定义一系列的处理流程或算法,把它们分别封装起来,使得它们可以相互替代。其目的就是将算法的使用和实现分离。
一个基于策略模式的程序通常会包含两个部分——一部分是一组策略类,其中包含一系列具体的处理算法,有点类似于包含不同处理过程的映射对象 valueMap;另一部分是环境类,它将根据上下问操作运算,决定调用策略类中的那个策略处理过程,即完成流程控制中条件匹配的部分。
假设一个具体场景:年底公司要根据员工的绩效等级发奖金,绩效考核打S的发四倍工资,打A的发三倍月工资,打B的发两倍月工资……为简化说明,仅以三种绩效考核等级为例。通常的解决方案,直接的想法是定义一个函数,接受两个参数,分别是员工的月薪和绩效考核等级,然后在其中通过if-else判断来分别计算出奖金额度:

//计算奖金的方法
function calculateBonus(salary, level){
    if(level === "S"){
        return salary*4;
    }else if(level === "A"){
        return salary*3;
    }else if(level === "B"){
        return salary*2;
    }
}

上述代码可以看出这样的实现本身没有什么问题,将所有奖金计算规则都包含在一个函数中解决。如果需要改写奖金计算规则,会发现这个函数不符合“对扩展开放,对修改封闭”的设计原则,扩展新功能的工作量不亚于推倒重做做。若重构为策略模式的写法:

//策略类
const strategies = {
    "S":(salary)=> salary*4;
    "A":(salary)=> salary*3;
    "B":(salary)=> salary*2;
}
//计算具体奖金
function calculateBonus(salary,level){
    return strategies[level](salary);
}

如此解耦了各种级别奖金计算的逻辑,如果要针对奖金发放算法进行调整,则只需修改策略类中对应的方法即可。
5. 条件判断的使用建议
· 当所要匹配的条件仅为一两个离散值时,或者容易划分不同取值范围时,使用if-else。
· 当所要匹配的条件超过一两个但少于十个离散值时,使用switch。
· 当所要匹配的条件超过十个离散值时,使用基于数组索引或对象属性的查找方式。

5.2.2 循环语句
与条件判断相比,循环语句对程序执行性能的影响更大。一个循环语句的循环执行次数直接影响程序的时间复杂度,如果代码中还存在去欸按导致循环不能及时停止,从而造成死循环,那么给用户带来的使用体验将会是非常糟糕的。
1. 三种常规循环语句
JavaScript中循环语句常见写法有三种,第一种是标准的for循环,这与大部分编程语言类似,包括初始化、循环结束条件、迭代语句及循环体四部分,第二种和第三种分别是while循环和do-while循环,二者唯一的差别就是do-while循环会先执行一遍循环体。
通常使用这三种循环语句时,基本都是对数组元素进行遍历。从索引的第一个元素开始直到数组的最后一个元素结束,每次在执行循环判断时,都需要将当前的数组索引与数组长度进行比较。由于该比较操作执行的过程中数组长度一般不会改变,且存取局部变量要比查找属性值时更省时,所以提前将要遍历的数组长度声明为局部变量,然后将该局部变量进行循环结束的条件判断,效率会更高。

//较差的循环结束判断
const array = [1,2,3,4,5];
for(let i =0;i

这在对包含较大规模DOM节点树的遍历过程中,效果会更加明显。此外还有一种更简单地提升循环语句性能的方式:将循环变量递减到0,而非递增到数组总长度。

for(let i=array.length-1;i>0;k--){
    ......
}

只有初始化时涉及到了属性值的读取,其比较的运算速度会更快。
2. for-in循环与函数迭代

//遍历object对象的所有属性
for(let prop in object){
    //确保不会遍历到object原型链上的其他对象
    if(object.hasOwnProperty(prop)){
        ......
    }
}

可以看出for-in循环能够遍历对象的属性集,特别适合处理诸如JSON对象这样的未知属性集,但对通常的循环使用场景来说,由于它遍历属性的顺序不确定,循环的结束条件也无法改变,并且因为需要从目标对象中解析出每个可枚举的属性,即要检查对象的原型和整个原型链,所以其循环速度也会比其他循环方式慢许多,若有性能要求尽量避免使用for-in循环。
对于数组的循环,JavaScript原生提供了一中forEach函数迭代的方法,此方法会遍历数组上的所有元素,并对每个元素执行一个方法,所运行的方法作为forEach的入参。
Array.forEach((value,index,arr)=>{

})

这种方式会让数组元素的迭代看起来更加直观,但在通常情况下与三种基本的循环方法相比,其性能方面仅能达到后者的1/8,如果数组长度较大或对运行速度有比较严格的要求,则函数迭代的方式不建议使用。
另外,还有ES6新加入的for-of循环,可以用它来代替for-in和forEach循环,它不仅性能比这二者更好,还支持对任何可迭代的数据结构进行遍历,但与三种常规循环语句相比其性能还是稍逊色一些。

5.2.3 递归
简单来说,递归就是函数执行体内部调用自身的行为,这种方式有时可以让复杂的算法实现变得简单,如斐波那契数列或阶乘。
使用递归也有一些潜在的问题需要注意:比如缺少或不明确递归的终止条件会很容易造成用户界面卡顿,同时由于递归是一种通过空间换时间的算法,其执行过程中会入栈保存大量的中间运算结果,对内存的开销将与递归次数成正比,由于浏览器都会限制JavaScript的调用栈大小,超出限制递归执行便会失败。
1. 使用迭代
任何递归函数都可以改写成迭代的循环形式,虽然循环会引入自身的一些性能问题,但相比于长时间执行的递归函数,其性能开销还是要小很多的。

//递归实现归并排序
function merge(left, right) {
  const result = [];
  while (left.length > 0 && right.length > 0) {
    //把最小的先取出来放到结果中
    if (left[0] < right[0]) {
      result.push(left.shift());
    } else {
      result.push(right.shift());
    }
  }
  //合并
  return result.concat(left).concat(right);
}
//递归函数
function mergeSort(array) {
  if (array.length === 1) return array;
  //计算数组中点
  const middle = Math.floor(array.length / 2);
  //分割数组
  const left = array.slice(0, middle);
  const right = array.slice(middle);
  //进行递归合并与排序
  return merge(mergeSort(left), mergeSort(right));
}

可以看出这段归并排序中,mergeSort()函数会被频繁调用,对于包含n个元素的数组来说,mergeSort()函数会被调用2n-1次,随着所处理数组元素的增多,这对浏览器的调用栈是一个严峻的考验。

//用迭代的方式改写递归函数
function mergeSort(array) {
  if (array.length === 1) return array;
  const len = array.length;
  const work = [];
  for (let i = 0; i < len; i++) {
    work.push([array[i]]);
  }
  //确保总数组长度为偶数
  if (len & 1) work.push([]);
  //迭代两两归并
  for (let lim = len; lim > 1; lim = (lim + 1) / 2) {
    for (let j = 0, k = 0; k < lim; j += 1, k += 2) {
      work[j] = merge(work[k], work[k + 1]);
      //数组长度为奇数时,补一个空数组
      if (lim & 1) work[j] = [];
    }
  }
  return work[0];
}

此处通过迭代实现的mergeSort()函数,其功能上与递归方式相同,虽然在执行时间上来看要慢一些,但它不会受到浏览器对JavaScript调用栈的限制。
2. 避免重复工作
如果在递归过程中,前一次的计算结果能被后一次计算使用,那么缓存前一次的计算结果就能有效避免许多重复工作。比如阶乘操作:

//计算某个数的阶乘
function factorial(n){
    if(n === 0){
        return 1;
    }else{
        return n*factorial(n-1);
    }
}

当我们计算多个数的阶乘(如2、3、4)时,如果分别计算这三个数的阶乘,则函数factorial()总共要被调用12次,其中国在计算4的阶乘时,会把3的阶乘重新计算一遍,计算3的阶乘时又会把2的阶乘重新计算一遍,可以看出如果在计算4的阶乘之前,将3的阶乘数缓存下来,那么在计算4的阶乘时,递归仅需要再执行一次。如此便通过缓存阶乘计算结果,避免多于计算过程,原本12次的递归调用,可以减少到5次。
如:

function memoize(func,cache){
    const cache = cache || {};
    return function(args){
        if(!cache.hasOwnProperty(args)){
            cache[args] = func(args);
        }
        return cache[args];
    }
}

该方法利用函数闭包有效避免了类似计算多次阶乘时的重复操作,确保只有当一个计算在之前从未发生过时,才产生新的计算值,这样前面的阶乘函数便可改写为:

const memorizeFactorial = memorize(factorial,{'0':1,'1':1});

这种方式也存在性能问题,比如函数闭包延长了局部变量的存活期,如果数据量过大又不能有效回收,则容易导致内存溢出。这种方案只有在程序中有相同参数多次调用时才会比较省时,所以综合而言,优化方案还需根据具体使用场景具体考虑。

5.3 字符串处理

为了搞笑处理字符串,使用正则表达式是必不可少的,但两个匹配同一文本的正则表达式并不意味着它们具有相同的执行速度。

5.3.1 字符串拼接
字符串拼接是前端开发中的常规操作,但在大规模数据的循环迭代中进行字符串拼接时,可能稍有不慎就会造成严重的性能问题。
几种常见的拼接方式:

//使用"+"运算符
const str1 = "a" + "b";
//使用"+="运算符
const str2 = "a";
str2 += "b";
//使用数组的join()方法
const str3 =["a","b"].join();
//使用字符串的concat()方法
const str4 = "a";
str4.concat("b");

当处理少量单次或少量字符串拼接时,这些方法的运行速度都很快,根据自己偏好使用即可,但随着需要迭代合并的字符串数量增加,他们之间性能的差异逐渐显现,如下是一个字符串迭代拼接的处理过程:

let len = 1000;
let str = "";
while(len--){
    str += "a" + "b";
}

但看循环内部的字符串拼接操作,其代码运行过程可分为四步:首先在内部创建一个临时的字符串变量,然后将拼接的字符串"ab"赋值给它,接着把该临时变量与str的当前值进行拼接,最后将结果赋值给str。可见由于存在临时变量的存取,其性能并不满足预期,若避免临时变量存取直接向str变量上拼接,在大部分浏览器中,都能将这一操作步骤的执行速度提升20%左右。
//不生产中间临时变量的字符串拼接
str = str + “a” + “b”;

数组对象的 join()方法和字符串对象的concat()方法比使用赋值表达式实现字符串拼接在性能上稍慢。

5.3.2 正则表达式
1. 正则表达式处理步骤
(1) 编译表达式:一个正则表达式对象可以通过RegExp构造函数创建,也可以定义成正则直接量,档期被创建出来后,浏览器会先去验证然后将它转化为一个原生待程序,用于执行匹配任务。
(2) 设置起始位置:当匹配开始时,需要先确定目标字符串的其实搜索位置,初始查询时为整个字符串的起始字符的位置,在回溯查询时为正则表达式对象的lastIndex属性指定的索引位置。
(3) 匹配过程:在确定了起始位置后,便会从左到右逐个测试正则表达式的各组成部分,看能否找到匹配的字元。如果遇到表达式中的量词和分支,则需要进行决策,对于量词(*、+或{3}),需要判断从何时开始进行更多字符的匹配尝试;对于分支("|"或操作),每次需从选项中选择一个分支进行接下来的匹配。在正则表达式做这种决策的时候,会进行记录以备回溯时使用。
(4) 匹配结束:若当前完成一个字元的匹配,则正则表达式会继续向右扫描,如果接下来的部分也都能匹配上,则宣布匹配成功并结束匹配;若当前字元匹配不到,或者后续字元匹配失败,则会回溯到上一个决策点选择余下可选字元继续匹配过程,直到匹配到目标子字符串,宣布匹配成功,或者尝试了所有排列组合后也没找到。宣布匹配失败,结束本轮匹配。回到起始字符串的下一个字符,重复匹配过程。
2. 分支与重复
看看正则表达式在匹配过程中是如何处理分支重复的:

/<(img|p)>.*<\img>/.test("

")

开始匹配时,首先从左向右查找<字符,恰好目标字符串的第一个字符时<,然后进行img|p分支子表达式的处理,分支选择也是从左到右的,先检查img是否能匹配成功,发现字符<随后的字符p并不能匹配,此分支无法继续。需要回溯到最近一次的分支决策点,即首字母<的后面,尝试第二个分支p字符的匹配,发现匹配成功。
接下来的.号标识匹配除换行符外的任意字符,并且带有量词符号*,这是一个贪婪量词,需要重复0次或多次的匹配.号,由于目标字符串中不存在换行符,所以它会过滤掉接下来的所有字符,至字符串尾部往回继续匹配接下来的字元<\/img>,最后一个字符为>,不匹配所需的<,尝试倒数第二个字符p,p也不匹配,如此循环知道匹配到目标字元或找不到目标字元匹配失败。
如果我们仅想查找距离字元<(img|p)>最近的<\/img>,显然这种贪婪量词的搜索过程会扩大正则表达式的匹配空间,为此可以使用惰性量词.*?进行替换。
可以看出这里的目标字符串,对于贪婪量词与惰性量词的正则匹配结果是相同的,但它们的匹配过程却是不同的,所以当目标字符串变得非常大时,获得相同匹配结果的正则表达式,其执行性能可能会存在较大差异。
3. 回溯失控
当某个正则表达式的执行使浏览器卡顿数秒或更长时间,可能出现了回溯失控。如下:

/.*?.*?.*?<\/title>.*?<\/head>.*?<body>.*?<\/body>.*?<\/html>/
</code></pre> 
  <p>该正则表达式在匹配常规html文件时不会存在运行问题,但如果碰到一些必要的html标签缺失,那么其匹配效率或变得非常糟糕。比如当html文件中缺少结束标签<code></html></code>时,在匹配最后一个惰性量词后并未能找到符合字元<code><\/html></code>的字符串,此时正则表达式并不会结束,而是向前回溯到上一次的惰性量词出,继续字元<code><\/body></code>的匹配,以试图找到第二个<code></body></code>标签。如果没有找到,则会一次继续向前回调,可想而知这样的查询性能会很低。<br> 如何解决?首先可以想到具体化模糊字元,比如将.<em>?具体化为[^\r\n]</em>,进而去除集中回溯时可能发生的情况。虽然这种方式控制了可能的回溯失控,但在匹配不完整html文件时所需时间依然喝文件大小成线性关系,所以性能并没有得到有效提高。<br> 更为有效的方式时预查找,它作为全局匹配的一部分,能够仅检查自己所包含的正则表达式字元于当前位置是否能够匹配,并且不消耗字符,即在一个匹配发生后立即开始下一次匹配搜索,而非从包含预查找的字符后开始。预查找的形式是:(?=pattern),pattern代表一个正则表达式,改写上面的例子:</p> 
  <pre><code>/<html>(?=(.*?<head>))\1(?=(.*?<title>))\2(?=(.*?<\/title>))\3(?=(.*?<\/head>))\4(?=(.*?<body>))\5(?=(.*?<\/body>))\6.*?<\/html>/
</code></pre> 
  <p>这样当html问而建结尾部分缺少<code></html></code>标签时,最后的惰性量词.*?会展开至整个字符串末尾,由于没有有效回溯点,所以正则表达式会立即宣布失败。<br> 4. 量词嵌套<br> 另一个可能会引起回溯失控的写法就是量词嵌套,即在一个整体被量词修饰的组中有量词的使用,如:对一个包含大量T字符的字符串使用如下正则表达式进行匹配:</p> 
  <pre><code>/(T+T+)+Q/
</code></pre> 
  <p>这种排列组合会产生数量巨大的查找分支。为防止这种情况的发生,关键要确保正则表达式不对字符串相同的部分进行匹配,并且尽量保持正则表达式简洁易懂,可以改写为:<code>/TT+Q/</code>,但对于较复杂的正则表达式可能难以避免,必要时可采取预查找进行规避。</p> 
  <p><strong>5.3.3 优化正则表达式</strong><br> 一些有效提升正则表达式匹配效率的方法:</p> 
  <ol> 
   <li>化繁为简:大规模的单一正则表达式很呐维护,并且容易出现回溯失控的问题。可使用条件逻辑将复杂的字符串搜索问题拆分为多个正则表达式来解决。</li> 
   <li>将正则表达式赋值给变量:复用时可以避免重新编译。</li> 
   <li>合适的量词:使用合适的量词可以有效提升性能。</li> 
   <li>更快失败:通常正则表达式执行较慢不是其匹配成功较慢,而是匹配失败的过程较慢。若想让正则表达式更快执行完毕,应加快其失败的过程。</li> 
   <li>尽量具体:对于子表达式能够重叠匹配或字符与字元相邻时,正则表达式的可能分支路径会增加,所以表达式应更加具体化。</li> 
   <li>减少分支数量:正则表达式中,使用类似按位或的竖线符号|来表示分支选型,但通常建议尽量减少分支的使用,可以使用字符集或选项数组来代替,因为字符集在切换选项时使用的时位向量的方式,这笔分支采用的回溯快。示例:</li> 
  </ol> 
  <table> 
   <thead> 
    <tr> 
     <th>分支方式</th> 
     <th>字符集</th> 
    </tr> 
   </thead> 
   <tbody> 
    <tr> 
     <td>bat\mat</td> 
     <td>[bm]at</td> 
    </tr> 
    <tr> 
     <td>red\read</td> 
     <td>rea?d</td> 
    </tr> 
    <tr> 
     <td>(.|\r|\n)</td> 
     <td>[\s\S]</td> 
    </tr> 
   </tbody> 
  </table> 
  <p>注意采用非捕获组:由于捕获组需要记录反向引用,会更加消耗内存和引用。比如可以使用(?:pattern)代替(pattern)。<br> 使用反向引用避免后处理:如果使用场景需要引用匹配的一部分,则应尽量用捕获组捕获目标片段,然后通过反向引用进一步处理,而不是剥离出目标字符串后再手动处理。</p> 
  <h3>5.4 快速响应</h3> 
  <p>JavaScript代码的执行通常会阻塞页面的渲染,考虑到用户体验,这就会限制我们在编写代码时需要注意减少或避免一些执行时间过长的逻辑运算。</p> 
  <p><strong>5.4.1 浏览器的限制</strong><br> 由于JavaScript是单线程,这就意味着浏览器的每个窗口或页签在同一时间内,要么执行JavaScript脚本,要么响应用户操作刷新页面,也就是说这二者的行为是相互阻塞的。<br> 对于浏览器的这种限制,我们可能就需要对长时间运行的脚本进行重构,尽量保证一段脚本的执行不超过100ms,若果超过这个时间阈值,用户明显就会网站卡顿变慢的使用体验。<br> 引起JavaScript执行时间过长的原因概括有三点:<br> 第一类是对DOM的频繁操作,相比于JavaScript的运算,DOM操作的开销都是极高的,这也是现代前端框架中普遍采取虚拟DOM的原因。<br> 第二类是不恰当的循环,可能因为循环次数执行过多,或者每次循环中执行了过多操作,若能将功能尽可能分解就会明显缓解这个问题。<br> 第三类是存在过深的递归,前面章节有提到过浏览器对JavaScript调用栈存在限制,将递归改写成迭代能有效地避免此类问题。</p> 
  <p><strong>5.4.2 异步队列</strong><br> JavaScript既要处理运算又要响应与用户的交互,就是通过异步队列完成的。<br> 当创建一个异步任务时,它其实并没有马上执行,而是被JavaScript引擎放置到了一个队列中,当执行完成一个任务脚本后,JavaScript引擎便会挂起让浏览器去做其他工作,比如更新页面,当页面更新完后JavaScript引擎便会查看此异步队列,并从中取出一个任务脚本去执行,只要该队列不为空,这个过程就会不断重复。<br> 故此便有了对执行过长任务的一种优化策略,即将一个长任务拆分为多个异步任务,从而让浏览器给刷新页面留出时间,但过短的延迟时间也可能会让浏览器响应不及时,通常可以用定时器来控制一个100ms左右的延迟。</p> 
  <h3>5.5 其他建议</h3> 
  <p>除了前面的几种方法,还有些小技巧也能帮助浏览器高效执行JavaScript,比如避免多重求值、使用位操作及使用原生方法。</p> 
  <p><strong>5.5.1 避免多重求值</strong><br> 多重求值是脚本语言中普遍存在的一种语法特性,即动态执行包含可执行代码的字符串,虽然当前的主流前端项目很少会有类似的方法,但如果面临优化历史代码的场景,就需要对此多加留意。能够运行代码字符串的方法通常有如下四种:setTimeout()、setInterval()、eval()及Function()构造函数。</p> 
  <pre><code>const a = 1, b = 2;
let result = 0;
//使用setTimeout() 函数执行代码字符串
setTimeout("result = a + b", 100);
//使用setInterval() 函数执行代码字符串
setInterval("result = a + b", 100);
//使用eval() 函数执行代码字符串
result = eval("a + b");
//使用Function() 函数执行代码字符串
result = new Function("a", "b", "return a + b");
</code></pre> 
  <p>这四段代码的执行过程,首先会以正常的方式进行求值,接着在执行过程中对字符串里的代码进行一次额外的求值运算,这个运算操作的代价,与直接执行字符串中代码的代价相比时巨大的。在开发中应当避免使用Function()与eval()函数,同时切记在使用setTimeout()和setInterval()函数时第一个参数使用字符串。</p> 
  <p><strong>5.5.2 使用位操作</strong><br> 几乎在所有编程语言中,微操作的执行速度都是非常快的,因为位操作通常发生在系统底层。在JavaScript中使用有符号的32位二进制来表示一个数字,位操作就是直接按照二进制方式进行计算的,这要比其他数学运算和布尔操作快得多。</p> 
  <p><strong>5.5.3 使用原生方法</strong><br> 使用位操作来优化数学运算的场景也是比较有限的,面对复杂的数学运算时可以多使用JavaScript的原生方法。<br> 常用的原生方法:</p> 
  <table> 
   <thead> 
    <tr> 
     <th>属性\方法</th> 
     <th>含义</th> 
    </tr> 
   </thead> 
   <tbody> 
    <tr> 
     <td>Math.abs(num)</td> 
     <td>计算num的绝对值</td> 
    </tr> 
    <tr> 
     <td>Math.pow(num,power)</td> 
     <td>计算num的power次幂</td> 
    </tr> 
    <tr> 
     <td>Math.sqrt(num)</td> 
     <td>计算num的平方根</td> 
    </tr> 
    <tr> 
     <td>Math.exp(num)</td> 
     <td>计算自然对数底的指数</td> 
    </tr> 
    <tr> 
     <td>Math.cos(x)</td> 
     <td>计算余弦函数</td> 
    </tr> 
    <tr> 
     <td>Math.PI</td> 
     <td>计算圆周率</td> 
    </tr> 
    <tr> 
     <td>Math.SQRT2</td> 
     <td>计算2的平方根</td> 
    </tr> 
   </tbody> 
  </table> 
  <h3>5.6 小结</h3> 
  <p>从代码书写角度介绍了许多与前端性能相关的内容,包括数据存取、流程控制、字符串处理、不阻塞页面渲染流程的快速响应。以及能让JavaScript执行更快的一些技巧。<br> 同时详细介绍了如何优化正则表达式,从执行过程到回溯失控以及相关的一些优化注意事项都有介绍。</p> 
  <p>前端性能优化系列:<br> 前端性能优化:1.什么是前端性能优化<br> 前端性能优化:2.前端页面的生命周期<br> 前端性能优化:3.图像资源优化<br> 前端性能优化:4.资源加载优化<br> 前端性能优化:5.高性能的JavaScript代码<br> 前端性能优化:6.项目构建优化<br> 前端性能优化:7.页面渲染优化</p> 
 </div> 
</div>
                            </div>
                        </div>
                    </div>
                    <!--PC和WAP自适应版-->
                    <div id="SOHUCS" sid="1723007241986060288"></div>
                    <script type="text/javascript" src="/views/front/js/chanyan.js"></script>
                    <!-- 文章页-底部 动态广告位 -->
                    <div class="youdao-fixed-ad" id="detail_ad_bottom"></div>
                </div>
                <div class="col-md-3">
                    <div class="row" id="ad">
                        <!-- 文章页-右侧1 动态广告位 -->
                        <div id="right-1" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                            <div class="youdao-fixed-ad" id="detail_ad_1"> </div>
                        </div>
                        <!-- 文章页-右侧2 动态广告位 -->
                        <div id="right-2" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                            <div class="youdao-fixed-ad" id="detail_ad_2"></div>
                        </div>
                        <!-- 文章页-右侧3 动态广告位 -->
                        <div id="right-3" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                            <div class="youdao-fixed-ad" id="detail_ad_3"></div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div class="container">
        <h4 class="pt20 mb15 mt0 border-top">你可能感兴趣的:(前端性能优化,javascript,前端,性能优化)</h4>
        <div id="paradigm-article-related">
            <div class="recommend-post mb30">
                <ul class="widget-links">
                    <li><a href="/article/1833549636153995264.htm"
                           title="notepad++软件介绍(含安装包)" target="_blank">notepad++软件介绍(含安装包)</a>
                        <span class="text-muted">LQS2020</span>
<a class="tag" taget="_blank" href="/search/notepad%2B%2B/1.htm">notepad++</a>
                        <div>Notepad++是一款开源的文本编辑器,主要用于编程和代码编辑。它是一个功能强大的替代品,常常被用来替代Windows系统自带的记事本。Notepad++win系统免费下载地址以下是Notepad++的一些主要特点和功能:多语言支持:Notepad++支持多种编程语言,包括Python、JavaScript、HTML、CSS、C++、Java等。它能够根据文件类型自动高亮显示语法,使代码更加易读</div>
                    </li>
                    <li><a href="/article/1833538043076767744.htm"
                           title="Nestjs微服务简单案例" target="_blank">Nestjs微服务简单案例</a>
                        <span class="text-muted">海上彼尚</span>
<a class="tag" taget="_blank" href="/search/node.js/1.htm">node.js</a><a class="tag" taget="_blank" href="/search/%E5%BE%AE%E6%9C%8D%E5%8A%A1/1.htm">微服务</a><a class="tag" taget="_blank" href="/search/%E6%9E%B6%E6%9E%84/1.htm">架构</a><a class="tag" taget="_blank" href="/search/node.js/1.htm">node.js</a>
                        <div>相信大家,来看这篇博客,就应该知道微服务的概念。只是不太知道实用方法而已。下面我通过最简单的案例,来教会大家。首先这是我的项目目录:nestwfw/├──app/├──project-microsericesapp是web服务,用来接收前端请求的网络请求project-microserices是一个微服务,名字都是随意的安装nestnewappnestnewproject-microservice</div>
                    </li>
                    <li><a href="/article/1833528336924635136.htm"
                           title="【LangChain】使用LangChain的提示词模板:技巧与总结" target="_blank">【LangChain】使用LangChain的提示词模板:技巧与总结</a>
                        <span class="text-muted">子夜时辰</span>
<a class="tag" taget="_blank" href="/search/LangChain%E7%9A%84%E5%AD%A6%E4%B9%A0/1.htm">LangChain的学习</a><a class="tag" taget="_blank" href="/search/langchain/1.htm">langchain</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/node.js/1.htm">node.js</a><a class="tag" taget="_blank" href="/search/AIGC/1.htm">AIGC</a><a class="tag" taget="_blank" href="/search/chatgpt/1.htm">chatgpt</a>
                        <div>作者简介:前端开发爱好者,致力学习前端开发技术⭐️个人主页:夜宵饽饽的主页❔系列专栏:JavaScript小贴士学习格言:成功不是终点,失败也并非末日,最重要的是继续前进的勇气前言:这里是关于LangChain框架中的提示词模板使用的技巧,希望可以帮助到大家,欢迎大家的补充和纠正文章目录一、使用LangChain的提示词模板:技巧与总结1、格式化示例集2、示例选择器来组合提示词模板3、在聊天模型中</div>
                    </li>
                    <li><a href="/article/1833525688494288896.htm"
                           title="web前端基础——第八章" target="_blank">web前端基础——第八章</a>
                        <span class="text-muted">ZiminLi</span>
<a class="tag" taget="_blank" href="/search/%E6%8A%80%E6%9C%AF%E6%A0%88%E7%AC%94%E8%AE%B0/1.htm">技术栈笔记</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a>
                        <div>目录八十五、对象的简介和基本操作八十六、属性名和属性值八十七、基本数据类型和引用数据类型八十八、对象字面量八十九、函数的简介九十、函数的参数九十一、函数的返回值九十二、实参可以是任何值九十三、返回值的类型九十四、立即执行函数九十五、方法九十六、枚举对象中的属性九十七、作用域(Scope)全局作用域变量的声明提前函数作用域九十八、this九十九、使用工厂方法创建对象一百、构造函数一百零一、原型对象一</div>
                    </li>
                    <li><a href="/article/1833518628872482816.htm"
                           title="转码日记——Javascript笔记(8)" target="_blank">转码日记——Javascript笔记(8)</a>
                        <span class="text-muted">zzcoding_</span>
<a class="tag" taget="_blank" href="/search/%E8%BD%AC%E7%A0%81%E6%97%A5%E8%AE%B0/1.htm">转码日记</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/1.htm">数据结构</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
                        <div>数组(Array)数组也是一个对象,和普通对象功能类似。普通对象使用字符串作为属性名,而数组使用数字来作为索引操作。索引:从0开始的整数。数组的存储效率比较高,对属性名没有要求的时候可以使用。基本应用//创建数组对象vararr=newArray();//向数组中添加对象//语法:数组[索引]=值;arr[0]=10;arr[1]=33;//如果读取不存在的索引则返回undefined//获取数组</div>
                    </li>
                    <li><a href="/article/1833514974358630400.htm"
                           title="uni-app前端post请求数据json序列化解决" target="_blank">uni-app前端post请求数据json序列化解决</a>
                        <span class="text-muted">标准形与二次型</span>
<a class="tag" taget="_blank" href="/search/web/1.htm">web</a><a class="tag" taget="_blank" href="/search/%E6%8A%A5%E9%94%99/1.htm">报错</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a>
                        <div>问题:前端使用uni-app的uni.request发送post请求时,携带data参数会被json序列化对于POST方法且header[‘content-type’]为application/json的数据,会进行JSON序列化。官方文档这就导致我写好的登录页面,传递用户名和密码,使用postman可以正常请求,但前端页面发送post请求则会报错:Requiredrequestparameter</div>
                    </li>
                    <li><a href="/article/1833514090031575040.htm"
                           title="python中selenium中使用ajax_使用selenium和python捕获AJAX响应" target="_blank">python中selenium中使用ajax_使用selenium和python捕获AJAX响应</a>
                        <span class="text-muted">weixin_39946534</span>

                        <div>我曾经截获了一些使用selenium向页面注入javascript的ajax调用.历史的不好的一面是,硒有时可能是,说“脆弱”.因此,无论如何我在进行注射时都会遇到硒异常.无论如何,我的想法是拦截XHR调用,并将其响应设置为我创建的一个新的dom元素,我可以从selenium操作.在拦截的条件下,你甚至可以使用发出请求的url来拦截你真正想要的那个(self._url)也许这有帮助.browser</div>
                    </li>
                    <li><a href="/article/1833513837786132480.htm"
                           title="python提取数据库数据到前端html5显示_python html提取数据库数据" target="_blank">python提取数据库数据到前端html5显示_python html提取数据库数据</a>
                        <span class="text-muted">weixin_39878745</span>

                        <div>python开源工具列表【持续更新】以下是个人在工作中整理的一些pythonwheel,供参考。这个列表包含与网页抓取和数据处理的Python库网络通用urllib-网络库(stdlib)。requests-网络库。grab–网络库(基于pycurl)。pycurl–网络库(绑定libcurl)。urllib3–...文章武耀文2018-04-253128浏览量8个用于业余项目的优秀Python库</div>
                    </li>
                    <li><a href="/article/1833506143486439424.htm"
                           title="从理论到实践:MySQL 性能优化和高可用架构,一次讲清" target="_blank">从理论到实践:MySQL 性能优化和高可用架构,一次讲清</a>
                        <span class="text-muted">程序猿java易</span>
<a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a><a class="tag" taget="_blank" href="/search/%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/1.htm">性能优化</a><a class="tag" taget="_blank" href="/search/%E6%9E%B6%E6%9E%84/1.htm">架构</a>
                        <div>数据库系统作为IT业务系统的核心,其高可用性和容灾能力对整个业务系统的连续性和数据完整性起着至关重要的作用,是企业正常运营的基石尤其是在性能优化与高可用架构两方面,很多从业多年的DBA限于生产环境的固定体系,往往盲人摸象,难窥全局。而性能优化和高可用又是一对存在根本矛盾的特性。可以说,掌握了这两项技术的平衡,就掌握了MySQL的绝大部分内容,也就把握了数据库核心技术的最主流脉络。这本《MySQL性</div>
                    </li>
                    <li><a href="/article/1833503623452127232.htm"
                           title="(代码可运行)Bootstrap框架的HTML示例" target="_blank">(代码可运行)Bootstrap框架的HTML示例</a>
                        <span class="text-muted">程序员大侠</span>
<a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/CSS/1.htm">CSS</a><a class="tag" taget="_blank" href="/search/html/1.htm">html</a><a class="tag" taget="_blank" href="/search/bootstrap/1.htm">bootstrap</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a>
                        <div>Bootstrap:一套流行的前端开发框架,基于HTML、CSS和JavaScript,适用于快速构建响应式Web应用。以下是一个使用Bootstrap构建的简单响应式Web应用的HTML示例:BootstrapExampleHello,Bootstrap!CardtitleSomequickexampletexttobuildonthecardtitleandmakeupthebulkofthe</div>
                    </li>
                    <li><a href="/article/1833489635276320768.htm"
                           title="移动端测试" target="_blank">移动端测试</a>
                        <span class="text-muted">渔jy</span>
<a class="tag" taget="_blank" href="/search/Android%E7%B3%BB%E7%BB%9F%E5%8F%8A%E5%BA%94%E7%94%A8/1.htm">Android系统及应用</a><a class="tag" taget="_blank" href="/search/android/1.htm">android</a><a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a>
                        <div>三种移动端产品类型介绍移动端应用的测试其自身特点,和其他传统测试又有一些独特的测试方法与思路。移动端应用又可以进一步细分为三大类:WebApp指的是移动端的Web浏览器,其实和PC端的Web浏览器没有任何区别,只不过Web浏览器所依附的操作系统不再是Windows和Linux了,而是iOS和Android了。WebApp采用的技术主要是,传统的HTML、JavaScript、CSS等Web技术栈,</div>
                    </li>
                    <li><a href="/article/1833487741132828672.htm"
                           title="C# WinForm实现WebService接口进行图片上传下载" target="_blank">C# WinForm实现WebService接口进行图片上传下载</a>
                        <span class="text-muted">诡道荒行</span>

                        <div>本文还有配套的精品资源,点击获取简介:本文深入介绍了在C#WinForm应用程序中使用WebService接口连接服务器,实现图片的上传和下载功能。通过理解WebService基础,利用WinForm工具创建用户界面,并实现客户端与WebService的连接,我们详细探讨了图片上传与下载的具体步骤,包括文件选择、数据转换、接口调用,以及异常处理和进度显示。同时,还强调了安全性与性能优化的重要性,确</div>
                    </li>
                    <li><a href="/article/1833481816355467264.htm"
                           title="JavaScript 常用模块化规范" target="_blank">JavaScript 常用模块化规范</a>
                        <span class="text-muted">渡鸦七</span>
<a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/ecmascript/1.htm">ecmascript</a>
                        <div>JavaScript模块化规范1.模块化概述1.1什么时模块化将程序文件依据一定规则拆分成多个文件,这种编码方式就是模块化的编码方式。拆分出来每个文件就是一个模块,模块中的数据都是私有的,模块之间相互隔离。同事也能通过一些手段,可以把模块内的指定数据“交出去”,提供其他模块使用。1.2为什么使用模块化随着应用的复杂度越来越高,其代码量和文件数据都会急剧增加,会逐渐引发一些问题:全局污染问题。依赖混</div>
                    </li>
                    <li><a href="/article/1833479296862220288.htm"
                           title="深入探索从ES6到ES2023" target="_blank">深入探索从ES6到ES2023</a>
                        <span class="text-muted">hai40587</span>
<a class="tag" taget="_blank" href="/search/es6/1.htm">es6</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/ecmascript/1.htm">ecmascript</a>
                        <div>从ES6到ES2023,我们深入探索ECMAScript(简称ES)的演变与发展,了解这一JavaScript标准背后的技术革新和进步。ECMAScript作为JavaScript的标准化版本,每年都在不断推出新版本,为开发者带来更加丰富和强大的功能。本文将从ES6的引入开始,逐步介绍到最新的ES2023,同时探讨这些新特性对现代Web开发的影响。ECMAScript简介与JavaScript的关</div>
                    </li>
                    <li><a href="/article/1833472993293070336.htm"
                           title="HTML 文本标签" target="_blank">HTML 文本标签</a>
                        <span class="text-muted">一壶浊酒..</span>
<a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91/1.htm">前端开发</a><a class="tag" taget="_blank" href="/search/html/1.htm">html</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a>
                        <div>一个静态页面绝大部分都是由文字、图片、超链接、音频、视频组成。动态页面和静态页面的区别在于:是否与服务器进行数据交互标题标签这是一级标题这是二级标题这是三级标题这是四级标题这是五级标题这是六级标题web前端开发床前明月光,疑是地上霜。举头望明月,低头思故乡这是普通文本这是粗体文本这是粗体文本斜体文本斜体文本斜体文本--->(a+b)2=a2+b2+2abH2SO4是指硫酸分子水果原价:6元现在:5</div>
                    </li>
                    <li><a href="/article/1833472866520231936.htm"
                           title="我们在进行前后端联调的时候 如何避免数据丢失 拿不到返回数据 查看不了状态信息等问题?" target="_blank">我们在进行前后端联调的时候 如何避免数据丢失 拿不到返回数据 查看不了状态信息等问题?</a>
                        <span class="text-muted">朱道阳</span>
<a class="tag" taget="_blank" href="/search/%E5%BA%95%E5%B1%82%E5%8E%9F%E7%90%86/1.htm">底层原理</a><a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95%E5%85%AB%E8%82%A1/1.htm">面试八股</a><a class="tag" taget="_blank" href="/search/%E5%9B%9E%E5%BD%92/1.htm">回归</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/npm/1.htm">npm</a><a class="tag" taget="_blank" href="/search/git/1.htm">git</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a>
                        <div>最近在进行前后端联调开发的全栈开发工作但是这时候会出现很多问题比如说前端拿不到数据获得的状态码可能是正确的传的值却是null我进行了学习总结出一下几点一、数据校验前端程序员必须对后端提供的数据进行严格的数据校验。数据校验的目的是确保接收到的数据符合预期的格式和类型。在JavaScript中,可以使用typeof操作符或Array.isArray()方法进行基本的类型检查。更复杂的数据结构,可以使用</div>
                    </li>
                    <li><a href="/article/1833450783916519424.htm"
                           title="前端面试题(附答案)持续更新中……" target="_blank">前端面试题(附答案)持续更新中……</a>
                        <span class="text-muted">卖家导航</span>
<a class="tag" taget="_blank" href="/search/%E7%A8%8B%E5%BA%8F%E5%91%98/1.htm">程序员</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a>
                        <div>块标签:div、h1~h6、ul、li、table、p、br、form。特征:独占一行,换行显示,可以设置宽高,可以嵌套块和行行标签:span、a、img、textarea、select、option、input。特征:只有在行内显示,内容撑开宽、高,不可以设置宽、高(img、input、textarea等除外)。5.清除浮动⭐⭐⭐父级div定义overflow:hidden结尾处加空div标签c</div>
                    </li>
                    <li><a href="/article/1833450154104025088.htm"
                           title="牛客错题集3,前端开发结构" target="_blank">牛客错题集3,前端开发结构</a>
                        <span class="text-muted">卖家导航</span>
<a class="tag" taget="_blank" href="/search/%E7%A8%8B%E5%BA%8F%E5%91%98/1.htm">程序员</a><a class="tag" taget="_blank" href="/search/oracle/1.htm">oracle</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">数据库</a>
                        <div>在Thread中有一个成员变量ThreadLocals,该变量的类型是ThreadLocalMap,也就是一个Map,它的键是threadLocal,值为就是变量的副本。通过ThreadLocal的get()方法可以获取该线程变量的本地副本,在get方法之前要先set,否则就要重写initialValue()方法。ThreadLocal的使用场景:数据库连接:在多线程中,如果使用懒汉式的单例模式创</div>
                    </li>
                    <li><a href="/article/1833449397376086016.htm"
                           title="linux-性能优化命令" target="_blank">linux-性能优化命令</a>
                        <span class="text-muted">码农小伙</span>
<a class="tag" taget="_blank" href="/search/Linux/1.htm">Linux</a><a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a><a class="tag" taget="_blank" href="/search/%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/1.htm">性能优化</a><a class="tag" taget="_blank" href="/search/%E6%9C%8D%E5%8A%A1%E5%99%A8/1.htm">服务器</a>
                        <div>top我们先来说说top命令用法,这个命令对于我们监控linux性能是至关重要的,我们先来看看展示结果。top-15:20:23up10min,2users,loadaverage:0.39,0.53,0.35Tasks:217total,1running,216sleeping,0stopped,0zombie%Cpu(s):0.0us,0.0sy,0.0ni,100.0id,0.0wa,0.0</div>
                    </li>
                    <li><a href="/article/1833441071204495360.htm"
                           title="07_React 路由" target="_blank">07_React 路由</a>
                        <span class="text-muted">qiao若huan喜</span>
<a class="tag" taget="_blank" href="/search/React/1.htm">React</a><a class="tag" taget="_blank" href="/search/%E5%85%A8%E5%AE%B6%E6%A1%B6/1.htm">全家桶</a><a class="tag" taget="_blank" href="/search/react.js/1.htm">react.js</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6/1.htm">前端框架</a>
                        <div>React路由(5.x版本)一、相关理解1、SPA的理解2、路由的理解2.1什么是路由?2.2路由分类2.2.1后端路由2.2.2前端路由3、react-router-dom(Web开发使用)的理解二、react-router-dom相关API1、内置组件1.1BrowserRouter1.2HashRouter1.3Route1.4Redirect1.5Link1.6NavLink1.7Swit</div>
                    </li>
                    <li><a href="/article/1833440060079435776.htm"
                           title="WebKit 简介及工作流程深度解析" target="_blank">WebKit 简介及工作流程深度解析</a>
                        <span class="text-muted">不知名靓仔</span>
<a class="tag" taget="_blank" href="/search/webkit/1.htm">webkit</a><a class="tag" taget="_blank" href="/search/chrome/1.htm">chrome</a><a class="tag" taget="_blank" href="/search/safari/1.htm">safari</a><a class="tag" taget="_blank" href="/search/edge/1.htm">edge</a>
                        <div>WebKit是一个开源的浏览器引擎,最初由苹果公司为Safari浏览器开发,后来被多个浏览器和应用采纳,如早期的Chrome和众多移动平台上的浏览器。WebKit不仅仅是一个渲染引擎,它集成了HTML、CSS、JavaScript的解析与渲染能力,以及网络资源加载、图形处理、排版布局等功能,为用户提供丰富的网页浏览体验。本文将深入探讨WebKit的核心组件以及其复杂的工作流程。WebKit核心架构</div>
                    </li>
                    <li><a href="/article/1833417579285278720.htm"
                           title="JavaScript对象" target="_blank">JavaScript对象</a>
                        <span class="text-muted">yeyang111</span>

                        <div>1.varfram={framer:'小明',dogs:["小兔","小猫"],field:[2,3,4]}六角学院截图.png2.向对象里边增加varfram={framer1:'小明',dogs:["小兔","小猫"],field:[2,3,4]}fram.framer2='小蕴'可以在控制台发现增加了一个0X7M8BN7.png3.像对象里边增加函数(方法)varfram={framer1:</div>
                    </li>
                    <li><a href="/article/1833411191523864576.htm"
                           title="标题:深入理解 JavaScript 中的定时器" target="_blank">标题:深入理解 JavaScript 中的定时器</a>
                        <span class="text-muted">小刘|</span>
<a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
                        <div>目录一、定时器的基本概念1.setInterval2.setTimeout二、代码示例分析一、定时器的基本概念在JavaScript中,定时器是一种用于在特定时间间隔后执行代码或者重复执行代码的机制。主要包含两种类型的定时器:setInterval和setTimeout。1.setIntervalsetInterval()是一个周期函数,它会在指定的时间间隔后,重复执行指定的函数。例如:vari=</div>
                    </li>
                    <li><a href="/article/1833410183246737408.htm"
                           title="js函数eval()" target="_blank">js函数eval()</a>
                        <span class="text-muted">温暖前端</span>
<a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
                        <div>1.eval()函数简介eval()是JavaScript中的一个全局函数,它可以将传入的字符串当作JavaScript代码来执行。eval()函数的基本语法如下:eval(string)其中,string是要执行的JavaScript代码字符串。eval()函数会返回最后一个表达式的结果。2.eval()的工作原理当调用eval()函数时,JavaScript解释器会执行以下步骤:a.解析传入的</div>
                    </li>
                    <li><a href="/article/1833406654624919552.htm"
                           title="前端Axios搭配Vue(认清Axios,Axios结合Vue发出Ajax请求,返回JSON数据案例!简洁易懂。)" target="_blank">前端Axios搭配Vue(认清Axios,Axios结合Vue发出Ajax请求,返回JSON数据案例!简洁易懂。)</a>
                        <span class="text-muted">酸奶代码</span>
<a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/json/1.htm">json</a><a class="tag" taget="_blank" href="/search/ajax/1.htm">ajax</a>
                        <div>一.什么是Axios1.axios是独立于vue的一个项目,不是Vue的一部分2.axios通常和Vue一起使用,实现Ajax操作3.Axios是一个基于promise的HTTP库axios官方文档二.引入Axios库文件1.可以直接引用2.可以下载Axios的js文件导入下载此js文件三.使用Axios配合Vue发出Ajax请求案例在Vue中使用Axios,向服务器发送Ajax请求,将获取的js</div>
                    </li>
                    <li><a href="/article/1833404841544740864.htm"
                           title="JavaScript之OOP基础概念学习总结一:scopes" target="_blank">JavaScript之OOP基础概念学习总结一:scopes</a>
                        <span class="text-muted">gaoshu883</span>

                        <div>这个系列的文章是去年在搭架完静态博客后撰写的(博客已经不再维护啦,哦还能访问)↓最近在探究JavaScript中的scopes概念。经过一番研究,我觉得要从Interpreter的角度,才能更好地理解这个概念。毕竟程序员主要是编写指令,而Interpreter则是把程序员编写的代码一行一行读下去并翻译出来(执行出来),最终结果就会直接反映在Web浏览器的页面上。不过还要注意的是,并不是所有的sco</div>
                    </li>
                    <li><a href="/article/1833403380370862080.htm"
                           title="Springboot 项目中引入WebSocket后,单元测试出现错误,前端开发揭秘" target="_blank">Springboot 项目中引入WebSocket后,单元测试出现错误,前端开发揭秘</a>
                        <span class="text-muted">杭州湾Java仔</span>
<a class="tag" taget="_blank" href="/search/2024%E5%B9%B4%E5%89%8D%E7%AB%AF%E7%A8%8B%E5%BA%8F%E5%91%98/1.htm">2024年前端程序员</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/boot/1.htm">boot</a><a class="tag" taget="_blank" href="/search/websocket/1.htm">websocket</a><a class="tag" taget="_blank" href="/search/%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95/1.htm">单元测试</a>
                        <div>java.lang.IllegalStateException:FailedtoloadApplicationContextatorg.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:12</div>
                    </li>
                    <li><a href="/article/1833401110015078400.htm"
                           title="Puppeteer Heap Snapshot: 探索JavaScript内存世界的利器" target="_blank">Puppeteer Heap Snapshot: 探索JavaScript内存世界的利器</a>
                        <span class="text-muted">金畏战Goddard</span>

                        <div>PuppeteerHeapSnapshot:探索JavaScript内存世界的利器puppeteer-heap-snapshotadriancooney/puppeteer-heap-snapshot:puppeteer-heap-snapshot是一个Node.js包,提供了通过Puppeteer获取浏览器内存堆快照的功能,以辅助JavaScript应用的内存泄漏检测和性能优化工作。项目地址:h</div>
                    </li>
                    <li><a href="/article/1833401110359011328.htm"
                           title="Puppeteer-Sign:自动化网页签名解决方案" target="_blank">Puppeteer-Sign:自动化网页签名解决方案</a>
                        <span class="text-muted">杭臣磊Sibley</span>

                        <div>Puppeteer-Sign:自动化网页签名解决方案项目简介是一个基于谷歌的Puppeteer库开发的工具,用于自动化处理网页表单的签名过程。它模拟了真实用户的交互行为,可以用于需要电子签名的各种场景,比如在线合同签署、文档审批等。项目以JavaScript编写,易于集成到Web应用或者CI/CD流程中。技术分析Puppeteer库Puppeteer是由GoogleChrome团队维护的一个Nod</div>
                    </li>
                    <li><a href="/article/1833389517101428736.htm"
                           title="Java 上传读取Excel文件" target="_blank">Java 上传读取Excel文件</a>
                        <span class="text-muted">Ben_1043556915</span>
<a class="tag" taget="_blank" href="/search/Java%E8%BF%9B%E9%98%B6/1.htm">Java进阶</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/servlet/1.htm">servlet</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
                        <div>Web中導入Excel文件ExtJs前端代碼://=========上傳Excel=============================uploadPanel=newExt.form.FormPanel({fileUpload:true,id:'fileUploadForm',frame:true,labelAlign:'right',buttonAlign:'center',labelWid</div>
                    </li>
                                <li><a href="/article/57.htm"
                                       title="多线程编程之join()方法" target="_blank">多线程编程之join()方法</a>
                                    <span class="text-muted">周凡杨</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/JOIN/1.htm">JOIN</a><a class="tag" taget="_blank" href="/search/%E5%A4%9A%E7%BA%BF%E7%A8%8B/1.htm">多线程</a><a class="tag" taget="_blank" href="/search/%E7%BC%96%E7%A8%8B/1.htm">编程</a><a class="tag" taget="_blank" href="/search/%E7%BA%BF%E7%A8%8B/1.htm">线程</a>
                                    <div>现实生活中,有些工作是需要团队中成员依次完成的,这就涉及到了一个顺序问题。现在有T1、T2、T3三个工人,如何保证T2在T1执行完后执行,T3在T2执行完后执行?问题分析:首先问题中有三个实体,T1、T2、T3, 因为是多线程编程,所以都要设计成线程类。关键是怎么保证线程能依次执行完呢?   
Java实现过程如下: 
public class T1 implements Runnabl</div>
                                </li>
                                <li><a href="/article/184.htm"
                                       title="java中switch的使用" target="_blank">java中switch的使用</a>
                                    <span class="text-muted">bingyingao</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/enum/1.htm">enum</a><a class="tag" taget="_blank" href="/search/break/1.htm">break</a><a class="tag" taget="_blank" href="/search/continue/1.htm">continue</a>
                                    <div>java中的switch仅支持case条件仅支持int、enum两种类型。 
用enum的时候,不能直接写下列形式。 
 
 
switch (timeType) {
            case ProdtransTimeTypeEnum.DAILY:

                break;

            default:
                br</div>
                                </li>
                                <li><a href="/article/311.htm"
                                       title="hive having count 不能去重" target="_blank">hive having count 不能去重</a>
                                    <span class="text-muted">daizj</span>
<a class="tag" taget="_blank" href="/search/hive/1.htm">hive</a><a class="tag" taget="_blank" href="/search/%E5%8E%BB%E9%87%8D/1.htm">去重</a><a class="tag" taget="_blank" href="/search/having+count/1.htm">having count</a><a class="tag" taget="_blank" href="/search/%E8%AE%A1%E6%95%B0/1.htm">计数</a>
                                    <div>hive在使用having count()是,不支持去重计数 
  
hive (default)> select imei from t_test_phonenum where ds=20150701 group by imei having count(distinct phone_num)>1 limit 10;  
FAILED: SemanticExcep</div>
                                </li>
                                <li><a href="/article/438.htm"
                                       title="WebSphere对JSP的缓存" target="_blank">WebSphere对JSP的缓存</a>
                                    <span class="text-muted">周凡杨</span>
<a class="tag" taget="_blank" href="/search/WAS+JSP+%E7%BC%93%E5%AD%98/1.htm">WAS JSP 缓存</a>
                                    <div>      对于线网上的工程,更新JSP到WebSphere后,有时会出现修改的jsp没有起作用,特别是改变了某jsp的样式后,在页面中没看到效果,这主要就是由于websphere中缓存的缘故,这就要清除WebSphere中jsp缓存。要清除WebSphere中JSP的缓存,就要找到WAS安装后的根目录。 
       现服务</div>
                                </li>
                                <li><a href="/article/565.htm"
                                       title="设计模式总结" target="_blank">设计模式总结</a>
                                    <span class="text-muted">朱辉辉33</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/1.htm">设计模式</a>
                                    <div>1.工厂模式 
  1.1 工厂方法模式 (由一个工厂类管理构造方法) 
     1.1.1普通工厂模式(一个工厂类中只有一个方法) 
     1.1.2多工厂模式(一个工厂类中有多个方法) 
     1.1.3静态工厂模式(将工厂类中的方法变成静态方法) 
&n</div>
                                </li>
                                <li><a href="/article/692.htm"
                                       title="实例:供应商管理报表需求调研报告" target="_blank">实例:供应商管理报表需求调研报告</a>
                                    <span class="text-muted">老A不折腾</span>
<a class="tag" taget="_blank" href="/search/finereport/1.htm">finereport</a><a class="tag" taget="_blank" href="/search/%E6%8A%A5%E8%A1%A8%E7%B3%BB%E7%BB%9F/1.htm">报表系统</a><a class="tag" taget="_blank" href="/search/%E6%8A%A5%E8%A1%A8%E8%BD%AF%E4%BB%B6/1.htm">报表软件</a><a class="tag" taget="_blank" href="/search/%E4%BF%A1%E6%81%AF%E5%8C%96%E9%80%89%E5%9E%8B/1.htm">信息化选型</a>
                                    <div>引言 
随着企业集团的生产规模扩张,为支撑全球供应链管理,对于供应商的管理和采购过程的监控已经不局限于简单的交付以及价格的管理,目前采购及供应商管理各个环节的操作分别在不同的系统下进行,而各个数据源都独立存在,无法提供统一的数据支持;因此,为了实现对于数据分析以提供采购决策,建立报表体系成为必须。 业务目标 
1、通过报表为采购决策提供数据分析与支撑 
2、对供应商进行综合评估以及管理,合理管理和</div>
                                </li>
                                <li><a href="/article/819.htm"
                                       title="mysql" target="_blank">mysql</a>
                                    <span class="text-muted">林鹤霄</span>

                                    <div>转载源:http://blog.sina.com.cn/s/blog_4f925fc30100rx5l.html 
mysql -uroot -p 
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES) 
  
[root@centos var]# service mysql</div>
                                </li>
                                <li><a href="/article/946.htm"
                                       title="Linux下多线程堆栈查看工具(pstree、ps、pstack)" target="_blank">Linux下多线程堆栈查看工具(pstree、ps、pstack)</a>
                                    <span class="text-muted">aigo</span>
<a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a>
                                    <div>原文:http://blog.csdn.net/yfkiss/article/details/6729364 
  
1. pstree 
pstree以树结构显示进程$ pstree -p work | grep adsshd(22669)---bash(22670)---ad_preprocess(4551)-+-{ad_preprocess}(4552)  &n</div>
                                </li>
                                <li><a href="/article/1073.htm"
                                       title="html input与textarea 值改变事件" target="_blank">html input与textarea 值改变事件</a>
                                    <span class="text-muted">alxw4616</span>
<a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a>
                                    <div>// 文本输入框(input) 文本域(textarea)值改变事件 
// onpropertychange(IE) oninput(w3c) 
$('input,textarea').on('propertychange input', function(event) { 
     console.log($(this).val()) 
}); 
  </div>
                                </li>
                                <li><a href="/article/1200.htm"
                                       title="String类的基本用法" target="_blank">String类的基本用法</a>
                                    <span class="text-muted">百合不是茶</span>
<a class="tag" taget="_blank" href="/search/String/1.htm">String</a>
                                    <div>  
字符串的用法; 
    // 根据字节数组创建字符串 
byte[] by = { 'a', 'b', 'c', 'd' };
String newByteString = new String(by); 
  
  
    1,length()  获取字符串的长度 
  
  &nbs</div>
                                </li>
                                <li><a href="/article/1327.htm"
                                       title="JDK1.5 Semaphore实例" target="_blank">JDK1.5 Semaphore实例</a>
                                    <span class="text-muted">bijian1013</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/thread/1.htm">thread</a><a class="tag" taget="_blank" href="/search/java%E5%A4%9A%E7%BA%BF%E7%A8%8B/1.htm">java多线程</a><a class="tag" taget="_blank" href="/search/Semaphore/1.htm">Semaphore</a>
                                    <div>Semaphore类 
       一个计数信号量。从概念上讲,信号量维护了一个许可集合。如有必要,在许可可用前会阻塞每一个 acquire(),然后再获取该许可。每个 release() 添加一个许可,从而可能释放一个正在阻塞的获取者。但是,不使用实际的许可对象,Semaphore 只对可用许可的号码进行计数,并采取相应的行动。 
S</div>
                                </li>
                                <li><a href="/article/1454.htm"
                                       title="使用GZip来压缩传输量" target="_blank">使用GZip来压缩传输量</a>
                                    <span class="text-muted">bijian1013</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/GZip/1.htm">GZip</a>
                                    <div>        启动GZip压缩要用到一个开源的Filter:PJL Compressing Filter。这个Filter自1.5.0开始该工程开始构建于JDK5.0,因此在JDK1.4环境下只能使用1.4.6。 
        PJL Compressi</div>
                                </li>
                                <li><a href="/article/1581.htm"
                                       title="【Java范型三】Java范型详解之范型类型通配符" target="_blank">【Java范型三】Java范型详解之范型类型通配符</a>
                                    <span class="text-muted">bit1129</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a>
                                    <div>  
  
定义如下一个简单的范型类, 
  
package com.tom.lang.generics;

public class Generics<T> {
    private T value;
    public Generics(T  value) {
        this.value = value;
    }
} </div>
                                </li>
                                <li><a href="/article/1708.htm"
                                       title="【Hadoop十二】HDFS常用命令" target="_blank">【Hadoop十二】HDFS常用命令</a>
                                    <span class="text-muted">bit1129</span>
<a class="tag" taget="_blank" href="/search/hadoop/1.htm">hadoop</a>
                                    <div>1. 修改日志文件查看器 
  
hdfs oev -i edits_0000000000000000081-0000000000000000089 -o edits.xml
cat edits.xml 
  
修改日志文件转储为xml格式的edits.xml文件,其中每条RECORD就是一个操作事务日志 
  2. fsimage查看HDFS中的块信息等 
&nb</div>
                                </li>
                                <li><a href="/article/1835.htm"
                                       title="怎样区别nginx中rewrite时break和last" target="_blank">怎样区别nginx中rewrite时break和last</a>
                                    <span class="text-muted">ronin47</span>

                                    <div>在使用nginx配置rewrite中经常会遇到有的地方用last并不能工作,换成break就可以,其中的原理是对于根目录的理解有所区别,按我的测试结果大致是这样的。  
 
 location /    
 {     
     proxy_pass http://test; </div>
                                </li>
                                <li><a href="/article/1962.htm"
                                       title="java-21.中兴面试题 输入两个整数 n 和 m ,从数列 1 , 2 , 3.......n 中随意取几个数 , 使其和等于 m" target="_blank">java-21.中兴面试题 输入两个整数 n 和 m ,从数列 1 , 2 , 3.......n 中随意取几个数 , 使其和等于 m</a>
                                    <span class="text-muted">bylijinnan</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a>
                                    <div>
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

public class CombinationToSum {

	/*
第21 题
2010 年中兴面试题
编程求解:
输入两个整数 n 和 m ,从数列 1 , 2 , 3.......n 中随意取几个数 ,
使其和等</div>
                                </li>
                                <li><a href="/article/2089.htm"
                                       title="eclipse svn 帐号密码修改问题" target="_blank">eclipse svn 帐号密码修改问题</a>
                                    <span class="text-muted">开窍的石头</span>
<a class="tag" taget="_blank" href="/search/eclipse/1.htm">eclipse</a><a class="tag" taget="_blank" href="/search/SVN/1.htm">SVN</a><a class="tag" taget="_blank" href="/search/svn%E5%B8%90%E5%8F%B7%E5%AF%86%E7%A0%81%E4%BF%AE%E6%94%B9/1.htm">svn帐号密码修改</a>
                                    <div>问题描述: 
     Eclipse的SVN插件Subclipse做得很好,在svn操作方面提供了很强大丰富的功能。但到目前为止,该插件对svn用户的概念极为淡薄,不但不能方便地切换用户,而且一旦用户的帐号、密码保存之后,就无法再变更了。 
解决思路: 
     删除subclipse记录的帐号、密码信息,重新输入</div>
                                </li>
                                <li><a href="/article/2216.htm"
                                       title="[电子商务]传统商务活动与互联网的结合" target="_blank">[电子商务]传统商务活动与互联网的结合</a>
                                    <span class="text-muted">comsci</span>
<a class="tag" taget="_blank" href="/search/%E7%94%B5%E5%AD%90%E5%95%86%E5%8A%A1/1.htm">电子商务</a>
                                    <div> 
 
      某一个传统名牌产品,过去销售的地点就在某些特定的地区和阶层,现在进入互联网之后,用户的数量群突然扩大了无数倍,但是,这种产品潜在的劣势也被放大了无数倍,这种销售利润与经营风险同步放大的效应,在最近几年将会频繁出现。。。。 
 
       如何避免销售量和利润率增加的</div>
                                </li>
                                <li><a href="/article/2343.htm"
                                       title="java 解析 properties-使用 Properties-可以指定配置文件路径" target="_blank">java 解析 properties-使用 Properties-可以指定配置文件路径</a>
                                    <span class="text-muted">cuityang</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/properties/1.htm">properties</a>
                                    <div>#mq 
xdr.mq.url=tcp://192.168.100.15:61618; 
 
import java.io.IOException; 
import java.util.Properties; 
 
 
public class Test { 
 
 String conf = "log4j.properties"; 
 private static final</div>
                                </li>
                                <li><a href="/article/2470.htm"
                                       title="Java核心问题集锦" target="_blank">Java核心问题集锦</a>
                                    <span class="text-muted">darrenzhu</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%9F%BA%E7%A1%80/1.htm">基础</a><a class="tag" taget="_blank" href="/search/%E6%A0%B8%E5%BF%83/1.htm">核心</a><a class="tag" taget="_blank" href="/search/%E9%9A%BE%E7%82%B9/1.htm">难点</a>
                                    <div>注意,这里的参考文章基本来自Effective Java和jdk源码 
 
 
1)ConcurrentModificationException 
当你用for each遍历一个list时,如果你在循环主体代码中修改list中的元素,将会得到这个Exception,解决的办法是: 
1)用listIterator, 它支持在遍历的过程中修改元素, 
2)不用listIterator, new一个</div>
                                </li>
                                <li><a href="/article/2724.htm"
                                       title="1分钟学会Markdown语法" target="_blank">1分钟学会Markdown语法</a>
                                    <span class="text-muted">dcj3sjt126com</span>
<a class="tag" taget="_blank" href="/search/markdown/1.htm">markdown</a>
                                    <div>markdown 简明语法 基本符号 
 
 *,-,+ 3个符号效果都一样,这3个符号被称为 Markdown符号  
 空白行表示另起一个段落 
 `是表示inline代码,tab是用来标记 代码段,分别对应html的code,pre标签 
 换行 
 
 单一段落( <p>) 用一个空白行 
 连续两个空格 会变成一个 <br> 
 连续3个符号,然后是空行</div>
                                </li>
                                <li><a href="/article/2851.htm"
                                       title="Gson使用二(GsonBuilder)" target="_blank">Gson使用二(GsonBuilder)</a>
                                    <span class="text-muted">eksliang</span>
<a class="tag" taget="_blank" href="/search/json/1.htm">json</a><a class="tag" taget="_blank" href="/search/gson/1.htm">gson</a><a class="tag" taget="_blank" href="/search/GsonBuilder/1.htm">GsonBuilder</a>
                                    <div>转载请出自出处:http://eksliang.iteye.com/blog/2175473 一.概述 
    GsonBuilder用来定制java跟json之间的转换格式 
  二.基本使用 
实体测试类: 
温馨提示:默认情况下@Expose注解是不起作用的,除非你用GsonBuilder创建Gson的时候调用了GsonBuilder.excludeField</div>
                                </li>
                                <li><a href="/article/2978.htm"
                                       title="报ClassNotFoundException: Didn't find class "...Activity" on path: DexPathList" target="_blank">报ClassNotFoundException: Didn't find class "...Activity" on path: DexPathList</a>
                                    <span class="text-muted">gundumw100</span>
<a class="tag" taget="_blank" href="/search/android/1.htm">android</a>
                                    <div>有一个工程,本来运行是正常的,我想把它移植到另一台PC上,结果报: 
 
 java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.mobovip.bgr/com.mobovip.bgr.MainActivity}: java.lang.ClassNotFoundException: Didn't f</div>
                                </li>
                                <li><a href="/article/3105.htm"
                                       title="JavaWeb之JSP指令" target="_blank">JavaWeb之JSP指令</a>
                                    <span class="text-muted">ihuning</span>
<a class="tag" taget="_blank" href="/search/javaweb/1.htm">javaweb</a>
                                    <div>  
要点 
  
JSP指令简介  
page指令  
include指令  
  
JSP指令简介  
  
JSP指令(directive)是为JSP引擎而设计的,它们并不直接产生任何可见输出,而只是告诉引擎如何处理JSP页面中的其余部分。 
JSP指令的基本语法格式: 
<%@ 指令 属性名="</div>
                                </li>
                                <li><a href="/article/3232.htm"
                                       title="mac上编译FFmpeg跑ios" target="_blank">mac上编译FFmpeg跑ios</a>
                                    <span class="text-muted">啸笑天</span>
<a class="tag" taget="_blank" href="/search/ffmpeg/1.htm">ffmpeg</a>
                                    <div>1、下载文件:https://github.com/libav/gas-preprocessor, 复制gas-preprocessor.pl到/usr/local/bin/下, 修改文件权限:chmod 777 /usr/local/bin/gas-preprocessor.pl 
2、安装yasm-1.2.0 
curl http://www.tortall.net/projects/yasm</div>
                                </li>
                                <li><a href="/article/3359.htm"
                                       title="sql mysql oracle中字符串连接" target="_blank">sql mysql oracle中字符串连接</a>
                                    <span class="text-muted">macroli</span>
<a class="tag" taget="_blank" href="/search/oracle/1.htm">oracle</a><a class="tag" taget="_blank" href="/search/sql/1.htm">sql</a><a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a><a class="tag" taget="_blank" href="/search/SQL+Server/1.htm">SQL Server</a>
                                    <div>有的时候,我们有需要将由不同栏位获得的资料串连在一起。每一种资料库都有提供方法来达到这个目的: 
 
 MySQL: CONCAT() 
 Oracle: CONCAT(), || 
 SQL Server: + 
 
CONCAT() 的语法如下: 
Mysql 中 CONCAT(字串1, 字串2, 字串3, ...): 将字串1、字串2、字串3,等字串连在一起。 
请注意,Oracle的CON</div>
                                </li>
                                <li><a href="/article/3486.htm"
                                       title="Git fatal: unab SSL certificate problem: unable to get local issuer ce rtificate" target="_blank">Git fatal: unab SSL certificate problem: unable to get local issuer ce rtificate</a>
                                    <span class="text-muted">qiaolevip</span>
<a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0%E6%B0%B8%E6%97%A0%E6%AD%A2%E5%A2%83/1.htm">学习永无止境</a><a class="tag" taget="_blank" href="/search/%E6%AF%8F%E5%A4%A9%E8%BF%9B%E6%AD%A5%E4%B8%80%E7%82%B9%E7%82%B9/1.htm">每天进步一点点</a><a class="tag" taget="_blank" href="/search/git/1.htm">git</a><a class="tag" taget="_blank" href="/search/%E7%BA%B5%E8%A7%82%E5%8D%83%E8%B1%A1/1.htm">纵观千象</a>
                                    <div>// 报错如下: 
$ git pull origin master 
fatal: unable to access 'https://git.xxx.com/': SSL certificate problem: unable to get local issuer ce 
rtificate 
  
// 原因: 
由于git最新版默认使用ssl安全验证,但是我们是使用的git未设</div>
                                </li>
                                <li><a href="/article/3613.htm"
                                       title="windows命令行设置wifi" target="_blank">windows命令行设置wifi</a>
                                    <span class="text-muted">surfingll</span>
<a class="tag" taget="_blank" href="/search/windows/1.htm">windows</a><a class="tag" taget="_blank" href="/search/wifi/1.htm">wifi</a><a class="tag" taget="_blank" href="/search/%E7%AC%94%E8%AE%B0%E6%9C%ACwifi/1.htm">笔记本wifi</a>
                                    <div>还没有讨厌无线wifi的无尽广告么,还在耐心等待它慢慢启动么 
教你命令行设置 笔记本电脑wifi: 
 
1、开启wifi命令 
 

netsh wlan set hostednetwork mode=allow ssid=surf8 key=bb123456
netsh wlan start hostednetwork
pause
 
 其中pause是等待输入,可以去掉 
 
2、</div>
                                </li>
                                <li><a href="/article/3740.htm"
                                       title="Linux(Ubuntu)下安装sysv-rc-conf" target="_blank">Linux(Ubuntu)下安装sysv-rc-conf</a>
                                    <span class="text-muted">wmlJava</span>
<a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a><a class="tag" taget="_blank" href="/search/ubuntu/1.htm">ubuntu</a><a class="tag" taget="_blank" href="/search/sysv-rc-conf/1.htm">sysv-rc-conf</a>
                                    <div>安装:sudo apt-get install sysv-rc-conf 使用:sudo sysv-rc-conf 
操作界面十分简洁,你可以用鼠标点击,也可以用键盘方向键定位,用空格键选择,用Ctrl+N翻下一页,用Ctrl+P翻上一页,用Q退出。 
  
  
背景知识 
sysv-rc-conf是一个强大的服务管理程序,群众的意见是sysv-rc-conf比chkconf</div>
                                </li>
                                <li><a href="/article/3867.htm"
                                       title="svn切换环境,重发布应用多了javaee标签前缀" target="_blank">svn切换环境,重发布应用多了javaee标签前缀</a>
                                    <span class="text-muted">zengshaotao</span>
<a class="tag" taget="_blank" href="/search/javaee/1.htm">javaee</a>
                                    <div>更换了开发环境,从杭州,改变到了上海。svn的地址肯定要切换的,切换之前需要将原svn自带的.svn文件信息删除,可手动删除,也可通过废弃原来的svn位置提示删除.svn时删除。 
  
然后就是按照最新的svn地址和规范建立相关的目录信息,再将原来的纯代码信息上传到新的环境。然后再重新检出,这样每次修改后就可以看到哪些文件被修改过,这对于增量发布的规范特别有用。 
  
检出</div>
                                </li>
                </ul>
            </div>
        </div>
    </div>

<div>
    <div class="container">
        <div class="indexes">
            <strong>按字母分类:</strong>
            <a href="/tags/A/1.htm" target="_blank">A</a><a href="/tags/B/1.htm" target="_blank">B</a><a href="/tags/C/1.htm" target="_blank">C</a><a
                href="/tags/D/1.htm" target="_blank">D</a><a href="/tags/E/1.htm" target="_blank">E</a><a href="/tags/F/1.htm" target="_blank">F</a><a
                href="/tags/G/1.htm" target="_blank">G</a><a href="/tags/H/1.htm" target="_blank">H</a><a href="/tags/I/1.htm" target="_blank">I</a><a
                href="/tags/J/1.htm" target="_blank">J</a><a href="/tags/K/1.htm" target="_blank">K</a><a href="/tags/L/1.htm" target="_blank">L</a><a
                href="/tags/M/1.htm" target="_blank">M</a><a href="/tags/N/1.htm" target="_blank">N</a><a href="/tags/O/1.htm" target="_blank">O</a><a
                href="/tags/P/1.htm" target="_blank">P</a><a href="/tags/Q/1.htm" target="_blank">Q</a><a href="/tags/R/1.htm" target="_blank">R</a><a
                href="/tags/S/1.htm" target="_blank">S</a><a href="/tags/T/1.htm" target="_blank">T</a><a href="/tags/U/1.htm" target="_blank">U</a><a
                href="/tags/V/1.htm" target="_blank">V</a><a href="/tags/W/1.htm" target="_blank">W</a><a href="/tags/X/1.htm" target="_blank">X</a><a
                href="/tags/Y/1.htm" target="_blank">Y</a><a href="/tags/Z/1.htm" target="_blank">Z</a><a href="/tags/0/1.htm" target="_blank">其他</a>
        </div>
    </div>
</div>
<footer id="footer" class="mb30 mt30">
    <div class="container">
        <div class="footBglm">
            <a target="_blank" href="/">首页</a> -
            <a target="_blank" href="/custom/about.htm">关于我们</a> -
            <a target="_blank" href="/search/Java/1.htm">站内搜索</a> -
            <a target="_blank" href="/sitemap.txt">Sitemap</a> -
            <a target="_blank" href="/custom/delete.htm">侵权投诉</a>
        </div>
        <div class="copyright">版权所有 IT知识库 CopyRight © 2000-2050 E-COM-NET.COM , All Rights Reserved.
<!--            <a href="https://beian.miit.gov.cn/" rel="nofollow" target="_blank">京ICP备09083238号</a><br>-->
        </div>
    </div>
</footer>
<!-- 代码高亮 -->
<script type="text/javascript" src="/static/syntaxhighlighter/scripts/shCore.js"></script>
<script type="text/javascript" src="/static/syntaxhighlighter/scripts/shLegacy.js"></script>
<script type="text/javascript" src="/static/syntaxhighlighter/scripts/shAutoloader.js"></script>
<link type="text/css" rel="stylesheet" href="/static/syntaxhighlighter/styles/shCoreDefault.css"/>
<script type="text/javascript" src="/static/syntaxhighlighter/src/my_start_1.js"></script>





</body>

</html>