ES5中数组API(every,some),遍历API(forEach,map),过滤汇总(filter,reduce),bind函数,严格模式-14

2016-09-06-day14


1.ES5中数组API:

1)判断数组中的元素是否符合要求
  • arr.every(): 每个元素是否都符合要求,every()是对数组中每一项运行给定函数,如果该函数对每一项返回true,则返回true。
  • arr.some(): 是否包含符合要求的元素,some()是对数组中每一项运行给定函数,如果该函数对任一项返回true,则返回true。
    如何使用:
arr.every(function(val,idx,arr){
  return 判断条件
});
arr.some(function(val,idx,arr){
  return 判断条件
});

arr.every()例子:检测数组中的所有元素是否都大于 10。

function isBigEnough(val, index, array) {
  return (val>= 10);
}
var passed = [12, 5, 8, 130, 44].every(isBigEnough);
console.log(passed)//false
var passed2 = [12, 54, 18, 130, 44].every(isBigEnough);
console.log(passed2)//true

arr.every()例子:检测数组中的所有元素是否都由奇数组成。

var arr1 = [1, 3, 5, 7, 9];
var arr2 = [2, 4, 6, 8, 10];
var arr3 = [1, , 3, , 5];
//判断哪个数组全由奇数组成:
function isOdd(val) {
  return val % 2 == 1;
}
arr1.some(isOdd) //true
arr2.some(isOdd) //false
arr3.some(isOdd) //true

arr.some()例子:检测在数组中是否有元素大于 10。

function isBiggerThan10(val, index, array) {
  return val> 10;
}

[2, 5, 8, 1, 4].some(isBiggerThan10);  // false
[12, 5, 8, 1, 4].some(isBiggerThan10); // true

arr.some()例子:检测在数组中是否是按升序排列的。

var arr4 = [1, 2, 3, 2, 1];
var arr5 = [5, 4, 3, 2, 1];
var arr6 = [1, 2, 3, 4, 5];
//判断哪个数组是按升序排列的
function isAscending(val, index, arr) {
  //当前元素是否<=下一个元素
  return index < arr.length - 1 ? val <= arr[index + 1] : true;
}
arr4.every(isAscending) //false
arr4.every(isAscending) //false
arr4.every(isAscending) //true

如果Array的原型对象中不包含every和some,那么可以用以下代码实现自定义方法。

//如果Array的原型对象中不包含every
if (Array.prototype.every === undefined) {
  Array.prototype.every =
    function (callback) {
      //遍历当前数组中每个元素
      for (var i = 0; i < this.length; i++) {
        //防止稀疏数组
        //如果i位置不是undefined
        //if(this[i]!==undefined){
        if (i in this) {
          //调用callback函数,传入:当前元素值,当前位置,当前数组 三个参数,将执行结果保存在变量r中
          var r = callback(this[i], i, this);
          if (!r) { //如果r为false
            return false; //返回false
          }
        }
      } //(遍历结束)
      return true; //返回true
    }
}
//如果Array的原型对象中不包含some
if (Array.prototype.some === undefined) {
  //在Array的原型对象中添加some方法,参数为fun函数
  Array.prototype.some = function (fun) {
    //遍历当前数组:
    for (var i = 0; i < this.length; i++) {
      //如果当前元素不是undefined
      if (this[i] !== undefined) {
        //调用fun函数,传入:当前元素值,当前位置,当前数组,返回结果保存在r中
        var r = fun(this[i], i, this)
        //如果r为true,就返回true
        if (r) {
          return true;
        }
      }
    } //(遍历结束)
    return false; //返回false
  }
}
2.遍历API:对数组中每个元素执行相同的操作
  • arr.forEach(): 对原数组中每个元素,直接做相同的操作——直接修改原数组
  • arr.map(): 依次取出原数组中每个元素,执行相同操作后,返回新数组
    如何使用:
   arr.forEach(function(val,index,arr){
      直接修改arr中index位置的当前元素
   });
   arr.map(function(val,index,arr){
      return 一个新值
   });

arr.forEach()例子:对数组中的每一个元素乘以2

var arr=[1,,3,,5];
arr.forEach(function(val,idx,arr){
  arr[idx]=val*2;
});
console.log(arr) //[2, ,6, ,10]

arr.map()例子:对数组中的每一个元素乘以2

var arr_odd=[1,3,5,7,9];
var arr_even=arr_odd.map(function(val){
  return val*2;
});
console.log(arr_odd) //[1,3,5,7,9]
console.log(arr_even) //[2,6,10,14,18]

使用map可以重新格式化数组对象的格式,例子如下:

var kvArray = [{key: 1, value: 10}, 
               {key: 2, value: 20}, 
               {key: 3, value: 30}];

var reformattedArray = kvArray.map(function(obj) { 
   var rObj = {};
   rObj[obj.key] = obj.value;
   return rObj;
});

// reformattedArray 数组为: [{1: 10}, {2: 20}, {3: 30}], 

// kvArray 数组未被修改: 
// [{key: 1, value: 10}, 
//  {key: 2, value: 20}, 
//  {key: 3, value: 30}]

使用map接口数据映射,例子如下:

let r = res.map(item => {
    return {
        title: item.name,
        sex: item.sex === 1? '男':item.sex === 0?'女':'保密',
        age: item.age,
        avatar: item.img
    }
})

利用map方法方便获得对象数组中的特定属性值,例子如下

var users = [
  {name: "张含韵", "email": "zhang@email.com"},
  {name: "江一燕",   "email": "jiang@email.com"},
  {name: "李小璐",  "email": "li@email.com"}
];

var emails = users.map(function (user) { return user.email; });

console.log(emails.join(", ")); // zhang@email.com, jiang@email.com, li@email.com

返回一个数组,数组中元素为原始数组的平方根,例子如下:

var numbers = [4, 9, 16, 25];

function myFunction() {
    x = document.getElementById("demo")
    x.innerHTML = numbers.map(Math.sqrt);
}

如果原型对象中没有forEach和map,那么可以粘贴以下代码来实现功能

//如果Array的原型中没有forEach方法
if(Array.prototype.forEach===undefined){
  //就为Array的原型添加forEach方法,参数定义为callback
  Array.prototype.forEach=
    function(callback){
      //遍历当前数组中每个元素
      for(var i=0;i<this.length;i++){
        //如果当前元素不是undefined
        if(this[i]!==undefined){
          //调用callback,传入当前元素值,当前位置,当前数组作为参数
          callback(this[i],i,this);
        }
      }
    }
}
//如果Array的原型中没有map方法
if(Array.prototype.map===undefined){
  //就为Array的原型添加map方法,参数定义为callback
  Array.prototype.map=
    function(callback){
      //创建一个空数组arr
      var arr=[];
      //遍历原数组中每个元素
      for(var i=0;i<this.length;i++){
        //如果原数组中当前元素不是undefined
        if(this[i]!==undefined){
          //调用callback,传入当前元素值,当前位置,原数组,将结果保存到arr的相同位置
          arr[i]=
            callback(this[i],i,this);
        }
      }//(遍历结束)
      return arr;//返回arr
    }
}
3.过滤和汇总:

arr.filter(): 筛选出原数组中符合条件的元素,返回新数组。
arr.reduce()汇总: 将数组中每个元素统计起来,得出一个结果。
如何使用:

arr.filter(function(val,idx,arr){
  return 判断条件
});

var r=arr.reduce(
   function(prev,val,idx,arr){
     return prev+val;//prev自动接收截止到目前已经统计的临时汇总结果。
   },
   startVal //startVal是开始汇总前的初始值
)

arr.filter()例子:取出数组中是偶数的元素(返回新数组)

var arr=[1,2,3,4,5];
var even=arr.filter(function(val){
  return val%2==0;
});
console.log(arr); //[1,2,3,4,5]
console.log(even); //[2,4]

arr.reduce()例子:计算数组元素总和

var arr=[1,2,3,4,5];
var sum=arr.reduce(function(prev,val){
  return prev+val;
});
console.log(sum);//1+2+3+4+5=15

var start=15;
var arr2=[6,7,8,9,10];
sum2=arr2.reduce(function(prev,val){
  return prev+val;
},start);
console.log(sum2);//15+6+7+8+9+10=55

2. bind函数:基于一个现有函数,创建一个新函数,并永久绑定this为指定对象,同时,还可提前绑定部分参数。

何时使用: 在使用回调函数时,只要希望固定回调函数中的this时。

鄙视题: call apply bind
call和apply: 临时借用构造函数,并临时替换函数中的this为指定对象。
立刻执行函数
调用后,this回复原样
call: 参数单独传入
apply: 参数以数组传入
bind: 创建一个函数,并永久绑定this
不会立刻执行新函数
一旦被bind创建的函数,其中的this,无法再被call/apply替换

<!doctype html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
  </head>
  <body>
    <script>
      //计算器: 计算总工资: 底薪+奖金
      function calc(base,bonus){
        document.write(
          this.name+"的总工资是"+(base+bonus)
          +"<br>"
        );
      }
      var lilei={name:"Li Lei"};
      var hmm={name:"Han Meimei"};
      //lilei临时借用calc
      calc.call(lilei,10000,5000);
      //相当于lilei.calc(10000,5000)
      //hmm临时借用calc
      calc.apply(hmm,[9000,7000]);
      //如果函数类型的原型中没有bind方法 
      if(Function.prototype.bind===undefined){
        //就在函数类型的原型中添加bind方法,定义1个参数obj
        Function.prototype.bind=
          function(obj/*,args1*/){
            var fun=this;//this->原函数对象
            var args1=//将arguments转化为纯正的数组,并选取1位置之后的剩余元素
              Array.prototype.slice.call(
                arguments,1
              );//arguments.slice(1)`
            return function(/*args2*/){//返回新函数:
              var args2=
                Array.prototype.slice.call(
                  arguments
                );//arguments.slice();
              //强行调用原函数,临时替换this为obj
              fun.apply(
                obj,args1.concat(args2)
              );
            }
          }
      }
      //基于calc函数,创建一个新函数,并永久绑定新函数中的this为lilei
      var lilei_calc=calc.bind(lilei,10000);
      //lilei_calc:function(){(闭包:fun->原函数)
        //fun.apply(lilei,arguments);
      //}
      lilei_calc(5000);
      //lilei_calc.call(hmm,9000,7000);
    </script>
  </body>
</html>

执行结果:


3. 严格模式:

如何使用:
在当前范围的开头: "use strice";
写在2个地方:
1. 写在一个函数内部的开头:
仅函数内使用严格模式,函数外依然使用普通模式
2. 写在一个script元素或js文件的开头
整个js文件或script代码段都采用严格模式
1. 旧项目升级,先逐个函数启用严格模式
2. 新项目,开始就使用严格模式

规定:

  1. 将静默失败升级为了错误!
  2. 不允许对未声明的变量赋值!
  3. 尽量少的或不使用arguments及其API
  4. 新增了eval作用域:
    在eval中声明的变量,eval结束后,不能使用。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,245评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,749评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,960评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,575评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,668评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,670评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,664评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,422评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,864评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,178评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,340评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,015评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,646评论 3 323
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,265评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,494评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,261评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,206评论 2 352

推荐阅读更多精彩内容