ECMAScript 6.0(简称ES6)是JavaScript语言的下一代标准,已经在2015年6月正式发布了。它的目标,是使得JavaScript语言可以用来编写复杂的大型应用程序,成为企业级开发语言。各大浏览器的最新版本,随着时间的推移,支持度已经越来越高了,ES6的大部分特性都实现了。那么也就意味着低版本浏览器是不支持ES6的。

1:let/const 声明变量关键字

1)let关键字特点

  • let声明的变量只在所在的块级作用域内有效(块级作用域特点:不受外部环境影响和内部代码块影响)
  • js预解析时不存在变量的提升定义,存在暂时性死区,声明语句位置后使用,否则异常
  • 暂时性死区(释义:let声明的变量进入所在作用域已存在,未声明前使用报错,受封闭作用域,不受外部的影响)
  • 不允许重复声明,重复声明异常 
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ES6</title>
<script type="text/javascript">
// 作用域:全局作用域、函数作用域
// ES6新增了一个 块级作用域
var varname="王五"
{
console.log(varname);//输出王五
var varname = '张三';
var varname = '赵四';
{
var varname="刘能"
console.log(varname)//输出刘能
}
}
console.log(varname)//输出刘能
console.log("————————————————我是分割线————————————————")
console.log("——————var关键字和let关键字的作用比对——————")
console.log("————————————————我是分割线————————————————")
let letname="李四"
{
//console.log(letname);
//取消注释直接异常提示未被定义,let声明的变量不存在变量的提升定义
let letname = '张三';
//let letname = '赵四';
//取消注释直接异常提示已被声明
{
let letname="刘能";
console.log(letname);
}
console.log(letname);
//输出张三块暂时性的死区,块级作用域不会受外部、内部的影响
}
console.log(letname);//输出李四
</script>
</head>
<body> </body>
</html>

  

let的使用

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ES6</title>
<style type="text/css">
*{
margin: ;
padding: ;
}
ul,ol{
list-style: none;
}
#list{
width: %;
margin: 100px auto;
border: 1px solid #f3f3f3;
}
#list li{
text-align: center;
border-bottom: 1px dashed #f3f3f3;
line-height: 50px;
font-size: 26px;
letter-spacing: 10px;
}
</style>
</head>
<body>
<ul id="list">
<li>我是第1行,我很皮</li>
<li>我是第2行,我很皮</li>
<li>我是第3行,我很皮</li>
<li>我是第4行,我很皮</li>
<li>我是第5行,我很皮</li>
</ul>
</body>
<script type="text/javascript">
var oList=document.getElementById('list');
var oLi=oList.children;
//var定义变量实现各行换色
/* for (var i = 0; i < oLi.length; i++) {
i % 2 === 0?oLi[i].style.background = '#eee':oLi[i].style.background = '#fff'
oLi[i].index=i;//给每个元素添加属性index记录下标
oLi[i].onmouseover=function() {
this.style.background = '#e33'
}
oLi[i].onmouseout=function() {
//不直接使用i的原因说明:i是全局变量事件只有在调用的时候执行,触发事件的时候,for循环已经执行完毕,则i的值则为29,保持不变
//通过添加的属性判断下标的奇偶设置背景色
this.index % 2 === 0?this.style.background = '#eee':this.style.background = '#fff'
}
}*/
//使用let关键字进行定义变量利用其的块级作用域进行实现,每次循环都相当于重新创建变量i
for (let i = ; i < oLi.length; i++) {
i % === ?oLi[i].style.background = '#eee':oLi[i].style.background = '#fff'
oLi[i].onmouseover=function() {
this.style.background = '#e33'
}
oLi[i].onmouseout=function() {
//不直接使用i的原因说明:i是全局变量事件只有在调用的时候执行,触发事件的时候,for循环已经执行完毕,则i的值则为29,保持不变
//通过添加的属性判断下标的奇偶设置背景色
i % === ?this.style.background = '#eee':this.style.background = '#fff'
}
} </script>
</html>

let的使用

2)const关键字特点

  • const定义的常量是不允许改变值,声明和赋值必须放在一起,只声明不赋值,就会报错
const a = 5;
a = 6;
console.log(a);
  • 拥有和let关键字的所有的特点(参考let属性的说明)
  • const常量定义关键字定义的复合类型的变量,变量名不指向存储的数据,指向数据的存储地址,const定义的变量控制的是指向的地址不变,并不是该地址指向的数据不变
// 特殊的场景
const a = {name: '赵四'};
a.name = '刘能';
console.log(a);

  

3)const命令和let命令的区别

1)const关键字定义的是常量,值无法改变,经常使用在值不变的情况下,如定义圆周率等。let定义的变量,块级作用域。

2)顶层对象,在浏览器环境指的是window对象,在Node指的是global对象。ES5之中,顶层对象的属性与全局变量是等价的

ES6全局变量将逐步与顶层对象的属性脱钩:

let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。

var命令和function命令声明的全局变量,依旧是顶层对象的属性(保证兼容性)

// 顶层对象属性
var vara = 4;
console.log(window.vara);
console.log("—————————分割线—————————")
let leta = 4;
console.log(window.leta);

  


2:变量结构赋值

ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)

“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。

 (各类的变量解构赋值在代码中说明,请祥看注释)

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ES6</title>
</head>
<body>
</body>
<script type="text/javascript">
//——————————————— 变量解构赋值————————————//
// 从数组中提取值
var arr = ['张三', '赵四', '王五'];
//ES6之前的写法
var a = arr[];
var b = arr[];
var c = arr[];
console.log(a, b, c);
/*ES6变量解构赋值(左右结构对称,模式相同,就会把左边的变量赋予对应的值)*/
//数组的解构
//——————————————— 解构赋值————————————//
console.log("变量解构赋值:");
var [a, b, c] = arr;
console.log(a, b, c);
//——————————————— 解构赋值————————————//
console.log("数组的解构:")
var [[a], [[b]], [c], [[[d]]]] = [[], [[]], [], [[[]]]];
console.log(a,b,c,d)
//不完全解构
var [a, b, c, d] = [, , ];
console.log(a,b,c,d)//如果结构不成功,则返回undefined
var [a,[b],c]=[,[,],]
console.log(a,b,c)
/*不完全解构:等号左边的模式,只匹配一部分的等号右边的数组。这种情况下,解构依然可以成功*/
// 指定默认值
console.log("指定默认值");
var [a, b, c, d = ] = [, , ];
console.log(a, b, c, d);
/*ES6内部使用严格相等运算符(===),判断一个位置是否有值。若一个数组成员不严格等于undefined,默认值是不会生效的*/
var [x=]=[undefined];
console.log(x);//输出为1
var [x=]=[null];
console.log(x);//输出为null //——————————————— 解构赋值————————————//
// ... 扩展运算符
console.log("扩展运算符:")
var [a, b, ...c] = [, , , ]; //...只能放到最后一个参数
console.log(a,b,c)//输出为1,2,[3,4]
// var [...a, b, c] = [1, 2, 3, 4]; // 不可以
var [,,c] = [, , ];
console.log(c)//输出为3 //——————————————— 解构赋值————————————//
// 对象的解构赋值
console.log("对象的解构赋值:")
var {name: name, age: age} = {name: '赵四', 'age': };
console.log(name, age);
var {name, age} = {name: '赵四', 'age': };
console.log(name, age);
//对象的属性没有次序,变量必须与属性同名,才能取到正确的值
var {age, name} = {name: '赵四', 'age': };
console.log(name, age);
var {age, name, sex='由于某种原因未知'} = {name: '赵四', 'age': };
console.log(name, age, sex); /*对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。*/
var {aniname:fname,aniage:fage}={aniname:"动物名称",aniage:"动物年龄"}
console.log(fname,fage)
/* 对象的默认值设置:默认值生效的条件是,对象的属性值严格等于undefined。如果要已经声明的变量用于
    解构赋值,需将代码块包到小括号内,否则JavaScript引擎会将{x}理解成一个代码块,从而发生语法错误。*/
let carname;
/*{carname}={carname:"BMW"}//报错*/
({carname}={carname:"BMW"})
console.log(carname) //——————————————— 解构赋值————————————//
// 函数的解构传参
console.log("函数的返回值解构:");
function introduce({name, age='保密', sex}) {
console.log('我叫' + name + ';今年' + age + ';性别' + sex);
}
introduce({
sex: 'boy',
name: '赵四'
}); //——————————————— 解构赋值————————————//
//函数的返回值解构
console.log("函数的返回值解构:");
function profile() {
return {
newname: '张三',
height: ,
newsex: '男'
};
}
let {height, newname, newsex} = profile();
console.log(height, newname, newsex); /*解构赋值不仅适用于var命令,也适用于let和const命令。*/
</script>
</html>

  


3:字符串扩展

1)ES6字符串新增的遍历器接口(for...of)

var str = 'good good study day day up!';
for(let v of str) {
console.log(v);
}

  2)ES6字符串新增的方法(includes(),startsWith(),endsWith(),repeat())

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ES6</title>
</head>
<body>
</body>
<script type="text/javascript">
var str = 'good good study day day up!';
//第一个参数指定查找的字符,第二个参数指定开始查找的位置
console.log(str.includes('good', 15));
//第一个参数指定查找的字符,第二个参数指定开始查找的位置
console.log(str.startsWith(' ', 15));
//第一个参数指定查找的字符,第二个参数指定结束位置的字符
console.log(str.endsWith('y', 15));
//repeat方法返回一个新字符串,表示将原字符串重复n次。
/* includes():返回布尔值,表示是否找到了参数字符串。
startsWith():返回布尔值,表示参数字符串是否在源字符串的头部。
endsWith():返回布尔值,表示参数字符串是否在源字符串的尾部。*/
console.log('x'.repeat(10) + 'o'.repeat(10));
//参数如果是小数,会被向下取整。
console.log('x'.repeat(10.1) + 'o'.repeat(10.9));
//参数NaN等同于0。
console.log('x'.repeat(NaN) + 'o'.repeat(10));
//如果repeat的参数是字符串,则会先转换成数字。
console.log('x'.repeat("10") + 'o'.repeat(10));
</script>
</html>

  

3)ES6模板字符串

模板字符串(template string)是增强版的字符串,用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。如果在模板字符串中需要使用反引号,则前面要用反斜杠转义。模板字符串中嵌入变量,需要将变量名写在${}之中。模板字符串表示多行字符串,所有的空格和缩进都会被保留在输出之中。

/*oLi.innerHTML='<a href="javascript:;" class="abtn" data-id="'+aGoodList[i].id+'">删除该商品</a><img src="'+aGoodList[i].src+'" /><div class="title">'+aGoodList[i].title+'</div><div class="price">¥'+aGoodList[i].price+'/个|数量'+aGoodList[i].amount+'</div>';*/
/*使用模板字符换拼接该字符串改写上面的字符串*/
oLi.innerHTML=`
<a href="javascript:;" class="abtn" data-id="${aGoodList[i].id}">
删除该商品
</a>
<img src="${aGoodList[i].src}" />
<div class="title">
${aGoodList[i].title}
</div>
<div class="price">
¥${aGoodList[i].price}/个|数量${aGoodList[i].amount}
</div>`; 

4:数值扩展

1)二进制和八进制的表示法

ES6提供了二进制和八进制数值的新的写法,分别用前缀0b(或0B)和0o(或0O)表示

console.log(0o123);
console.log(0b1010101);

  

'use strict';
// console.log(0123);//此处报错
console.log(0o123);

  0b和0o前缀的字符串数值转为十进制,要使用Number方法。

console.log(Number(0b0111));//7
console.log(Number(0o123));//83

2)Number对象的扩展 Number.isNaN()、Number.parseInt()、Number.parseFloat()

1>Number.isNaN()

ES6在Number对象上,新提供了Number.isNaN()方法。Number.isNaN()用来检查一个值是否为NaN。

console.log(isNaN(NaN));//NaN是NaN类型  返回true
console.log(Number.isNaN(NaN));//NaN的数据类型是number类型返回true

与传统的全局方法isNaN()的区别在于,传统方法先调用Number()将非数值的值转为数值,再进行判断,而该新方法只对数值有效,非数值一律返回false。

// isNaN和Number.isNaN的区别
console.log(isNaN('12px'));//非数值先转数值类型在判断
console.log(Number.isNaN('12px'));//如果是非数值类型,直接输出false

2>Number.parseInt()(逐步减少全局性方法,使得语言逐步模块化)

console.log(parseInt("12px"))
console.log(Number.parseInt("12px"))//除了将方法挂载到Number身上无任何差别

  3>Number.parseFloat()(逐步减少全局性方法,使得语言逐步模块化)

console.log(parseFloat("12px"))
console.log(Number.parseFloat("12px"))//挂载到Number身上无任何差别

  3)Math对象的扩展 Math.trunc(),Math.sign(),Math.cbrt(),Math.hypot()

1>Math.trunc()去除小数向下取整,非数值Math.trunc内部使用Number方法将其先转为数值。对于空值和无法截取整数的值,返回NaN。

2>Math.sign():用来判断一个数到底是正数、负数、还是零。返回值:参数为正数,返回1;参数为负数,返回-1;参数为0,返回0;参数为-0,返回-0;其他值,返回NaN。

3>Math.cbrt()用于计算一个数的立方根。非数值,Math.cbrt方法内部也是先使用Number方法将其转为数值。

4>Math.hypot()返回所有参数的平方和的平方根。非数值,Math.hypot方法会将其转为数值。只要有一个参数无法转为数值,就会返回NaN。

// Math对象的扩展
console.log("Math.trunc方法:")
console.log(Math.trunc(4.9));
console.log("Math.sign方法:")
console.log(Math.sign(4.9));
console.log(Math.sign(-4.9));
console.log(Math.sign(0));
console.log(Math.sign(+0));
console.log(Math.sign(-0));
console.log("Math.cbrt方法:")
console.log(Math.cbrt(8));
console.log("Math.hypot方法:")
console.log(Math.hypot(3,4));

    


5:数组扩展

  • Array.from()用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象。
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ES6</title>
</head>
<body>
<ul id="list">
<li>这是第1个LI</li>
<li>这是第2个LI</li>
<li>这是第3个LI</li>
<li>这是第4个LI</li>
<li>这是第5个LI</li>
<li>这是第6个LI</li>
<li>这是第7个LI</li>
<li>这是第8个LI</li>
<li>这是第9个LI</li>
<li>这是第10个LI</li>
</ul>
</body>
<script type="text/javascript">
var oList = document.getElementById('list');
console.log("未转换前输出OList是否数组的结果:")
console.log(Array.isArray(oList.children));//伪数组
var aLi = oList.children;
for(var i = ; i < aLi.length; i++) {
aLi[i].onclick = function () {
this.style.background = 'red';
}
}
console.log("已转换后输出OList是否数组的结果:")
var aLi = Array.from(oList.children);
console.log(Array.isArray(aLi));
aLi.forEach(function (v) {
console.log(v);
});
</script>
</html>

  • find()和findIndex() 数组的实例方法  

find(参数是回调函数),用于找出第一个符合条件的数组成员然后返回该成员。如果没有符合条件的成员,则返回undefined。

findIndex(参数是回调函数)用于找出第一个符合条件的数组成员然后返回该成员索引,如果所有成员都不符合条件,则返回-1

var arr = [1, 4, 7, 9];

var result = arr.find(function (v) {
if(v > 5) {
return true;
} else {
return false;
}
});
console.log(result); var result = arr.findIndex(function (v) {
if(v > 5) {
return true;
} else {
return false;
}
}); console.log(result);

6:函数扩展

1)函数参数默认值

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ES6</title>
</head>
<body>
</body>
<script type="text/javascript">
//es6通过判断参数给定值
function introduce(name, age, sex ) {
// let sex;//不能重复定义,参数变量是默认声明的,所以不能用let或const再次声明。
//方式一:
if(typeof(sex)===undefined){
sex='unknown'
}
//方式二:
//sex = sex || 'unknown';
//缺点参数sex对应的布尔值为false,则该赋值不起作用。
console.log(`my name is ${name}, my age is ${age}, my sex is ${sex}`);
}
introduce('赵四',false);
//es6直接传参赋默认值
function introducees6(name, age=, sex="unknown" ) {
console.log(`my name is ${name}, my age is ${age}, my sex is ${sex}`);
}
introducees6('赵四');
</script>
</html>

2)rest参数

ES6引入rest参数(形式为“...变量名”),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest参数搭配的变量是一个数组,该变量将多余的参数放入数组中。rest参数之后不能再有其他参数(即只能是最后一个参数),否则会报错。   

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ES6</title>
</head>
<body>
</body>
<script type="text/javascript">
function sum(...args) {
console.log(Array.isArray(arguments));//伪数组
console.log(Array.isArray(args));//数组类型
return args.reduce(function (prev, current) {
return prev + current;
});
}
console.log(sum(1,4,7,9,10, 10, 23, 34));
</script>
</html>

  

3)扩展运算符:扩展运算符(spread)是三个点(...)。它好比rest参数的逆运算,将一个数组转为用逗号分隔的参数序列。

console.log(...[1, 4, 7]);

  

扩展运算符的应用:

1>合并数组:扩展运算符提供了数组合并的新写法。

var a = [1, 4, 7], b = [2, 5, 8];
console.log("ES6之前合并数组的方法:")
var result = a.concat(b);
console.log(result)
console.log("ES6扩展运算符合并数组的方法:")
var result = [...a, ...b];
console.log(result)

 

2>与解构赋值结合:扩展运算符可以与解构赋值结合起来,用于生成数组。如果将扩展运算符用于数组赋值,只能放在参数的最后一位,否则会报错。

var [a, b, ...c] = [1, 4, 7, 9, 10];
console.log(c)

  

3:字符串:扩展运算符还可以将字符串转为真正的数组。

var arr = [...'hello world!'];
console.log(arr);

    

严格模式:

从ES5开始,函数内部可以设定为严格模式。《ECMAScript 2016标准》做了一点修改,规定只要函数参数使用了默认值、解构赋值、或者扩展运算符,那么函数内部就不能显式设定为严格模式,否则会报错。

规定原因:函数内部的严格模式,同时适用于函数体代码和函数参数代码。但是,函数执行的时候,先执行函数参数代码,然后再执行函数体代码。这样就有一个不合理的地方,只有从函数体代码之中,才能知道参数代码是否应该以严格模式执行,但是参数代码却应该先于函数体代码执行。

箭头函数:ES6允许使用“箭头”(=>)定义函数。

// 使用箭头的方式创建函数

//箭头函数不用加function关键字定义函数,也不用定义函数名
//代码块部分多于一条语句,就要使用大括号将它们括起来,并且使用return语句返回。
var sumone = (a, b) =>{
a++;
b++;
return a + b;
};
console.log(sumone(4,5));//返回值:11 var sumone = (a, b) =>a + b;//单条语句可以省略花括号和return关键字
console.log(sumone(4,5));//输出的值:9 var sumtwo = a => a + 4;//单个惨数可以省略小括号
console.log(sumtwo(4));//输出的值:8 var sumthree =()=> 4+0;//无参数可以直接写括号
console.log(sumthree());//输出的值:4 //大括号代码块的标识,所箭头函数直接返回一个对象,必须在对象外面加上括号
var sumfour=(name)=>({name:name,age:25});
console.log(sumfour("赵四"));//{name: "赵四", age: 25}

 

  this的指向

// this在箭头函数中的使用

/*
1:在普通函数中,this指向的是window,在严格模式下,this指向的是undefined
2:在方法内,this指向的是方法的拥有者
3:在箭头函数内,this指向的是创建箭头函数时所在的环境中this指向的值。
*/
var title = '我是标题一';
var obj = {
title: '我是标题二',
introduce: function () {
console.log("1"+this.title);
//方法内this指向拥有者obj,则值为1我是标题二
var title="我是标题三"
function introduce() {
console.log("2"+this.title);
//普通函数this指向window,则值为2我是标题一
}
introduce();
var introduce = () => { console.log("3"+this.title) };
//箭头函数this指向所在环境obj方法introduce中this,则值为3我是标题二
introduce();
}
};
obj.introduce();

  

注意点:

1:函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。(this对象的指向是可变的,但是在箭头函数中,它是固定的。)

2:不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。

3:不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用Rest参数代替。

4:不可以使用yield命令,因此箭头函数不能用作Generator函数。


7:对象扩展

1)对象的简写

// 对象的扩展
var title = '新华书店';
var obj = {
title: title,
introduce: function () {
console.log(this.title);
}
};
console.log(obj);
var obj = {
title,
//属性的简写:ES6允许在对象直接写变量。属性名为变量名, 属性值为变量的值。
introduce() {
console.log(this.title);
}
//省略键名书写和定义方法的关键字function
}; console.log(obj);

  

2)对象的新增方法:Object.assign()

Object.assign()用于对象的合并,将源对象(source)的所有属性,复制到目标对象(target)

目标对象:Object.assign方法的第一个参数是目标对象

源  对  象:除了目标对象Object.assign方法的其他参数都是源对象

  注       意:(1)目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。

              (2)Object.assign方法实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。

// 合并对象
var obj1 = {a:1}, obj2= {b:2},obj3={b:3,c:4};
Object.assign(obj1, obj2, obj3);
console.log(obj1);//输出值:{a: 1, b: 3, c: 4}
//释义:obj1目标对象,obj2、obj3源对象
// obj2和obj3的键名有重复后面的覆盖前面的值为3
var obj1 = {a:1}, obj2= {b:2},obj3={c:{d:5},e:6};
var obj4=Object.assign(obj1, obj2, obj3);
//Object.assign方法实行的是浅拷贝,而不是深拷贝。
console.log(obj1);
console.log(obj4.c);//Object.assign拷贝得到的是这个对象的引用
console.log(obj4.c.d);

  


8:Set和Map结构

1)Set结构

  1>Set结构创建:

var test=new Set();

   2>Set的赋值  

//先创建后赋值
var arr = [1, 2, 3, 4, 5]
var s = new Set();
for(var val of arr) {
   s.add(val);//add方法向Set结构添加元素
}
//创建的过程中赋值
var arr = [1, 2, 3, 4, 5 , 5]//Set函数可以接受一个数组(或类似数组的对象)作为参数,用来初始化。
var s = new Set(arr);
console.log(s);//输出:Set(5)。5重复只会保留一个

  3>Set的特点:类似于数组,但是成员的值都是唯一的,没有重复的值。Set本身是一个构造函数,用来生成Set数据结构。

  应用数组去重:

// 数组去重
var arr = [1, 4, 7, 2, 4, 7, 1, 2, 3, 4];
var result = [...new Set(arr)];
var result = Array.from(new Set(arr));
console.log(result);

  

4>Set实例的属性和方法 

Set实例的属性:constructor属性、size属性

  • constructor属性:构造函数,默认就是Set函数。
  • size属性:返回Set实例的成员总数。

Set实例的方法分为两大类:操作方法(用于操作数据)和遍历方法(用于遍历成员)。

操作方法:

    • add(value):添加某个值,返回Set结构本身。 (注意:向Set加入值的时候,不会发生类型转换,所以5和"5"是两个不同的值。Set内部判断两个值是否不同,使用的算法叫做“Same-value equality”,它类似于精确相等运算符(===),主要的区别是NaN等于自身,而精确相等运算符认为NaN不等于自身。)
    • delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
    • has(value):返回一个布尔值,表示该值是否为Set的成员。
    • clear():清除所有成员,没有返回值。

遍历方法:keys(),values(),entries()

    • keys方法由于 Set 结构没有键名,只有键值(或者说键名和键值是同一个值)
    • values方法由于 Set 结构没有键名,只有键值(或者说键名和键值是同一个值)
    • entries方法返回的都是遍历器对象,同时包括键名和键值,所以每次输出一个数组,它的两个成员完全相等。
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ES6</title>
</head>
<body>
</body>
<script type="text/javascript">
// 属性和方法
var s = new Set();
console.log("Set对象的构造函数的输出:");
console.log(s.constructor);
s.add();
s.add('');
s.add();
//向Set加入值的时候,不会发生类型转换,所以5和"5"是两个不同的值。
console.log("NaN精确匹配NaN的结果:"+NaN === NaN);// false
s.add(NaN);
s.add(NaN);//与精确运算符的区别,Same-value equality认为NaN等于NaN,精确运算符不等
console.log("Set对象的输出:");
console.log(s)
console.log("Set对象的Size属性"+s.size);//set的大小
console.log(s.has());//判断该值是否为Set的成员
console.log("keys遍历结果:");
console.log(s.keys());//Set成员的键
for (var setObj of s.keys()){
console.log(setObj)
}
console.log("values遍历结果:")
console.log(s.values());//Set成员的键值
for (var setObj of s.values()){
console.log(setObj)
}
console.log("entries遍历结果:")
console.log(s.entries());//遍历Set对象
for (var setObj of s.entries()){
console.log(setObj)
}
console.log("Set对象是否为数组:")
console.log(Array.isArray(s));//伪数组
/*不同对象是伪数组,但是拥有属性不同,对数组的方法支持也不同,
set对象拥有入口是数组类型的,可以直接使用数组的方法等,不需要转直接使
用,对于一些伪数组想用数组的方法等则需使用Array.from()方法去转成数组。
注意转换后原数据类型的方法、属性等掉了无法继续支持后续使用。*/ console.log("Set对象forEach遍历数组:")
s.forEach((val, key) => {
console.log(val, key);
});
var flag= s.delete();//删除Set对象成员,不指定删除成员,删除all
console.log("Set对象删除方法的执行结果:")
console.log(flag);
console.log(s);
s.clear();//清除Set对象成员
console.log("Set对象清除方法的执行结果:")
console.log(s);
</script>
</html>

2)Map结构

Map数据结构的由来:JavaScript的对象(Object),本质上是键值对的集合,但是传统上只能用字符串当作键。这给它的使用带来了很大的限制。为了解决这个问题,ES6提供了Map数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object结构提供了“字符串—值”的对应,Map结构提供了“值—值”的对应。如果你需要“键值对”的数据结构,Map比Object更合适。

Map实例的属性和方法:

size属性:返回Map结构的成员总数。

set(key, value):set方法设置key所对应的键值,然后返回整个Map结构。如果key已经有值,则键值会被更新,否则就新生成该键。set方法返回的是Map本身,因此可以采用链式写法

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

has(key):返回一个布尔值,表示某个键是否在Map数据结构中。

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

clear():清除所有成员,没有返回值

// 传统对象的键名只能是字符串
console.log("传统对象")
var obj = {
name: '张三',
age:
};
for(var sAttr in obj) {
console.log(sAttr, typeof sAttr);
}
console.log("Map对象")
var obj = {name: '张三'};
var m = new Map();
m.set(obj, '');
console.log(m.get(obj));
console.log(m.size);
console.log(m.constructor);
//Map对象的连续赋值,链式写法
m.set('a', ).set('b', ).set('c', );
console.log(m.get('b'));
console.log(m.has('b'));
console.log(m.delete('b'));
console.log(m.keys());
console.log(m.values());
console.log(m.entries());
m.clear()
console.log(m);

 MaP对象的易错点

只有对同一个对象的引用,Map结构才将其视为同一个键。这一点要非常小心。 

var map=new Map();
map.set(['a'],"数组")
var mapa=map.get(['a'])
/*表面是针对同一个键,但实际上这是两个值,内存地址是不一样的,因此get方法无法读取该键,返回undefined*/
console.log(mapa) // 正确写法
var map=new Map();
var b=['a'];
map.set(b,"数组")
var mapa=map.get(b)
console.log(mapa)

释义:Map对象的set和get方法,表面是针对同一个键,但实际上这是两个值,内存地址是不一样的,因此get方法无法读取该键,返回undefined。

Map的键简单类型的值(数字、字符串、布尔值),则只要两个值严格相等,Map将其视为一个键,包括0和-0。

Map的键NaN不严格相等于自身,严格不相等与自身,但Map将其视为同一个键。


9:generator生成器函数

Generator函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同。

1)语法上,可以把它理解成,Generator函数是一个状态机,封装了多个内部状态。

2)形式上,Generator函数是一个普通函数,但是有两个特征。

  1.function关键字与函数名之间有一个星号;

  2.函数体内部使用yield语句,定义不同的内部状态(yield语句在英语里的意思就是“产出”)。

执行Generator函数会返回一个遍历器对象,也就是说,Generator函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历Generator函数内部的每一个状态。

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ES6</title>
</head>
<body>
</body>
<script type="text/javascript">
// 定义状态机
function* sum(a, b) {
a--;
b += ;
yield a + b; a *= ;
b /= ;
yield a + b; return a + b;
}
// 状态机的调用与普通函数的调用方式一样
console.log("状态机的调用:");
var result = sum(, );
console.log(result);
console.log("第一次调用Next()方法:");
console.log(result.next());
console.log("第二次调用Next()方法:");
console.log(result.next());
console.log("第三次调用Next()方法:");
console.log(result.next());
console.log("第四次调用Next()方法:");
console.log(result.next());
/*注意查看状态机的返回结果*/
</script>
</html>

yield语句:由于Generator函数返回的遍历器对象,只有调用next方法才会遍历下一个内部状态,所以其实提供了一种可以暂停执行的函数。yield语句就是暂停标志。

next()方法:会执行generator的代码,然后,每次遇到yield x;就返回一个对象{value: x, done: true/false},然后“暂停”。返回的value就是yield的返回值,done表示这个generator是否已经执行结束了。如果done为true,则value就是return的返回值。当执行到done为true时,这个generator对象就已经全部执行完毕,不要再继续调用next()了。

遍历器对象的next()方法的运行逻辑如下:

1:遇到yield语句,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值。

2:下一次调用next方法时,再继续往下执行,直到遇到下一个yield语句。

3:如果没有再遇到新的yield语句,就一直运行到函数结束,直到return语句为止,并将return语句后面的表达式的值,作为返回的对象的value属性值。

4:如果该函数没有return语句,则返回的对象的value属性值为undefined。


10:CLASS的写法

ES6提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。基本上,ES6的class可以看作只是一个语法糖,它的绝大部分功能,ES5都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已.Class不存在变量提升,这一点与ES5完全不同。

constructor方法:是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。

类的继承:

Class之间可以通过extends关键字实现继承,这比ES5的通过修改原型链实现继承,要清晰和方便很多。

子类没有定义constructor方法,这个方法会被默认添加,代码如下。也就是说,不管有没有显式定义,任何一个子类都有constructor方法。

在子类的构造函数中,只有调用super之后,才可以使用this关键字,否则会报错。这是因为子类实例的构建,是基于对父类实例加工,只有super方法才能返回父类实例。

super关键字:既可以当作函数使用,也可以当作对象使用。

1>super作为函数调用时,代表父类的构造函数。ES6 要求,子类的构造函数必须执行一次super函数,当做函数调用时必须放到子类构造函数中调用

2>super作为对象时,指向父类的原型对象。

// ES5版本
function point(x,y){
this.x=x;
this.y=y;
}
/*函数对象都有一个子对象 prototype对象,类是以函数的形式来定义的。
prototype表示该函数的原型,也表示一个类的成员的集合。*/
point.prototype.toString=function() {
console.log("我是转换成字符串的方法")
return '('+this.x+','+this.y+')';
}
var p=new point(,);
console.log(p.toString()); // ES6版本
class Animal{
constructor() {
this.height="178cm";
console.log('我是父类的构造函数');
}
drink() {
console.log('我是父类拥有喝的动作');
}
eat() {
console.log('我是父类拥有吃的动作');
}
} /*子类继承父类所有属性及方法,父类不一定拥有子类的所有的属性及方法,继承的关键字extends*/
class Person extends Animal{
constructor(hasMustache) {
// 调用父类的构造函数
super();
//ES6规定子类如果不是默认构造函数,必须通过super()调用父类的构造函数
this.mustache = hasMustache;
this.type = '人类'; }
sleep() {
this.drink();
console.log('第一次结束')
super.eat();//super作为对象时,指向父类的原型对象。
console.log('第二次结束')
console.log('我是子类睡觉!');
}
}
var man = new Person(true);
console.log(man);
console.log(man.height);
man.eat();
man.sleep();
// 本质还是函数
console.log(typeof Person);

  

从零开始学习前端JAVASCRIPT — 10、JavaScript基础ES6(ECMAScript6.0)的更多相关文章

  1. 从零开始学习前端开发 — 10、HTML5新标签及表单控件属性和属性值

    一.html5新增标签 1.结构性标签 header 定义网页的头部 nav 定义网页的导航 footer 定义网页的底部 section 定义网页的某个区域 article 定义网页中的一篇文章 a ...

  2. 从零开始学习前端JAVASCRIPT — 1、JavaScript基础

    1:定义:javascript是一种弱类型.动态类型.解释型的脚本语言. 弱类型:类型检查不严格,偏向于容忍隐式类型转换. 强类型:类型检查严格,偏向于不容忍隐式类型转换. 动态类型:运行的时候执行类 ...

  3. 李洪强和你一起学习前端之(3)Css基础和选择器

    大家好! 经过了前面的学习,是不是对前端的学习有了初步的了解.虽然我之前有iOS开发的经验,现在接触一门新的语言,对我来说 有一定的优势,但是一门技术对于谁来说都是公平的,我承认,我在接触新知识的时候 ...

  4. 从零开始学习前端开发 — 17、CSS3背景与渐变

    一.css3背景切割: background-clip:border-box|padding-box|content-box; 作用: 用来设置背景的可见区域 a) border-box 默认值,背景 ...

  5. 从零开始学习前端开发 — 3、CSS盒模型

    ★  css盒模型是css的基石,每个html标签都可以看作是一个盒模型. css盒模型是由内容(content),补白或填充(padding),边框(border),外边距(margin)四部分组成 ...

  6. 从零开始学习前端JAVASCRIPT — 2、JavaScript基础ES5

    1:ES5简介 ECMAScript 5.1 (或仅 ES5) 是ECMAScript(基于JavaScript的规范)标准的修正. 与HTML5规范进程本质类似,ES5通过对现有JavaScript ...

  7. 从零开始学习前端JAVASCRIPT — 7、JavaScript基础EVENT

    1:事件驱动 1)事件:所谓事件就是js侦测到的用户的操作或是页面的一些行为(怎么发生的) 2)事件源对象:引发事件的元素.(发生在谁的身上) 3)事件处理程序:对事件处理的程序或是函数 (发生了什么 ...

  8. 从零开始学习前端JAVASCRIPT — 9、JavaScript基础RegExp(正则表达式)

    1:正则的概念 正则表达式(regular expression)是一个描述字符规则的对象.可以用来检查一个字符串是否含有某个子字符串,将匹配的子字符串做替换或者从某个字符串中取出符合某个条件的子串等 ...

  9. 从零开始学习前端JAVASCRIPT — 4、JavaScript基础Math和Date对象的介绍

    Math对象的介绍 1:Math对象 Math 对象用于执行数学任务.并不像 Date 和 String 那样是对象的类,因此没有构造函数 Math().您无需创建它,通过把 Math 作为对象使用就 ...

随机推荐

  1. MySQL中MyISAM 和 InnoDB 的基本区别

    有以下5点 1.innodb支持事务,myisam不支持 2.innodb支持mvcc,myisam不支持 3.innodb支持外键,myisam不支持 4.innodb不支持 FULLTEXT类型的 ...

  2. 网络编程(sock)搞定!

    前些日子写了一个网络编程的,纯新手,能优化的地方很多!但是,也算自己独立完成了这么一个东西,晚上发上来!!

  3. c++(hash表)

    hash表,有时候也被称为散列表.个人认为,hash表是介于链表和二叉树之间的一种中间结构.链表使用十分方便,但是数据查找十分麻烦:二叉树中的数据严格有序,但是这是以多一个指针作为代价的结果.hash ...

  4. 关于数据库timestamp类型问题

    数据库使用timestamp类型字段,默人时间为0000-00-00 00:00:00 于是后台会报java.sql.SQLException: Value '0000-00-00 00:00:00' ...

  5. 微信小程序模板消息详解

    先放代码 wxml: <form name='pushMsgFm' report-submit bindsubmit='orderSign'> <view> 单号: 0< ...

  6. Spider_Man_3 の selenium

    一:介绍 selenium最初是一个自动化测试工具,而爬虫中使用它主要是为了解决requests无法直接执行JavaScript代码的问题 selenium本质是通过驱动浏览器,完全模拟浏览器的操作, ...

  7. Vue.js 1.x 和 2.x 实例的生命周期

    在Vue.js中,在实例化Vue之前,它们都是以HTML的文本形式存在文本编辑器中.当实例化后将经历创建.编译.销毁三个主要阶段. 以下是Vue.js 1.x  实例的生命周期图示: Vue.js 1 ...

  8. 【程序员的吃鸡大法】利用OCR文字识别+百度算法搜索,玩转冲顶大会、百万英雄、芝士超人等答题赢奖金游戏

    [先上一张效果图]: 一.原理: 其实原理很简单: 1.手机投屏到电脑: 2.截取投屏画面的题目部分,进行识别,得到题目和三个答案: 3.将答案按照一定的算法,进行搜索,得出推荐答案: 4.添加了一些 ...

  9. 初识RabbitMQ,附RabbitMQ+PHP演示实例

    RabbitMQ是一个在AMQP基础上实现的企业级消息系统.何谓消息系统,就是消息队列系统,消息队列是""消费-生产者模型""的一个典型的代表,一端往消息队列中 ...

  10. removeClass()

    定义和用法 removeClass() 方法从被选元素移除一个或多个类. 注释:如果没有规定参数,则该方法将从被选元素中删除所有类. 语法 $(selector).removeClass(class) ...