10-ES6-Set和Map数据结构

Set数据结构
1-1、ES6提供了新的数据结构—Set。它类似于数组,但是成员都是唯一的,没有重复;
Set本身是一个构造函数,用来生成Set数据结构。

  const s = new Set();
  [ 2, 2, 5, 4, 5, 2, 2 ].forEach( item => s.add( item ) );

  for( let item of s ){
    console.log( i ); // 2 5 4
  };

1-2、Set函数可以接受一个数组(或者具有iterable接口的其他数据结构)作为参数,来初始化;

  // 例1
  const set = new Set( [ 1, 2, 3, 4 ] );  
  [ ...set ];      		   // [ 1, 2, 3, 4 ]    【接受数组为参数】
  
  // 例2
  const items = new Set([ 1, 2, 3, 4, 5, 5, 5]);
  console.log( items.size );  // 5  

  // 例3
  function getDivs(){
return [ ...document.querySelectorAll( 'div' ) ];
  }
  const set = new Set( getDivs() );
  console.log( set.size );          // 10   【接受类似数组的对象作为参数】

1-3、Set加入值时不会发生类型转换,所以5和’5’是两个不同的值;Set内部判断两个值是 否相同类似于精确相等运算符(===),主要 的区别是【NaN等于自身】,精确相等运算符认为NaN不等于自身;

  let set = new Set();
  let a = NaN;
  let b = NaN;
  set.add( a );
  set.add( b );
  console.log( set );  // Set { NaN }

1-4、Set中两个对象是不相等;

  let set = new Set();
  let obj1 = {};
  let obj2 = {};
  set.add( obj1 );
  set.add( obj2 );
  console.log( set.size );   // 2

2-1、Set实例的属性和方法

  Set.property.constructor: 构造函数,默认是Set函数;
  Set.property.size: 返回Set实例的成员总数;

2-2、Set的操作方法

  add(): 添加某个值,返回Set解构本身;
     let set = new Set();
     set.add( 1 ).add( 2 );
     console.log( set.size );   // 2

  delete():删除某个值,返回一个布尔值,表示删除是否成功;
     let set = new Set();
 	 set.add(1).delete(1);    // true

  has():返回一个布尔值,表示参数是否为Set成员;
     let set = new Set();
     set.add( 1 ).has( 1 );    // true 

  clear():清除所有成员;
     let set = new Set();
     set.add( 1 ).clear();     // {}

2-3、对比Object结构和Set结构的写法的不同之处;

  // 对象的写法
  const obj = { 'width': 10 };
  if( obj[ someName ] ){ ...};

  // Set的写法
  const set = new Set();
  set.add( 'widith' );
  if( set.has( someName ) ){ ...};

2-4、Array.from()方法可以将Set解构转为数组;

  const items = new Set( [ 1, 2, 3, 4, 5 ] );
  const array = Array.from( items );
  // 数组去重
  let arr = [ 1, 2, 2, 1, 3, 3 ];
  function dedupe( arr ){
return Array.from( new Set( arr ) );
  };
  dedupe( arr );    // [ 1, 2, 3 ]

2-5、Set结构的实例有4个遍历方法,可用于遍历成员;

  keys()、values()、entries()返回的都是遍历对象,
  由于Set结构没有键名,只有键值,所以keys()和values()行为完全一致;

 【keys()】: 返回键名的遍历器
  let set = new Set([1,2,3]);
  for( let item in set.keys() ){
	console.log( item ); // 1、2、3
  };

 【values()】: 返回键值的遍历器
  let set = new Set([1,2,3]);
  for( let item of set.values() ){
	console.log( item ); // 1、2、3
  };
  

 【entries()】: 返回键值的遍历器,同时包括键名和键值
  let set = new Set([1,2,3]);
  for( let item in set.entries() ){
	console.log( item ); // ["1","1"]、["2","2"]、["3","3"]
  };
  

  forEach(): 用于对每个成员执行某种操作,没有返回值; 第一个参数是处理函数;第二个参数表示绑定的this对象;
  
  let set = new Set( [ 1, 2, 3 ] );
  set.forEach( ( value, key ) => console.log( value * 2 ) );   // 2 4 6

2-6、遍历的应用 扩展运算符( …)内部使用 for…of循环,也可以用于Set结构;

  let set = new Set( [ 'red', 'blue', 'pink' ] );
  let arr = [ ...set ];
  console.log( arr );   // [ 'red', 'blue', 'pink' ]

2-7、扩展运算符和Set结构相结合就可以去除数组的重复成员

  let arr = [ 2, 2, 2, 3, 3, 3, 4, 4, 5, 5 ];
  let cleatRepeat = [ ...new Set( arr ) ];
  console.log( cleatRepeat );

2-8、遍历操作中同步改变原来的Set结构, 一种是利用原Set结构映射出一个新的结构,然后赋值给原来的Set结构;一种是利用Array.from()方法;

// 重新赋值
let set = new Set( [ 1, 2, 3 ] );
set = new Set( [ ...set ].map( val => val * 2 ) );
console.log( set );    	// 2 4 6

    // Array.from();
let set = new Set( [ 1, 2, 3 ] );
set = new Set( Array.from( set, val => val * 2 ) );
console.log( set );  	// 2 4 6

Map数据结构
1-1、概述:Map数据结构。它类似于对象,也是键值对的集合,但是"键"的范围不限于字符串, 各种类型的值(包括对象)都可以当做键。也就是说,Object结构提供了"字符串-值"的对应 Map结构提供了"【值–值】"的对应,是一种更完善的Hash结构实现;

   const map = new Map();
   const obj = { p: 'hello' };
   map.set( obj, 'content' );
   console.log( map );                // key: {p: "1"}   value: "content"
   console.log( map.get( obj ) );     // 'content'
   console.log( map.has( obj ) );     // true
   console.log( map.delete( obj ) );  // true
   console.log( map.has( obj ) );     // false

1-2、作为构造函数,Map也可以接受一个数组作为参数。该数组的成员是一个个表示键值的数组;不仅是数组,任何具有Iterator接口且每个成员都是一个双元素的数据结构都可以当做Map构造函数的参数。也就是,Set和Map都可以用来生成新的Map;

  const map = new Map( [ [ 'name': zhang, 'title': 'hello' ] ] );
  map.size;  // 2
  map.has( 'name' ); // true
  map.get( 'name' ); // zhang

1-3、如果同一个键多次赋值,后面的值会覆盖前面的值

  const map = new Map();
  map.set( 1, 'a' ).set( 1, 'b' );
  console.log( map.get( 1 ) ); // b

1-4、如果读取一个位置的键,则返回undefined

  new Map().get( 'csdf' );  // undefined

1-5、只用对【同一个对象的引用】,Map结构才将其视为同一个键!!!

  const map = new Map();
  map.set(['a'],555);
  map.get(['a']);     // undefined    两个['a']内存地址不一样,取不到想要的值

1-6、Map的键实际上是和内存地址绑定的,只要内存地址不一样,就视为两个键 如果Map的键是一个简单类型的值(数值、字符串、布尔值),则只要两个值严格相等,Map就将其视为一个值,包括0和-0,另外,虽然NaN还不严格等于自身,但Map将其视为同一个键

  let map = new Map();
  map.set( -0, 123 );
  map.get( +0 );          // 123

  map.set( true, 1 );
  map.set( 'true', 1 );
  map.get( true );        // 1

  map.set( undefined, 1 );
  map.set( null, 2 );
  map.get( undefined );   // 1

  map.set( NaN,123 );   
  map.get( NaN );         // 123	

2-1、Map属性
size属性: 返回Map结构的成员总数

  const map = new Map();
  map.set( 'foo', true ).set( 'bar', false );
  console.log( map.size ); // 2

2-2、Map方法

  set( key, value ):设置key所对应的键值,然后返回整个Map结构
  get( key ): 获取key对应的键值,如果找不到key,则返回undefined
  has( key ): 返回一个布尔值,表示某个键是否在Map数据结构中
  delete( key ):删除某个键,返回true;如果删除失败,则返回false
  clear(): 清除所有成员    

2-3、遍历方法
keys(): 返回键名的遍历器

          const map = new Map([['foo','no'],['bar','yes']]);
          for( let key of map.keys() ){ console.log( key ) };   // "foo"、  "bar"
          
  values(): 返回键值得遍历器
          const map = new Map([['foo','no'],['bar','yes']]);
          for( let key of map.values() ){ console.log( key ) };   // "no"、  "yes"

  entries(): 返回所有成员的遍历器
          const map = new Map([['foo','no'],['bar','yes']]);
          for( let item of map.entries() ){ console.log( item[0], item[1] ) };   // "foo" "no" 、 "bar" "yes"

  forEach(): 遍历Map的所有成员,与数组的forEach()方法类似,也可以实现遍历
             此方法接受第二个参数,用于绑定this;
             
	 // this绑定
       const reporter = {
	   		report: function( key, value ){
              	cosole.log( key, value );
        	}
	 };
	 
	 map.forEach( function( value, key, map ){
           this.rep( key, value );
	 }, reporter );

2-4、Map转数组,使用扩展运算符

  const myMap = new Map();
  myMap.set( true, 7 ).set( { foo:3 },[ 'abc' ] );    // [[true,7],[{foo:3},['abc']]]

2-5、数组转Map,将数组传入Map构造函数可以转为Map

  new Map( [ [ true, 7], [{a:'1'},'abc'] ] );         // true => 7    {a:'1'} => 'abc'

2-6、Map转对象,Map所有【键】都是字符串,则可以转为对象

  function strMapToObj( arg ){
  	let obj = Object.create( null );
	for( let [key,vlaue] of arg ){
  		obj[key] = value;
	}
	return obj;
  };
  
  const myMap = new Map().set('yes',true).set('no',false);
  strMapToObj(myMap);  // { yes: true, no: false }

2-7、对象转Map

  function objToStrMap( obj ){
	let strMap = new Map();
    for( let key of obj.keys() ){
  		serMap.set( key, obj[ key ] );
    }
  };
  
  const myMap = new Map().set('yes',true).set('no',false);
  objToStrMap(myMap);  // { yes: true, no: false }

2-8、Map转JSON分两种情况:一种是Map的键都是字符串; 一种是Map的键是非字符串,可以选择转为数组JSON

  // 键都是字符串
  function strMapToObject( map ){
	let obj = Object.create( null );
	for( let [ key, value ] of map ){
	  obj[ key ] = value;
  	}
	return obj;
  };


  function strMapJson( map ){
    return JSON.stringify( strMapToObject( map ) );
  };
  let myMap = new Map().set( 'yes', true ).set( 'no', false );
  console.log( strMapJson( myMap ) ); // {"yes":true,"no":false}


  // 转为数组JSON
  function mapToArrayJson( map ){
	return JSON.stringify( [ ...map ] );
  };
  let map = new Map().set( true, 7 ).set( {foo:3},['abc'] );
  mapToArrayJson(map);

2-9、JSON转Map,分两种情况

  // 键名都是字符串
  function jsonToStrMap(jsonStr){
   	return objToStrMap( JSON.parse( jsonStr ) );
  };
  console.log(jsonToStrMap( '{ "yes": true, "no": false }'));

  function objToStrMap( obj ){
	let setMap = new Map();
    for( let key of Object.keys( obj ) ){
      setMap.set( key, obj[key] );
    }
    return setMap;
  };

  // JSON是数组
  function jsonToMap( jsonstr ){
	return new Map( JSON.parse( jsonstr ) );
  };
  jsonToMap( '[[true,7],[{foo:3},['abc']]]' )
  // Map { true => 7, Object { foo: 3 } => [ 'abc' ] }


  未完待续...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值