前端性能优化: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/1835509897106649088.htm"
                           title="Long类型前后端数据不一致" target="_blank">Long类型前后端数据不一致</a>
                        <span class="text-muted">igotyback</span>
<a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a>
                        <div>响应给前端的数据浏览器控制台中response中看到的Long类型的数据是正常的到前端数据不一致前后端数据类型不匹配是一个常见问题,尤其是当后端使用Java的Long类型(64位)与前端JavaScript的Number类型(最大安全整数为2^53-1,即16位)进行数据交互时,很容易出现精度丢失的问题。这是因为JavaScript中的Number类型无法安全地表示超过16位的整数。为了解决这个问</div>
                    </li>
                    <li><a href="/article/1835498925755297792.htm"
                           title="DIV+CSS+JavaScript技术制作网页(旅游主题网页设计与制作)云南大理" target="_blank">DIV+CSS+JavaScript技术制作网页(旅游主题网页设计与制作)云南大理</a>
                        <span class="text-muted">STU学生网页设计</span>
<a class="tag" taget="_blank" href="/search/%E7%BD%91%E9%A1%B5%E8%AE%BE%E8%AE%A1/1.htm">网页设计</a><a class="tag" taget="_blank" href="/search/%E6%9C%9F%E6%9C%AB%E7%BD%91%E9%A1%B5%E4%BD%9C%E4%B8%9A/1.htm">期末网页作业</a><a class="tag" taget="_blank" href="/search/html%E9%9D%99%E6%80%81%E7%BD%91%E9%A1%B5/1.htm">html静态网页</a><a class="tag" taget="_blank" href="/search/html5%E6%9C%9F%E6%9C%AB%E5%A4%A7%E4%BD%9C%E4%B8%9A/1.htm">html5期末大作业</a><a class="tag" taget="_blank" href="/search/%E7%BD%91%E9%A1%B5%E8%AE%BE%E8%AE%A1/1.htm">网页设计</a><a class="tag" taget="_blank" href="/search/web%E5%A4%A7%E4%BD%9C%E4%B8%9A/1.htm">web大作业</a>
                        <div>️精彩专栏推荐作者主页:【进入主页—获取更多源码】web前端期末大作业:【HTML5网页期末作业(1000套)】程序员有趣的告白方式:【HTML七夕情人节表白网页制作(110套)】文章目录二、网站介绍三、网站效果▶️1.视频演示2.图片演示四、网站代码HTML结构代码CSS样式代码五、更多源码二、网站介绍网站布局方面:计划采用目前主流的、能兼容各大主流浏览器、显示效果稳定的浮动网页布局结构。网站程</div>
                    </li>
                    <li><a href="/article/1835497792265613312.htm"
                           title="【加密社】Solidity 中的事件机制及其应用" target="_blank">【加密社】Solidity 中的事件机制及其应用</a>
                        <span class="text-muted">加密社</span>
<a class="tag" taget="_blank" href="/search/%E9%97%B2%E4%BE%83/1.htm">闲侃</a><a class="tag" taget="_blank" href="/search/%E5%8C%BA%E5%9D%97%E9%93%BE/1.htm">区块链</a><a class="tag" taget="_blank" href="/search/%E6%99%BA%E8%83%BD%E5%90%88%E7%BA%A6/1.htm">智能合约</a><a class="tag" taget="_blank" href="/search/%E5%8C%BA%E5%9D%97%E9%93%BE/1.htm">区块链</a>
                        <div>加密社引言在Solidity合约开发过程中,事件(Events)是一种非常重要的机制。它们不仅能够让开发者记录智能合约的重要状态变更,还能够让外部系统(如前端应用)监听这些状态的变化。本文将详细介绍Solidity中的事件机制以及如何利用不同的手段来触发、监听和获取这些事件。事件存储的地方当我们在Solidity合约中使用emit关键字触发事件时,该事件会被记录在区块链的交易收据中。具体而言,事件</div>
                    </li>
                    <li><a href="/article/1835496149843275776.htm"
                           title="关于城市旅游的HTML网页设计——(旅游风景云南 5页)HTML+CSS+JavaScript" target="_blank">关于城市旅游的HTML网页设计——(旅游风景云南 5页)HTML+CSS+JavaScript</a>
                        <span class="text-muted">二挡起步</span>
<a class="tag" taget="_blank" href="/search/web%E5%89%8D%E7%AB%AF%E6%9C%9F%E6%9C%AB%E5%A4%A7%E4%BD%9C%E4%B8%9A/1.htm">web前端期末大作业</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/html/1.htm">html</a><a class="tag" taget="_blank" href="/search/css/1.htm">css</a><a class="tag" taget="_blank" href="/search/%E6%97%85%E6%B8%B8/1.htm">旅游</a><a class="tag" taget="_blank" href="/search/%E9%A3%8E%E6%99%AF/1.htm">风景</a>
                        <div>⛵源码获取文末联系✈Web前端开发技术描述网页设计题材,DIV+CSS布局制作,HTML+CSS网页设计期末课程大作业|游景点介绍|旅游风景区|家乡介绍|等网站的设计与制作|HTML期末大学生网页设计作业,Web大学生网页HTML:结构CSS:样式在操作方面上运用了html5和css3,采用了div+css结构、表单、超链接、浮动、绝对定位、相对定位、字体样式、引用视频等基础知识JavaScrip</div>
                    </li>
                    <li><a href="/article/1835496148601761792.htm"
                           title="HTML网页设计制作大作业(div+css) 云南我的家乡旅游景点 带文字滚动" target="_blank">HTML网页设计制作大作业(div+css) 云南我的家乡旅游景点 带文字滚动</a>
                        <span class="text-muted">二挡起步</span>
<a class="tag" taget="_blank" href="/search/web%E5%89%8D%E7%AB%AF%E6%9C%9F%E6%9C%AB%E5%A4%A7%E4%BD%9C%E4%B8%9A/1.htm">web前端期末大作业</a><a class="tag" taget="_blank" href="/search/web%E8%AE%BE%E8%AE%A1%E7%BD%91%E9%A1%B5%E8%A7%84%E5%88%92%E4%B8%8E%E8%AE%BE%E8%AE%A1/1.htm">web设计网页规划与设计</a><a class="tag" taget="_blank" href="/search/html/1.htm">html</a><a class="tag" taget="_blank" href="/search/css/1.htm">css</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/dreamweaver/1.htm">dreamweaver</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a>
                        <div>Web前端开发技术描述网页设计题材,DIV+CSS布局制作,HTML+CSS网页设计期末课程大作业游景点介绍|旅游风景区|家乡介绍|等网站的设计与制作HTML期末大学生网页设计作业HTML:结构CSS:样式在操作方面上运用了html5和css3,采用了div+css结构、表单、超链接、浮动、绝对定位、相对定位、字体样式、引用视频等基础知识JavaScript:做与用户的交互行为文章目录前端学习路线</div>
                    </li>
                    <li><a href="/article/1835492740536823808.htm"
                           title="node.js学习" target="_blank">node.js学习</a>
                        <span class="text-muted">小猿L</span>
<a class="tag" taget="_blank" href="/search/node.js/1.htm">node.js</a><a class="tag" taget="_blank" href="/search/node.js/1.htm">node.js</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a><a class="tag" taget="_blank" href="/search/vim/1.htm">vim</a>
                        <div>node.js学习实操及笔记温故node.js,node.js学习实操过程及笔记~node.js学习视频node.js官网node.js中文网实操笔记githubcsdn笔记为什么学node.js可以让别人访问我们编写的网页为后续的框架学习打下基础,三大框架vuereactangular离不开node.jsnode.js是什么官网:node.js是一个开源的、跨平台的运行JavaScript的运行</div>
                    </li>
                    <li><a href="/article/1835448619277316096.htm"
                           title="Android应用性能优化" target="_blank">Android应用性能优化</a>
                        <span class="text-muted">轻口味</span>
<a class="tag" taget="_blank" href="/search/Android/1.htm">Android</a>
                        <div>Android手机由于其本身的后台机制和硬件特点,性能上一直被诟病,所以软件开发者对软件本身的性能优化就显得尤为重要;本文将对Android开发过程中性能优化的各个方面做一个回顾与总结。Cache优化ListView缓存:ListView中有一个回收器,Item滑出界面的时候View会回收到这里,需要显示新的Item的时候,就尽量重用回收器里面的View;每次在getView函数中inflate新</div>
                    </li>
                    <li><a href="/article/1835448238103162880.htm"
                           title="springboot+vue项目实战一-创建SpringBoot简单项目" target="_blank">springboot+vue项目实战一-创建SpringBoot简单项目</a>
                        <span class="text-muted">苹果酱0567</span>
<a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95%E9%A2%98%E6%B1%87%E6%80%BB%E4%B8%8E%E8%A7%A3%E6%9E%90/1.htm">面试题汇总与解析</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/%E5%90%8E%E7%AB%AF/1.htm">后端</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E4%B8%AD%E9%97%B4%E4%BB%B6/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>这段时间抽空给女朋友搭建一个个人博客,想着记录一下建站的过程,就当做笔记吧。虽然复制zjblog只要一个小时就可以搞定一个网站,或者用cms系统,三四个小时就可以做出一个前后台都有的网站,而且想做成啥样也都行。但是就是要从新做,自己做的意义不一样,更何况,俺就是专门干这个的,嘿嘿嘿要做一个网站,而且从零开始,首先呢就是技术选型了,经过一番思量决定选择-SpringBoot做后端,前端使用Vue做一</div>
                    </li>
                    <li><a href="/article/1835448239864770560.htm"
                           title="JavaScript 中,深拷贝(Deep Copy)和浅拷贝(Shallow Copy)" target="_blank">JavaScript 中,深拷贝(Deep Copy)和浅拷贝(Shallow Copy)</a>
                        <span class="text-muted">跳房子的前端</span>
<a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E9%9D%A2%E8%AF%95/1.htm">前端面试</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中,深拷贝(DeepCopy)和浅拷贝(ShallowCopy)是用于复制对象或数组的两种不同方法。了解它们的区别和应用场景对于避免潜在的bugs和高效地处理数据非常重要。以下是对深拷贝和浅拷贝的详细解释,包括它们的概念、用途、优缺点以及实现方式。1.浅拷贝(ShallowCopy)概念定义:浅拷贝是指创建一个新的对象或数组,其中包含了原对象或数组的基本数据类型的值和对引用数</div>
                    </li>
                    <li><a href="/article/1835437775344726016.htm"
                           title="博客网站制作教程" target="_blank">博客网站制作教程</a>
                        <span class="text-muted">2401_85194651</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/maven/1.htm">maven</a>
                        <div>首先就是技术框架:后端:Java+SpringBoot数据库:MySQL前端:Vue.js数据库连接:JPA(JavaPersistenceAPI)1.项目结构blog-app/├──backend/│├──src/main/java/com/example/blogapp/││├──BlogApplication.java││├──config/│││└──DatabaseConfig.java</div>
                    </li>
                    <li><a href="/article/1835432358141063168.htm"
                           title="深入浅出 -- 系统架构之负载均衡Nginx的性能优化" target="_blank">深入浅出 -- 系统架构之负载均衡Nginx的性能优化</a>
                        <span class="text-muted">xiaoli8748_软件开发</span>
<a class="tag" taget="_blank" href="/search/%E7%B3%BB%E7%BB%9F%E6%9E%B6%E6%9E%84/1.htm">系统架构</a><a class="tag" taget="_blank" href="/search/%E7%B3%BB%E7%BB%9F%E6%9E%B6%E6%9E%84/1.htm">系统架构</a><a class="tag" taget="_blank" href="/search/%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1/1.htm">负载均衡</a><a class="tag" taget="_blank" href="/search/nginx/1.htm">nginx</a>
                        <div>一、Nginx性能优化到这里文章的篇幅较长了,最后再来聊一下关于Nginx的性能优化,主要就简单说说收益最高的几个优化项,在这块就不再展开叙述了,毕竟影响性能都有多方面原因导致的,比如网络、服务器硬件、操作系统、后端服务、程序自身、数据库服务等,对于性能调优比较感兴趣的可以参考之前《JVM性能调优》中的调优思想。优化一:打开长连接配置通常Nginx作为代理服务,负责分发客户端的请求,那么建议开启H</div>
                    </li>
                    <li><a href="/article/1835428948339683328.htm"
                           title="JavaScript `Map` 和 `WeakMap`详细解释" target="_blank">JavaScript `Map` 和 `WeakMap`详细解释</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%8E%9F%E7%94%9F%E6%96%B9%E6%B3%95/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>在JavaScript中,Map和WeakMap都是用于存储键值对的数据结构,但它们有一些关键的不同之处。MapMap是一种可以存储任意类型的键值对的集合。它保持了键值对的插入顺序,并且可以通过键快速查找对应的值。Map提供了一些非常有用的方法和属性来操作这些数据对:set(key,value):将一个键值对添加到Map中。如果键已经存在,则更新其对应的值。get(key):获取指定键的值。如果键</div>
                    </li>
                    <li><a href="/article/1835428317084348416.htm"
                           title="最简单将静态网页挂载到服务器上(不用nginx)" target="_blank">最简单将静态网页挂载到服务器上(不用nginx)</a>
                        <span class="text-muted">全能全知者</span>
<a class="tag" taget="_blank" href="/search/%E6%9C%8D%E5%8A%A1%E5%99%A8/1.htm">服务器</a><a class="tag" taget="_blank" href="/search/nginx/1.htm">nginx</a><a class="tag" taget="_blank" href="/search/%E8%BF%90%E7%BB%B4/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/html/1.htm">html</a><a class="tag" taget="_blank" href="/search/%E7%AC%94%E8%AE%B0/1.htm">笔记</a>
                        <div>最简单将静态网页挂载到服务器上(不用nginx)如果随便弄个静态网页挂在服务器都要用nignx就太麻烦了,所以直接使用Apache来搭建一些简单前端静态网页会相对方便很多检查Web服务器服务状态:sudosystemctlstatushttpd#ApacheWeb服务器如果发现没有安装web服务器:安装Apache:sudoyuminstallhttpd启动Apache:sudosystemctl</div>
                    </li>
                    <li><a href="/article/1835427057752961024.htm"
                           title="补充元象二面" target="_blank">补充元象二面</a>
                        <span class="text-muted">Redstone Monstrosity</span>
<a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95/1.htm">面试</a>
                        <div>1.请尽可能详细地说明,防抖和节流的区别,应用场景?你的回答中不要写出示例代码。防抖(Debounce)和节流(Throttle)是两种常用的前端性能优化技术,它们的主要区别在于如何处理高频事件的触发。以下是防抖和节流的区别和应用场景的详细说明:防抖和节流的定义防抖:在一段时间内,多次执行变为只执行最后一次。防抖的原理是,当事件被触发后,设置一个延迟定时器。如果在这个延迟时间内事件再次被触发,则重</div>
                    </li>
                    <li><a href="/article/1835421888088731648.htm"
                           title="MyBatis 详解" target="_blank">MyBatis 详解</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/mybatis/1.htm">mybatis</a>
                        <div>目录目录一、MyBatis是什么二、为什么使用MyBatis(一)灵活性高(二)性能优化(三)易于维护三、怎么用MyBatis(一)添加依赖(二)配置MyBatis(三)创建实体类和接口(四)使用MyBatis一、MyBatis是什么MyBatis是一个优秀的持久层框架,它支持自定义SQL、存储过程以及高级映射。MyBatis免除了几乎所有的JDBC代码以及设置参数和获取结果集的工作。它可以通过简</div>
                    </li>
                    <li><a href="/article/1835420753252675584.htm"
                           title="微信小程序开发注意事项" target="_blank">微信小程序开发注意事项</a>
                        <span class="text-muted">jun778895</span>
<a class="tag" taget="_blank" href="/search/%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F/1.htm">微信小程序</a><a class="tag" taget="_blank" href="/search/%E5%B0%8F%E7%A8%8B%E5%BA%8F/1.htm">小程序</a>
                        <div>微信小程序开发是一个融合了前端开发、用户体验设计、后端服务(可选)以及微信小程序平台特性的综合性项目。这里,我将详细介绍一个典型的小程序开发项目的全过程,包括项目规划、设计、开发、测试及部署上线等各个环节,并尽量使内容达到或超过2000字的要求。一、项目规划1.1项目背景与目标假设我们要开发一个名为“智慧校园助手”的微信小程序,旨在为学生提供一站式校园生活服务,包括课程表查询、图书馆座位预约、食堂</div>
                    </li>
                    <li><a href="/article/1835419870070665216.htm"
                           title="切换淘宝最新npm镜像源是" target="_blank">切换淘宝最新npm镜像源是</a>
                        <span class="text-muted">hai40587</span>
<a class="tag" taget="_blank" href="/search/npm/1.htm">npm</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/node.js/1.htm">node.js</a>
                        <div>切换淘宝最新npm镜像源是一个相对简单的过程,但首先需要明确当前淘宝npm镜像源的状态和最新的镜像地址。由于网络环境和服务更新,镜像源的具体地址可能会发生变化,因此,我将基于当前可获取的信息,提供一个通用的切换步骤,并附上最新的镜像地址(截至回答时)。一、了解npm镜像源npm(NodePackageManager)是JavaScript的包管理器,用于安装、更新和管理项目依赖。由于npm官方仓库</div>
                    </li>
                    <li><a href="/article/1835411044768509952.htm"
                           title="字节二面" target="_blank">字节二面</a>
                        <span class="text-muted">Redstone Monstrosity</span>
<a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95/1.htm">面试</a>
                        <div>1.假设你是正在面试前端开发工程师的候选人,面试官让你详细说出你上一段实习过程的收获和感悟。在上一段实习过程中,我获得了宝贵的实践经验和深刻的行业洞察,以下是我的主要收获和感悟:一、专业技能提升框架应用熟练度:通过实际项目,我深入掌握了React、Vue等前端框架的使用,不仅提升了编码效率,还学会了如何根据项目需求选择合适的框架。问题解决能力:在实习期间,我遇到了许多预料之外的技术难题。通过查阅文</div>
                    </li>
                    <li><a href="/article/1835398064727224320.htm"
                           title="前端代码上传文件" target="_blank">前端代码上传文件</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/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>
                        <div>点击上传文件import{ElNotification}from'element-plus'import{API_CONFIG}from'../config/index.js'import{UploadFilled}from'@element-plus/icons-vue'import{reactive}from'vue'import{BASE_URL}from'../config/index'i</div>
                    </li>
                    <li><a href="/article/1835385458356482048.htm"
                           title="uniapp实现动态标记效果详细步骤【前端开发】" target="_blank">uniapp实现动态标记效果详细步骤【前端开发】</a>
                        <span class="text-muted">2401_85123349</span>
<a class="tag" taget="_blank" href="/search/uni-app/1.htm">uni-app</a>
                        <div>第二个点在于实现将已经被用户标记的内容在下一次获取后刷新它的状态为已标记。这是什么意思呢?比如说上面gif图中的这些人物对象,有一些已被该用户添加为关心,那么当用户下一次进入该页面时,这些已经被添加关心的对象需要以“红心”状态显现出来。这个点的难度还不算大,只需要在每一次获取后端的内容后对标记对象进行状态更新即可。II.动态标记效果实现思路和步骤首先,整体的思路是利用动态类名对不同的元素进行选择。</div>
                    </li>
                    <li><a href="/article/1835383919906746368.htm"
                           title="高性能javascript--算法和流程控制" target="_blank">高性能javascript--算法和流程控制</a>
                        <span class="text-muted">海淀萌狗</span>

                        <div>-for,while和do-while性能相当-避免使用for-in循环,==除非遍历一个属性量未知的对象==es5:for-in遍历的对象便不局限于数组,还可以遍历对象。原因:for-in每次迭代操作会同时搜索实例或者原型属性,for-in循环的每次迭代都会产生更多开销,因此要比其他循环类型慢,一般速度为其他类型循环的1/7。因此,除非明确需要迭代一个属性数量未知的对象,否则应避免使用for-i</div>
                    </li>
                    <li><a href="/article/1835373236217540608.htm"
                           title="360前端星计划-动画可以这么玩" target="_blank">360前端星计划-动画可以这么玩</a>
                        <span class="text-muted">马小蜗</span>

                        <div>动画的基本原理定时器改变对象的属性根据新的属性重新渲染动画functionupdate(context){//更新属性}constticker=newTicker();ticker.tick(update,context);动画的种类1、JavaScript动画操作DOMCanvas2、CSS动画transitionanimation3、SVG动画SMILJS动画的优缺点优点:灵活度、可控性、性能</div>
                    </li>
                    <li><a href="/article/1835368019430305792.htm"
                           title="Vue + Express实现一个表单提交" target="_blank">Vue + Express实现一个表单提交</a>
                        <span class="text-muted">九旬大爷的梦</span>

                        <div>最近在折腾一个cms系统,用的vue+express,但是就一个表单提交就弄了好久,记录一下。环境:Node10+前端:Vue服务端:Express依赖包:vueexpressaxiosexpress-formidableelement-ui(可选)前言:axiosget请求参数是:paramsaxiospost请求参数是:dataexpressget接受参数是req.queryexpresspo</div>
                    </li>
                    <li><a href="/article/1835362892480868352.htm"
                           title="Rust是否会取代C/C++?Rust与C/C++的较量" target="_blank">Rust是否会取代C/C++?Rust与C/C++的较量</a>
                        <span class="text-muted">AI与编程之窗</span>
<a class="tag" taget="_blank" href="/search/%E6%BA%90%E7%A0%81%E7%BC%96%E8%AF%91%E4%B8%8E%E5%BC%80%E5%8F%91/1.htm">源码编译与开发</a><a class="tag" taget="_blank" href="/search/rust/1.htm">rust</a><a class="tag" taget="_blank" href="/search/c%E8%AF%AD%E8%A8%80/1.htm">c语言</a><a class="tag" taget="_blank" href="/search/c%2B%2B/1.htm">c++</a><a class="tag" taget="_blank" href="/search/%E5%86%85%E5%AD%98%E5%AE%89%E5%85%A8/1.htm">内存安全</a><a class="tag" taget="_blank" href="/search/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/1.htm">并发编程</a><a class="tag" taget="_blank" href="/search/%E4%BB%A3%E7%A0%81%E5%AE%89%E5%85%A8/1.htm">代码安全</a><a class="tag" taget="_blank" href="/search/%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/1.htm">性能优化</a>
                        <div>目录引言第一部分:Rust语言的优势内存安全性并发性性能社区和生态系统的成长第二部分:C/C++语言的优势和地位历史积淀和成熟度广泛的库和工具支持性能优化和硬件控制丰富的行业应用社区和行业支持第三部分:挑战和阻碍学习曲线现有代码库的迁移成本生态系统和工具链的完善度社区和人才培养行业应用和推广法规和标准化第四部分:未来趋势和可能性行业趋势教育和人才培养兼容和共存行业标准化企业支持和应用开源社区和生态</div>
                    </li>
                    <li><a href="/article/1835360244646113280.htm"
                           title="JavaScript中秋快乐!" target="_blank">JavaScript中秋快乐!</a>
                        <span class="text-muted">Q_w7742</span>
<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>我们来实现一个简单的祝福网页~主要的难度在于使用canvas绘图当点击canvas时候,跳出“中秋节快乐”字样,需要注册鼠标单击事件和计时器。首先定义主要函数:初始化当点击canvas之后转到onCanvasClick函数,绘图生成灯笼。functiononCanvasClick(){//事件处理函数context.clearRect(0,0,canvas1.width,canvas1.heigh</div>
                    </li>
                    <li><a href="/article/1835359727924637696.htm"
                           title="Nginx从入门到实践(三)" target="_blank">Nginx从入门到实践(三)</a>
                        <span class="text-muted">听你讲故事啊</span>

                        <div>动静分离动静分离是将网站静态资源(JavaScript,CSS,img等文件)与后台应用分开部署,提高用户访问静态代码的速度,降低对后台应用访问。动静分离的一种做法是将静态资源部署在nginx上,后台项目部署到应用服务器上,根据一定规则静态资源的请求全部请求nginx服务器,达到动静分离的目标。rewrite规则Rewrite规则常见正则表达式Rewrite主要的功能就是实现URL的重写,Ngin</div>
                    </li>
                    <li><a href="/article/1835354700392787968.htm"
                           title="Nginx的使用场景:构建高效、可扩展的Web架构" target="_blank">Nginx的使用场景:构建高效、可扩展的Web架构</a>
                        <span class="text-muted">张某布响丸辣</span>
<a class="tag" taget="_blank" href="/search/nginx/1.htm">nginx</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E6%9E%B6%E6%9E%84/1.htm">架构</a>
                        <div>Nginx,作为当今最流行的Web服务器和反向代理软件之一,凭借其高性能、稳定性和灵活性,在众多Web项目中扮演着核心角色。无论是个人博客、中小型网站,还是大型企业级应用,Nginx都能提供强大的支持。本文将探讨Nginx的几个主要使用场景,帮助读者理解如何在实际项目中充分利用Nginx的优势。1.静态文件服务对于包含大量静态文件(如HTML、CSS、JavaScript、图片等)的网站,Ngin</div>
                    </li>
                    <li><a href="/article/1835354447627251712.htm"
                           title="前端知识点" target="_blank">前端知识点</a>
                        <span class="text-muted">ZhangTao_zata</span>
<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><a class="tag" taget="_blank" href="/search/css/1.htm">css</a>
                        <div>下面是一个最基本的html代码body{font-family:Arial,sans-serif;margin:20px;}//JavaScriptfunctionthatdisplaysanalertwhencalledfunctionshowMessage(){alert("Hello!Youclickedthebutton.");}MyFirstHTMLPageWelcometoMyPage</div>
                    </li>
                    <li><a href="/article/1835352325032603648.htm"
                           title="第三十一节:Vue路由:前端路由vs后端路由的了解" target="_blank">第三十一节:Vue路由:前端路由vs后端路由的了解</a>
                        <span class="text-muted">曹老师</span>

                        <div>1.认识前端路由和后端路由前端路由相对于后端路由而言的,在理解前端路由之前先对于路由有一个基本的了解路由:简而言之,就是把信息从原地址传输到目的地的活动对于我们来说路由就是:根据不同的url地址展示不同的页面内容1.1后端路由以前咱们接触比较多的后端路由,当改变url地址时,浏览器会向服务器发送请求,服务器根据这个url,返回不同的资源内容后端路由的特点就是前端每次跳转到不同url地址,都会重新访</div>
                    </li>
                    <li><a href="/article/1835350917352878080.htm"
                           title="华雁智科前端面试题" target="_blank">华雁智科前端面试题</a>
                        <span class="text-muted">因为奋斗超太帅啦</span>
<a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E7%AC%94%E8%AF%95%E9%9D%A2%E8%AF%95%E9%97%AE%E9%A2%98%E6%95%B4%E7%90%86/1.htm">前端笔试面试问题整理</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>1.var变量的提升题目:vara=1functionfun(){console.log(b)varb=2}fun()console.log(a)正确输出结果:undefined、1答错了,给一个大嘴巴子,错误答案输出结果为:2,1此题主要考察var定义的变量,作用域提升的问题,相当于varaa=1functionfun(){varbconsole.log(b)b=2}fun()console.l</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>