1.变量声明--var,const,let

1.1 var - (全局作用域,局部作用域)会有变量提升

//第一个小例子
<script>var num = 123;function fn(){console.log(num);  // undefinedvar num = 46;console.log(num) // 46}fn()
</script>
//为什么第一个输出值会是undefined,而不是123呢?因为这里存在着变量名的提升,其实上述语句相当于:
<script>var num = 123;function fn(){var num;console.log(num);  // undefinednum = 46;console.log(num) // 46}fn()
</script>//第二个小例子
<script>var num = 123;if(true){console.log(num) // 123var num = 456;console.log(num)  // 456}console.log(num)  // 456
</script>
//这里为什么第一个输出值不是undefined,第三个输出值不是123呢?原因是这样的,因为var不存在块级作用域,且变量名会提升,所以上述代码其实相当于:
<script>var num;num = 123if(true){console.log(num) // 123num = 456;console.log(num)  // 456}console.log(num)  // 456
</script>

1.2 const - 常用来声明常量,且常量不可修改,必须初始化,存在着块级作用域

//1.无变量提升
<script>function fn(){console.log(num); const num = 456;console.log(num)}fn()
</script>
//运行上述代码会发现会报错 Uncaught ReferenceError: num is not defined 。这里说明,使用const来定义的常量名并没有提升。
//2.必须初始化
<script>const num;console.log(num)
</script>
//这里运行后发现会报错。 Uncaught SyntaxError: Missing initializer in const declaration 意思是:语法错误,在const声明中没有初始化。
//3.块级作用域
<script>const num = 456if(true){const num = 789;console.log(num); // 789}console.log(num) // 456
</script>

1.3 let - let定义的变量存在着块级作用域,在函数内定义的变量,对函数外部无影响

//1.块级作用域
<script>let num = 789;function fn(){let num = 46;console.log(num) // 46}fn()console.log(num) // 789
</script>
//2.无变量提升
<script>function fn(){console.log(num); // Uncaught ReferenceError: num is not definedlet num = 46;console.log(num)}fn()
</script>

2.set

 ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。

2.1 可以对数组进行去重

var str = new Set("Hello world!");
for(var str1 of str){console.log(str1+" ")
}
//结果会是这样:H e l o w r d !function fn(arr){return Array.from(new Set(arr))  // Array.from方法可以将 Set 结构转为数组
}
const items = [1,2,3,4,5,6,7,1,2,1,3,1,2,3]
console.log(fn(items))//[1,2,3,4,5,6,7]let arr1 = [12,13,23,45,46,48,78,79,45,12,13,23];
let arr = new Set(arr1)
console.log([...arr])  // [ 12, 13, 23, 45, 46, 48, 78, 79 ]

let newarr = [1,2,3,4,5,6,7,1,2,1,3,1,2,3];newarr = [...new set(newarr)];//[1,2,3,4,5,6,7]newarr = Array.form(new Set(newarr));//[1,2,3,4,5,6,7]

2.2 set 实例的属性和方法

1.属性Set.prototype.constructor:构造函数,默认就是Set函数。Set.prototype.size:返回Set实例的成员总数。
2.Set 实例的方法分为两大类:操作方法(用于操作数据)和遍历方法(用于遍历成员)。下面先介绍四个操作方法:add(value):添加某个值,返回 Set 结构本身。delete(value):删除某个值,返回一个布尔值,表示删除是否成功。has(value):返回一个布尔值,表示该值是否为Set的成员。clear():清除所有成员,没有返回值。

s.add(1).add(2).add(2);
// 注意2被加入了两次s.size // 2s.has(1) // true
s.has(2) // true
s.has(3) // falses.delete(2);
s.has(2) // false

Set 结构的实例有四个遍历方法,可以用于遍历成员。keys():返回键名的遍历器values():返回键值的遍历器entries():返回键值对的遍历器forEach():使用回调函数遍历每个成员

keys方法、values方法、entries方法返回的都是遍历器对象。由于 Set 结构没有键名,只有键值(或者说键名和键值是同一个值),所以keys方法和values方法的行为完全一致。

let set = new Set([{ID:'1',Robort_name:'桑桑',Wechat_Name:'Only',is_read:'1'},{ID:'2',Robort_name:'33',Wechat_Name:'O',is_read:'0'},{ID:'3',Robort_name:'55',Wechat_Name:'1',is_read:'1'}])for (let item of set.keys()) {//keys() 返回键名的遍历器console.log(item);}for (let i of set.values()) {//values() 返回键值的遍历器console.log(i);}for(let i of set.entries()){//entries():返回键值对的遍历器console.log(i)}

  

//扩展运算符(...)内部使用for...of循环,所以也可以用于 Set 结构。let set = new Set(['red', 'green', 'blue']);let arr = [...set];console.log(arr)//['red', 'green', 'blue']//扩展运算符和 Set 结构相结合,就可以去除数组的重复成员。let arr1 = [3, 5, 2, 2, 5, 5];let unique = [...new Set(arr1)];console.log(unique)// [3, 5, 2]//而且,数组的map和filter方法也可以间接用于 Set 了。let set = new Set([1, 2, 3]);set = new Set([...set].map(x => x * 2));console.log(set)// 返回Set结构:{2, 4, 6}let set1 = new Set([1, 2, 3, 4, 5]);set1 = new Set([...set1].filter(x => (x % 2) == 0));// 返回Set结构:{2, 4}//因此使用 Set 可以很容易地实现并集(Union)、交集(Intersect)和差集(Difference)。let a = new Set([1, 2, 3]);let b = new Set([4, 3, 2]);// 并集let union = new Set([...a, ...b]);console.log(union)// Set {1, 2, 3, 4}// 交集let intersect = new Set([...a].filter(x => b.has(x)));console.log(intersect)// set {2, 3}// 差集let difference = new Set([...a].filter(x => !b.has(x)));console.log(difference)// Set {1}//如果想在遍历操作中,同步改变原来的 Set 结构,目前没有直接的方法,但有两种变通方法。一种是利用原 Set 结构映射出一个新的结构,然后赋值给原来的 Set 结构;另一种是利用Array.from方法。// 方法一let set3 = new Set([1, 2, 3]);set3 = new Set([...set3].map(val => val * 2));console.log(set3)// set的值是2, 4, 6// 方法二let set4 = new Set([1, 2, 3]);set4 = new Set(Array.from(set4, val => val * 2));console.log(set4)// set的值是2, 4, 6//上面代码提供了两种方法,直接在遍历操作中改变原来的 Set 结构。

3.map

JavaScript 的对象(Object),本质上是键值对的集合(Hash 结构),但是传统上只能用字符串当作键。ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map 的键实际上是跟内存地址绑定的,只要内存地址不一样,就视为两个键。

const m = new Map();const o = {p: 'Hello World'};m.set(o, 'content')m.get(o) // "content"m.has(o) // truem.delete(o) // truem.has(o) // falseconsole.log([...m])const map = new Map([['name', '张三'],['title', 'Author']]);map.size // 2map.has('name') // truemap.get('name') // "张三"map.has('title') // truemap.get('title') // "Author"console.log([...map]) //[{'name':'张三'},{'title':'Author'}]// 实际上是这样const items = [['name', '张三'],['title', 'Author']];const map = new Map();items.forEach(([key, value]) => map.set(key, value));console.log([...map]) //[{'name':'张三'},{'title':'Author'}]const set = new Set([['foo', 1],['bar', 2]]);const m1 = new Map(set);m1.get('foo') // const m2 = new Map([['baz', 3]]);const m3 = new Map(m2);m3.get('baz') // 3console.log([...m1]) //map转为数组 ['foo',1] ['bar',2]console.log([...m2]) //['baz',3]console.log([...m3])  //['baz',3]const map = new Map();map.set(1, 'aaa').set(1, 'bbb');map.get(1) // "bbb"console.log([...map]) //[1,'bbb']const map = new Map();const k1 = ['a'];const k2 = ['a'];map.set(k1, 111).set(k2, 222);map.get(k1) // 111map.get(k2) // 222console.log([...map]) //[[['a'],111],[['b'],222]]let map = new Map();map.set(-0, 123);map.get(+0) // 123map.set(true, 1);map.set('true', 2);map.get(true) // 1map.set(undefined, 3);map.set(null, 4);map.get(undefined) // 3map.set(NaN, 123);map.get(NaN) // 123console.log([...map]) //[[0,123],['true',1],['true',2],[undefined,2],[null,4],[NaN,123]]

实例的属性和操作方法
(1)size 属性
size属性返回 Map 结构的成员总数。

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

(2)set(key, value)
set方法设置键名key对应的键值为value,然后返回整个 Map 结构。如果key已经有值,则键值会被更新,否则就新生成该键。

const m = new Map();m.set('edition', 6)        // 键是字符串
m.set(262, 'standard')     // 键是数值
m.set(undefined, 'nah')    // 键是 undefined

Set方法返回的是当前的Map对象,因此可以采用链式写法。

let map = new Map().set(1, 'a').set(2, 'b').set(3, 'c');

(3)get(key)
get方法读取key对应的键值,如果找不到key,返回undefined。

const m = new Map();const hello = function() {console.log('hello');};
m.set(hello, 'Hello ES6!') // 键是函数m.get(hello)  // Hello ES6!

(4)has(key)
has方法返回一个布尔值,表示某个键是否在当前 Map 对象之中。

const m = new Map();m.set('edition', 6);
m.set(262, 'standard');
m.set(undefined, 'nah');m.has('edition')     // true
m.has('years')       // false
m.has(262)           // true
m.has(undefined)     // true

(5)delete(key)
delete方法删除某个键,返回true。如果删除失败,返回false。

const m = new Map();
m.set(undefined, 'nah');
m.has(undefined)     // truem.delete(undefined)
m.has(undefined)       // false

(6)clear()
clear方法清除所有成员,没有返回值。

let map = new Map();
map.set('foo', true);
map.set('bar', false);map.size // 2
map.clear()
map.size // 0

遍历方法
Map 结构原生提供三个遍历器生成函数和一个遍历方法。
keys():返回键名的遍历器。
values():返回键值的遍历器。
entries():返回所有成员的遍历器。
forEach():遍历 Map 的所有成员。

const map = new Map([['F', 'no'],['T',  'yes'],
]);for (let key of map.keys()) {console.log(key);
}
// "F"
// "T"for (let value of map.values()) {console.log(value);
}
// "no"
// "yes"for (let item of map.entries()) {console.log(item[0], item[1]);
}
// "F" "no"
// "T" "yes"// 或者
for (let [key, value] of map.entries()) {console.log(key, value);
}
// "F" "no"
// "T" "yes"// 等同于使用map.entries()
for (let [key, value] of map) {console.log(key, value);
}
// "F" "no"
// "T" "yes"

Map 结构转为数组结构,比较快速的方法是使用扩展运算符(...)。

const map = new Map([[1, 'one'],[2, 'two'],[3, 'three'],
]);[...map.keys()]
// [1, 2, 3][...map.values()]
// ['one', 'two', 'three'][...map.entries()]
// [[1,'one'], [2, 'two'], [3, 'three']][...map]
// [[1,'one'], [2, 'two'], [3, 'three']]

结合数组的map方法、filter方法,可以实现 Map 的遍历和过滤(Map 本身没有map和filter方法)。

const map0 = new Map().set(1, 'a').set(2, 'b').set(3, 'c');const map1 = new Map([...map0].filter(([k, v]) => k < 3)
);
// 产生 Map 结构 {1 => 'a', 2 => 'b'}const map2 = new Map([...map0].map(([k, v]) => [k * 2, '_' + v]));
// 产生 Map 结构 {2 => '_a', 4 => '_b', 6 => '_c'}

此外,Map 还有一个forEach方法,与数组的forEach方法类似,也可以实现遍历。

map.forEach(function(value, key, map) {console.log("Key: %s, Value: %s", key, value);
});

forEach方法还可以接受第二个参数,用来绑定this。

const reporter = {report: function(key, value) {console.log("Key: %s, Value: %s", key, value);}
};map.forEach(function(value, key, map) {this.report(key, value);
}, reporter);

与其他数据结构的互相转换
(1)Map 转为数组
前面已经提过,Map 转为数组最方便的方法,就是使用扩展运算符(...)。

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

(2)数组 转为 Map
将数组传入 Map 构造函数,就可以转为 Map。

new Map([[true, 7],[{foo: 3}, ['abc']]
])
// Map {
//   true => 7,
//   Object {foo: 3} => ['abc']
// }

(3)Map 转为对象
如果所有 Map 的键都是字符串,它可以无损地转为对象。如果有非字符串的键名,那么这个键名会被转成字符串,再作为对象的键名。

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

 (4)对象转为 Map

function objToStrMap(obj) {let strMap = new Map();for (let k of Object.keys(obj)) {strMap.set(k, obj[k]);}return strMap;
}objToStrMap({yes: true, no: false})
// Map {"yes" => true, "no" => false}

 (5)Map 转为 JSON
Map 转为 JSON 要区分两种情况。一种情况是,Map 的键名都是字符串,这时可以选择转为对象 JSON。

 

function strMapToJson(strMap) {return JSON.stringify(strMapToObj(strMap));
}let myMap = new Map().set('yes', true).set('no', false);
strMapToJson(myMap)
// '{"yes":true,"no":false}'

  另一种情况是,Map 的键名有非字符串,这时可以选择转为数组 JSON。

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

  (6)JSON 转为 Map
JSON 转为 Map,正常情况下,所有键名都是字符串。

function jsonToStrMap(jsonStr) {return objToStrMap(JSON.parse(jsonStr));
}jsonToStrMap('{"yes": true, "no": false}')
// Map {'yes' => true, 'no' => false}

4.Array.from()方法

Array.from方法用于将两类对象转为真正的数组:(类数组)类似数组的对象(array-like object)和可遍历(iterable)的对象(包括 ES6 新增的数据结构 Set 和 Map)。

 

let arrayLike = {'0': 'a','1': 'b','2': 'c',length: 3
};// ES5的写法
var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']// ES6的写法
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']

  

let arrayLike = {0: 'tom', 1: '65',2: '男',3: ['jane','john','Mary'],'length': 4
}
let arr = Array.from(arrayLike)
console.log(arr) // ['tom','65','男',['jane','john','Mary']]
//那么,如果将上面代码中length属性去掉呢?实践证明,答案会是一个长度为0的空数组。
//这里将代码再改一下,就是具有length属性,但是对象的属性名不再是数字类型的,而是其他字符串型的,代码如下:
let arrayLike = {'name': 'tom', 'age': '65','sex': '男','friends': ['jane','john','Mary'],length: 4
}
let arr = Array.from(arrayLike)
console.log(arr)  // [ undefined, undefined, undefined, undefined ]

 会发现结果是长度为4,元素均为undefined的数组
  由此可见,要将一个类数组对象转换为一个真正的数组,必须具备以下条件:
  1、该类数组对象必须具有length属性,用于指定数组的长度。如果没有length属性,那么转换后的数组是一个空数组。
  2、该类数组对象的属性名必须为数值型或字符串型的数字
  ps: 该类数组对象的属性名可以加引号,也可以不加引号

 

//实际应用中,常见的类似数组的对象是 DOM 操作返回的 NodeList 集合,以及函数内部的arguments对象。Array.from都可以将它们转为真正的数组。
// NodeList对象
let ps = document.querySelectorAll('p');
Array.from(ps).filter(p => {return p.textContent.length > 100;
});
// arguments对象
function foo() {var args = Array.from(arguments);// ...
}
//上面代码中,querySelectorAll方法返回的是一个类似数组的对象,可以将这个对象转为真正的数组,再使用filter方法。//只要是部署了 Iterator 接口的数据结构,Array.from都能将其转为数组。
Array.from('hello')
// ['h', 'e', 'l', 'l', 'o']
let namesSet = new Set(['a', 'b'])
Array.from(namesSet) // ['a', 'b']
//上面代码中,字符串和 Set 结构都具有 Iterator 接口,因此可以被Array.from转为真正的数组。//如果参数是一个真正的数组,Array.from会返回一个一模一样的新数组。
Array.from([1, 2, 3])
// [1, 2, 3]//值得提醒的是,扩展运算符(...)也可以将某些数据结构转为数组。
// arguments对象
function foo() {const args = [...arguments];
}// NodeList对象
[...document.querySelectorAll('div')]
//扩展运算符背后调用的是遍历器接口(Symbol.iterator),如果一个对象没有部署这个接口,就无法转换。Array.from方法还支持类似数组的对象。所谓类似数组的对象,本质特征只有一点,即必须有length属性。因此,任何有length属性的对象,都可以通过Array.from方法转为数组,而此时扩展运算符就无法转换。Array.from({ length: 3 });
// [ undefined, undefined, undefined ]
//上面代码中,Array.from返回了一个具有三个成员的数组,每个位置的值都是undefined。扩展运算符转换不了这个对象。//对于还没有部署该方法的浏览器,可以用Array.prototype.slice方法替代。const toArray = (() =>Array.from ? Array.from : obj => [].slice.call(obj)
)();//Array.from还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组。Array.from(arrayLike, x => x * x);
// 等同于
Array.from(arrayLike).map(x => x * x);Array.from([1, 2, 3], (x) => x * x)
// [1, 4, 9]
下面的例子是取出一组 DOM 节点的文本内容。let spans = document.querySelectorAll('span.name');// map()
let names1 = Array.prototype.map.call(spans, s => s.textContent);// Array.from()
let names2 = Array.from(spans, s => s.textContent)//下面的例子将数组中布尔值为false的成员转为0。
Array.from([1, , 2, , 3], (n) => n || 0)
// [1, 0, 2, 0, 3]//另一个例子是返回各种数据的类型。
function typesOf () {return Array.from(arguments, value => typeof value)
}
typesOf(null, [], NaN)
// ['object', 'object', 'number']
//如果map函数里面用到了this关键字,还可以传入Array.from的第三个参数,用来绑定this。//Array.from()可以将各种值转为真正的数组,并且还提供map功能。这实际上意味着,只要有一个原始的数据结构,你就可以先对它的值进行处理,然后转成规范的数组结构,进而就可以使用数量众多的数组方法。Array.from({ length: 2 }, () => 'jack')
// ['jack', 'jack']
//上面代码中,Array.from的第一个参数指定了第二个参数运行的次数。这种特性可以让该方法的用法变得非常灵活。//Array.from()的另一个应用是,将字符串转为数组,然后返回字符串的长度。因为它能正确处理各种 Unicode 字符,可以避免 JavaScript 将大于\uFFFF的 Unicode 字符,算作两个字符的 bug。function countSymbols(string) {return Array.from(string).length;
}

  

 

转载于:https://www.cnblogs.com/zhoubingyan/p/9052508.html

es6(var,let,const,set,map,Array.from())相关推荐

  1. ES6基础(var let const 箭头函数)-学习笔记

    文章目录 ES6基础(var let const 箭头函数)- 学习笔记 定义:var let const 箭头函数 数据结构 set map ES6基础(var let const 箭头函数)- 学 ...

  2. es6(let与const命令)

    es6(let与const命令) 理论区别 var let const 在函数作用域内或者全局有效,没有块级作用域 只在let命令所在的代码块内有效 只在声明所在的块级作用域内有效 能重复声明 不能重 ...

  3. ES6学习(var,let,const区别)

    本人写这个专题的博客是为了总结一下自己学习,使用还有刷题时学到的ES6知识点,并做以归纳. var,let,const 三个属性都可以声明变量. 作用域 var  重新赋值,重新定义变量,可以重复声明 ...

  4. ES6(迭代器、Set、Map、数组去重)

    目录 迭代器Iterator Iterator 的作用 原生具备 Iterator 接口的数据结构 Iterator 的遍历过程 迭代器实现了Iterator接口,只要实现了Iterator就可以使用 ...

  5. 第七天2017/04/14(引用与const、C++基本知识)

    一.引用与const 1.const引用的初始化的两种形式: //const引用,让被const修饰的变量具有只读属性 #include <iostream> using namespac ...

  6. C++STL4种关联容器(set、multiset、map和multimap)

    关联容器将值和键关联在一起,并使用键来查找值. 特点: 可对元素进行快速访问 允许插入元素,但不能指定位置. 通常使用某种数来实现. 这四类容器仅仅只是在RBTree上进行了一层封装,首先,set和m ...

  7. python四个带 key 参数的函数(max、min、map、filter)

    四个带 key 参数的函数: max()点击查看详细 min()点击查看详细 map()点击查看详细 filter()点击查看详细 1)max(iterable, key) key:相当于对可迭代对象 ...

  8. Spring框架中XML配置文件注入集合(数组、LIST、MAP、SET)属性

    Spring框架中XML配置文件注入集合属性 前言 创建测试类与属性 配置XML配置文件 建立调用类 调用结果 前言 某些类的属性是可能是集合,包括:数组.LIST.MAP.SET等集合,在Sprin ...

  9. js中数组的高逼格操作(filter、sort、map、reduce)

    说在前面的话 ES6全称ECMAScript 6.0, 成为JavaScript 的下一个版本标准.它提供了一些很牛逼的东西,使我们写的代码更加简洁.方便.比如模板字符串.箭头函数.promise.c ...

  10. PAT乙级真题 1075 链表元素分类 C++实现(测试点5:用map会超时)

    题目 给定一个单链表,请编写程序将链表元素进行分类排列,使得所有负值元素都排在非负值元素的前面,而 [0, K] 区间内的元素都排在大于 K 的元素前面.但每一类内部元素的顺序是不能改变的.例如:给定 ...

最新文章

  1. 前沿 | DeepMind改进超参数优化:遗传算法效果超越贝叶斯
  2. 用一个比喻说明项目里各个成员的角色
  3. 验证数字的正则表达式集
  4. Android布局之LinearLayout
  5. MyBatis之传入参数——parameterType
  6. AngularJS学习之旅—AngularJS Http(九)
  7. 抽屉效果_宜家靠边,好用不贵的全格收纳抽屉使用感受
  8. (原创)对某国的一次渗透
  9. java locale.us_JAVA实现国际化
  10. 看完这篇还不知道css固定和自适应可以小和尚要摆地摊了
  11. scrapy再学习与第二个实例
  12. hibernate连接mysql 释放连接_SSH 占用数据库连接不释放问题
  13. 搭建局域网HTTP FTP服务
  14. Markdown_合并表格中的单元格
  15. 如何使用Putty登录安装在VirtualBox里的ubuntu 1
  16. 16 计划稳定性与控制
  17. 优点 spark_分布式计算引擎之星——Spark
  18. 9月6日 星期二 晴(晚上有雨)
  19. Spark Java实战
  20. 函数的极值点、零点、驻点、拐点的理解

热门文章

  1. 大事件!35的程序员竟然失去了面试资格,这是为什么?
  2. 淘宝云梯分布式计算平台架构
  3. 区块链入门实战教程—看完本文你也会开发区块链
  4. “干活的干不过写PPT 的”:新东方年会神曲刷屏背后:这3点值得我们思考
  5. 干货|现代IM系统中消息推送和存储架构的实现
  6. 你应该知道的一些 ADB 命令
  7. 对Python中列表和数组的赋值,浅拷贝和深拷贝的实例讲解
  8. shell基础之综合练习
  9. PAT乙级真题 | 1006 换个格式输出整数
  10. 网络传输中利用fastjson将复杂嵌套数据类型Json格式转换(GeoJsonPolygon)