ECMAScript 5 常用的技巧(一)

结合自己编码遇到的小坑的积累吧。因此下面会有一些个人的见解,参考书籍《JavaScript高级程序设计》(第三版)

尽量不适用 var 声明局部变量

在 esc5 中 var 声明变量是一个万能的方式,往往因为太便利了就会出现一些问题。例如我其实只是想让一个变量在局部作用域中有效果,但是在下面的代码却出现了问题。

// 猜猜下面执行后的结果。

var a = { a: 2 }
var b = { a: 2 }
if (a) {
    a.a = 1;
    var a = new Object();
    a.a = 3;

}

// 如果你讲 if 里的 var 换成 let 会抛出异常,需要将 a.a=1 注销掉才可以。
console.error(a); // 3

function str(b) {
    b.a = 1;
    var b = new Object();
    b.a = 3;
}
str(b)
console.log(b); // 1

for (var i = 0; i < 3; i++) {
    var b = 2
}
console.log(i); // 3
console.log(b); // 2

所以在声明变量的时候最好是用 let 而不是 var 这也是 ECMAScript6 推荐的做法。

Array 数组

其实数组里还是设计到数据结构栈类似的存储结构,对栈的认识 可以参考这个链接

  • array.length :不仅可读,还是可以通过设置长度截取或增加数组的内容。并且会更爱原数组;当然新增数组的内容默认值是 undefined

  • 判断数组

    • 针对一个网页,或者是一个框架环境的情况下,用 instanceof 就可以实现。

      if( value instanceof Array){
        //对数组执行操作
      }
      
      
    • 网页中如果包含多个框架,一个框架的 Array 值传递进入另一个框架做是否数组的判断。用Array.isArray()

      if(Array.isArray( value )){
        // 对数组执行的操作
      }
      
  • 数组排序 sortreserve

    // sort 的排序方式是比较函数通过返回值小于零、大于零、等于零来影响排序结果,减法的操作就可以适用部分情况。
    
    var arr = [2,3,1,3,4,5,1];
    
    var sortArray = arr.sort(
              function (a, b){
                    return b - a;
                  //return a < b ? 1 : -1; 
                    
              }
           );
           // 倒叙排列
           console.error(sortArray);
    
    // 正序排列
    function compare(value1, value2){
              if(value1 < value2){
                  return -1;
              }else if( value1 > value2){
                  return 1;
              }else{
                  return 0;
              }
              
     }
      //var sortArray =arr.sort(compare);
    
           // reserve 的作用就是反转已经排好的顺序。
    
      var reverseSort = sortArray.reverse();
          
      console.log(reverseSort);
    
  • 数组合并 concat

      var color = ['green']; // color 的值不变
    
      var colors = color.concat('yellow', ['blue','red']);
    
    
  • 数组截取 slice

    
    
    // 不会影响原数组
    var colors = ["green", "yellow", "blue", "red"];
    
    colors.slice(1); // ["yellow", "blue", "red"];
    
    // 返回起始位置的值,单不包含结束位置的值;
    colors.slice(1,3); //["yellow", "blue"]
    
  • 数组splice 删除、新增、修改操作

    
    var arr = [1,2,3,4];
    // 删除
    //arr.splice(起始下标, 删除项数)
    arr.splice(0,1);  // 返回删除的项1, 
    arr = [2,3,4];
    
    //替换 or 新增
    //arr.splice(起始下标, 删除项目,替换的值)
    
    arr.splice(0, 0 ,4); // arr = [4, 1, 2, 3, 4]
    
    arr.splice(0, 1, 5); // arr = [5, 2, 3, 4]
    
    
  • 位置方法 indexOf、lastIndexOf

    // 可以接受2个参数, 下标是可选的,如果字符有,下标正确,返回下标值,否则返回 -1
    
    str.indexOf(字符, 下标);
    // 我们一般的书写代码习惯
    let a = "foo";
    if(a.indexOf('a') != -1){
      //...
    }
     // 其实这个代码可以简化下
    if(~a.indexOf(a)){
      // 这样就简化了代码
    }
    这里就必须补充一个知识点了
    ~42 ===> -(42+1) = -43
    所以 ~-1 = 0
    
    
  • 迭代数组,执行一个方法,查看返回值 every、filter、forEach、map、some

  • 迭代数组的每一项 reduce、reduceRight

    var arr = [1,2,3];
    arr.reduce(function(prev, curr, index, array){
      return prev + curr;
    })
    
    // 6
    
    reduce & reduceRight 功能都一致,只是顺序不同。
    

正则

RegExp 每次执行都会创建一个新的构造函数,并且只接收字符串

// exec 返回匹配的第一个值

// test


函数

  • 内部属性 arguments、this、callee

    // 解除递归 函数和函数名的耦合
    function str(num){
      if(num <= 1){
        return 1;
      }else{
        return num + arguments.callee(num -1);
      }
    }
    str(7); //28
    
    
  • apply、call

// 1、apply、和call 相同点:都是指定方法在被调用的作用域
//                 不同点:apply,第二个参数是,方法接收参数用数组传递;call 是直接一个一个书写。

function a(num1, num2){
    return num1 + num2;
}
 function b(num1, num2){
   //return a.apply(this, arguments);
    return a.call(this, num1, num2);
 }
  b(1,2); //3


// 方法内部继承,实例化方法调用。
  function animal(name){
    this.name= name || "animal";
    this.getName = function(name){
      return this.name;
    }
  }

  function dog(name){
     animal.call(this, name);
  }
  var dog1= new dog("旺财");
  console.log(dog1.getName()); // 旺财


  // 实例化方法继承的方式
  function Animal(){
    this.name= "animal";
    this.getName = function(name){
         return this.name;
    }
  }
  function Dog(){
    this.name ='汪汪'
  }
  var dog= new Dog();
  var animal = new Animal();
  console.log(animal.getName.call(dog, ","));

// functionName.apply(作用域, 参数数组)

function sun(num1, num2){

          return num1 - num2;

      }

      function cont(num1, num2){

          return sun.apply(this, [num1,num2]);  // 这两种都是可以的

          //return sun.apply(this, arguments);

      }

      console.log(cont(1,10)); // -9

数字的处理 toFixed / toExponential / toPrecision

//toFixed 
var a =10;
a.toFixed(2); // 10.00;
// 常见问题,如果对数据的精度要求不是很高的情况下,我们解决 0.1+0.2 != 0.3 的情况
Number((0.1+0.2).toFixed(2)) // 0.30

// 采用科学计数法显示
a.toExponential() // "1e+1"

// 会根据传入的参数,自动的用科学计数法,还是正常的显示十进制    
a.toPrecision(1) // 1e+1;

字符方法 charAt、charCodeAt、concat、slice、substr、substring、toLowerCase、toLocaleLowerCase、toUpperCase、toLocaleUpperCase、fromCharCode、split

var str = 'hello world';
// 获取字符串中指定位置的字符
str.charAt(1); //e

// 获取指定位置字符的字符编码
str.charCodeAt(); //101

// 字符连接,当然后面是可以跟多个参数的。其实更多的时候我们是用 + 来实现字符串的链接
str.concat(" and"," you "); //"hello world and you"

//fromCharCode 的作用与 charCodeAt 方法效果是相反的。参数是字符和数字都可以,前提是能转换成整数
Sting.fromCharCode(101); //e  

// split 经常用来将 string 转换成 Array 类型。
let a = "foo";
let b = a.split("");
b// ['f','o','o'];
// 当然如果想对字符串的操作用 Array 的方法其实可以不用将字符串 split 转换
1. 使用call
Array.prototype.join.call(a,"-"); // f-o-o

Array.prototype.map.call(a, (val) => {
    return val.toLocaleUpperCase()
}).join(".")  // F.O.O

replace 方法的使用

//在以前的时候我都是仅仅简单的使用 replace 替换字符,其实我们可以对 ,替换的字符做一些操作

// 可以给符合的字符增加字符并凭借在一起。
var str = "bat, cat, dat";
var word= str.replace(/(.at)/g, "word ($1)");
alert(word);

// 当然第二个参数也可以是一个方法,传入三个值
// match:匹配的字符
// originalText:被替换的字符
// positoin:被替换字符的位置
var word = str.replace(/(.at)/g, function(match, originalText, position){
    switch(match){
        case "bat" :
            return "bb "+position +' '+originalText;
        case "cat" :
            return "cc "+ position+ ' ' +originalText;
        case "dat" :
            return "dd "+ position +' '+ originalText;
    }
})
alert(word); // "bb 0 bat, cc 5 cat, dd 10 dat"


获取匹配参数说明

在数组中比较数字的大小

// 方法一排序 sort
var arr = [1,2,3,4];

var arrsort = arr.sort(function(a, b){
  return b -a ; // return a-b; 升序
})
arrsort[0]; // 4

//方法二: Math.max, Math.min 
//语法: Math.max(num1,num2,num3...);  但是如果我是想比较数组里的值怎么办呢,这时候就可以用到 eval了
var arr = [1,2,3,4];
var arrStr = arr.toString();
eval("Math.max("+ arrstr +")"); // 4

// 方法三,利用 apply 第二参数可以接收数组的特性,然后结合Math.max & Math.min js 提供的 2 个方法
var arr = [1,2,3,4];
function max(arr){
    return Math.max.apply(Math,arr);  
};
max(arr); // 4

// 方法 4 for 循环判断
var arr = [1,2,3,4];
function max(arr){
  var curr = "";
  for(var i in arr){
    if(arr[i] > curr ){
      curr = arr[i]
    }
  }
  return curr;
}
max(arr); // 4

 // 我知道的暂时就这四种,还缺少性能上的比较,后期看到了在更新。



Math 方法

// Math.max(num1, num2, num3 ...) 获取最大值
// Math.min(num1, num2, num3 ...) 获取最小值
// Math.ceil(num) // 执行向上舍入为最接近的整数
// Math.floor(num) // 执行向下舍入最接近的整数
// Math.round(num) // 执行标准的四舍五入,并且四舍五入小数后一位,只保留整数位置,和toFixed不同
// Math.random() //返回一个 0 ~ 1 之间的随机数,不包括 0 和 1


// 生成 0 - 9 的一个随机数
Math.floor(Math.random() * 10);

// 如果你想生成的 2 - 10 的一个随机数, 然后自己看半天蛮麻烦的。其实别人早已经想到方法了

function selectFrom(lowerValue, upperValue){
  var choices = upperValue -  lowerValue;
  return  Math.floor(Math.random() * choices + lowerValue );
}

备注常见的问题

  • 解决 0.1 + 0.2 != 0.3 的情况
// 精度要求不高的情况下
Number((0.1+0.2).toFixed(2)) // 0.3
// 判断一个特定值
Number.EPSILON  // 2.220446049250313e-16
if(a - b< Number.EPSILON){
  return true; // 相等
}
  • 取小数的整数部分
1、~~49.1 // 49
2、~~-49.1 // -49
3、 Number.parseInt(49.1) // 49
  • 在使用 == 判断对象和数字的情况
let d = {
    val: 1
}
console.log(d ==1); // false

let d = {
    val: 1,
    toString: function () {
        return this.val;
     },

}
console.log(d ==1); // false

let d = {
    val: 1,
     toString: function () {
         return this.val;
     },
     valueOf: function () {
         return this.val + 1;
     }
}
console.log(d ==2); // true

// 在使用 == 判断相等的时候,js 会将引用类型数据获取 ToPrimitive 对应的值,会调用 toString 和 ValueOf。
  • js 相等转换类型中的7个坑,真的是天坑。你会意想不到的,因为他们是相等的。
false == "0"; // true -- 晕!
false == 0; // true -- 晕!
false == ""; // true -- 晕!
false == []; // true -- 晕!
"" == 0; // true -- 晕!
"" == []; // true -- 晕!
0 == []; // true -- 晕!
  • js switch 函数中 case 值的运用
var a = "hello world";
var b = 10;
switch (true) {
    case (a || b == 10):
        // 永远执行不到这里
        console.log(123)
        break;
    default:
        console.log("Oops");
}
// 如果细微的更改下
switch (true) {
    case !!(a || b == 10):
        console.log(123)
        break;
    default:
        console.log("Oops");
}
// 这里执行的结果就是 123, 这样书写仅做参考。

备注

  • 所有的对象都有 toLocaleString() 、 toString() 、 valueOf() 方法。可以看到方法执行的内容,不过每个浏览器对这三个方法返回内容和格式会有一定的差异,对调试代码还是很有用的。
  • alert 方法只接收字符串的参数,当传入数组的时候,alert 会执行 toString() 方法,因此显示的结果是数组的字符串并以逗号隔开的形式。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345