Set集合,Map集合,Symbol,Promises-1708

2017-08-22-day08

Set 集合:

  • 什么是: 值不允许重复的集合。专门用于按元素值,直接判断集合中是否存在指定元素
  • 何时: 快速去重复(通过元素值,快速判断是否包含元素时)
  • 如何使用:
var set=new Set(凡是可遍历的,都可打散转为Set)
 将set转回数组: var arr=[...set];//散播

下面是一个简单的例子

var arr=[1,2,3,2,1];
var set=new Set(arr);
console.log(set);//将数组转为Set类型
arr=[...set];
console.log(arr);//将Set类型转为数组

以下是一个经典笔试题,数组去重复,且考虑百万数量级的情况下有什么方法效率高,repeat1是最笨的实现方式,indexOf底层是for循环的方式,repeat2是用Set类型来实现的,底层是哈希实现方式,下面用过打印执行时间来观察。在执行函数前加console.time,执行函数后加console.timeEnd可以打印出该程序的执行时间。

for(var i=0,arr=[];i<1000000;i++){
  arr[i]=parseInt(Math.random()*1000+9000)
}

function repeat1(arr){
  var res=[];
  for(var i=0;i<arr.length;i++){
    if(res.indexOf(arr[i])==-1)
      res.push(arr[i]);
  }
  return res;
}
function repeat2(arr){
  var set=new Set(arr);
  return [...set];
}

以下是另一种实现方法,结果巨快的。这是一种最好的数组去重的方法。这种答案最好。

function repeat3(arr){
  var res=[];
  var hash={};
  for(var i=0;i<arr.length;i++){
    if(hash[arr[i]]===undefined){
      hash[arr[i]]=1;
      res.push(arr[i]);
    }
  }
  return res;
}

左1是要被去重的数组,左2是一个哈希数组(也可以理解为对象)它是用来筛选数组的,右1是最终结果,将左1的值在对象的key值中是undefined,那么就给它定义并赋值1,不是1也可以这个随意。只是要让它存在而已。后面的自行理解。


  • Set集合的其他方法:
    1)set.size 获取集合中元素的个数
    2)set.has(value)判断集合中是否包含指定元素
    3)set.add(value)添加元素,如果已经存在,则无效
    4)set.delete(value)删除元素
    5)set.clear()清空集合

Map 集合:

  • 什么是: 一组键值对的集合(实际上就是关联数组或对象的一种封装)
  • 何时: 代替关联数组(对象)使用
    如何:
var hash=new Map(); //相当于新建对象{}
      hash.set(key,value); //相当于给对象赋值hash[key]=value
      var bool=hash.has(key); //相当于判断对象值是否存在hash[key]!==undefined
  • Map集合的其他API
    map.size 获得map中键值对的个数
    map.has(key)查询一个key是否存在
    map.get(key)获得指定键对应的值
    map.set(key,value)添加一个新的键值对,如果key已经存在,则不会重复添加
    map.delete(key)删除指定key对应的键值对
    map.keys()获取map中所有的key的集合
    map.values()获取map中所有的value的集合

将上面百万级别数组去重的问题用map的方式改写一遍,结果如下,速度还可以,和set差不多,但是没有hash快,那个最好。

function repeat3(arr){
  var res=[];
  var hash=new Map();
  for(var i=0;i<arr.length;i++){
    if(!hash.has(arr[i])){
      hash.set(arr[i],1);
      res.push(arr[i]);
    }
  }
  return res;
}

for of : 代替for循环遍历

  • 什么是: 依次获得数组/类数组对象/集合中每个值
  • 何时: 只要不关心位置,只关心每个元素值时
  • 如何:
for(var value of 数组|类数组对象|集合){
        value: 自动获得当前元素值
      }

以下是一个简单的遍历对象数组的例子

let array = [{"a": 1}, {"b": 2}, {"c":3}];
for (let obj of array) {
  console.log(obj);
}

问题:
1). 无法获得位置
2). 必须从头到尾,逐个执行,不能跳跃或遍历部分
3). 只能从头到尾,顺序遍历,不能反向遍历

Symbol类型

  • ES6中,为了获得一个不与对象中现有任何属性冲突的唯一属性,定义了Symbol类型
  • Symbol是第六大原始类型
  • Symbol的值必须通过Symbol函数获的
  • Symbol的值作为属性名时,不能用.访问,只能用[]访问。
    以下是一个例子,点击一下按钮就让小方块右移一段距离,图片正在移动时再点击无效,html中
<button id="btn_right">右移一次</button>
<div id="pop"></div>

css中

div{
  width:100px; 
  height:100px;
  background:red;
  position:fixed;
  top:100px; left:0;
  transition:all 2s linear;
}

js中

function moveRight(elem,dist){
  var left=
    parseFloat(getComputedStyle(elem).left);
  left+=dist;
  elem.style.left=left+"px";
}

var isMoving=Symbol("isMoving");
console.dir(isMoving);
pop[isMoving]=false;
btn_right.onclick=function(){
  if(pop[isMoving]==false){
    pop[isMoving]=true;
    moveRight(pop,100);
    setTimeout(()=>pop[isMoving]=false,2000);
  }
}
pop.isMoving=false;
image.png

****Promises(重点掌握)

  • 什么是: 解决"callback hell"(回调地狱)
  • 为什么: 回调函数,层级很可能很深,可读性极差
  • 何时: 今后,只要多个回调函数,必须保证顺序执行时
    我先写了这样的3个函数,callback指的是回调函数,下一个任务必须要在上一个任务完成之后才可以执行,这种必须得用回调函数来做。如果把callback()直接放在第一个任务中的话,它不会等3秒,而会直接执行,只有放在setTimeOut中才会等3秒再执行。
function conn(callback){
  console.log("连接数据库...");
  //3秒后自动调用callback
  setTimeout(callback,3000);
}
function query(callback){
  console.log("查询数据...");
  setTimeout(callback,5000);
}
function response(callback){
  console.log("返回响应...");
  setTimeout(callback,2000);
}

如何让这3个函数串起来顺序执行呢,执行conn并在它的参数中传一个匿名函数,匿名函数中调用query(),依次类推。只有这样写才会先执行conn,等3秒后执行query,等5秒后执行response,等2秒后打印查询出结果。

//callback hell
conn(function(){
  query(function(){
    response(function(){
      console.log("查询出结果!");
    })
  })
});

但是上面的写法很难看一直往下陷,像一个大坑。称之为回调地狱。

  • 如何使用Promise: 2步:

1). 在前一个函数内

return new Promise((callback)=>{
  ... callback() ...
})

2). 在调用前一个函数时,

前一个函数.then(()=>{ 后一个函数(); })

下面我们将上面的那个例子改为promise的形式,它可以将不确定层级的函数抹平成一级。.then的作用不是调用的意思,它是把后面的参数给Promise对象。这里的callback在后面的介绍中相当于resolve函数。

function conn(){
  console.log("连接数据库...");
  return new Promise((callback)=>{
    setTimeout(callback,3000);
  });
}
function query(){
  console.log("查询数据...");
  return new Promise((callback)=>{
    setTimeout(callback,5000);
  });
}
function response(){
  console.log("返回响应...");
  return new Promise((callback)=>{
    setTimeout(callback,2000);
  })
}

conn()//往下调用的时候是平级的
  .then(()=>query())
  .then(()=>response())
  .then(()=>console.log("查询出结果"))
Promise可以接受2参数来进行错误处理: 分2步

1). 在前一个函数内

 return new Promise(resolve,reject)=>{
       如果没出错,执行resolve
       如果出错,执行reject("错误提示")
 })

2). 在调用前一个函数时,其中.then执行的是resolve的内容,.catch执行的是reject的内容。一旦出错后面调用的函数都不会执行。

前一个函数.then(()=>{ 下一个函数(); }) 
              .catch((err)=>{ 输出err }

将上面的例子模拟出可以出错的样式,用resolve和reject来进行改写,这里在reject中还传了参数以便出错时知道在哪个函数中出错的。

function conn(){
  console.log("连接数据库...");
  return new Promise((resolve,reject)=>{
                    //.then   .catch
    setTimeout(()=>{
      var err=Math.random()<0.3?true:false;
      if(!err)
        resolve();
      else
        reject("连接出错");
    },3000);
  });
}
function query(){
  console.log("查询数据...");
  return new Promise((resolve,reject)=>{
    setTimeout(()=>{
      var err=Math.random()<0.3?true:false;
      if(!err)
        resolve();
      else
        reject("查询出错");
    },5000);
  });
}
function response(){
  console.log("返回响应...");
  return new Promise((resolve,reject)=>{
    setTimeout(()=>{
      var err=Math.random()<0.3?true:false;
      if(!err)
        resolve();
      else
        reject("响应出错");
    },2000);
  })
}
conn()
  .then(()=>query())
  .then(()=>response())
  .then(()=>console.log("查询出结果"))
  .catch((err)=>console.log(err))

很多情况一些框架都支持promise,都不需要开发者去写return promise这段代码,只要会使用.then和。catch的用法即可。

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

推荐阅读更多精彩内容