ES6的新特性
let关键字
作用和Var一样
let k;
let b,c,d
//初识值
let e=100
let声明变量的特性
-
变量不可以重复声明 ,为了防止变量名污染
let star='小米' let star='小明'
-
块级作用域,只在代码块中有效,如果出了代码块中无效
{ let girl='翠花' } console.log(girl)
-
不存在变量提升
console.log(obj) let obj=123131
-
不影响作用域链
<body> <div class="container"> <h2 class="page-header">点击切换颜色</h2> <div class="item"></div> <div class="item"></div> <div class="item"></div> </div> <script> // 获取元素 let item = document.querySelectorAll('.item') // 循环遍历并绑定事件 for (let i = 0; i < item.length; i++) { item[i].onclick = function () { // 修改当前元素的背景颜色 // this.style.background = 'pink' item[i].style.background = 'pink' } } { let i = 0 } console.log(i); { let i = 1 } { let i = 2 } </script> </body>
const 常量
特性
-
一定要赋初识值
const A //报错 //Uncaught SyntaxError: Missing initializer in const declaration
-
一般常量使用大写(潜规则)
const a=100
-
常量的值不可以修改
const a= 100 const a=123 'Uncaught SyntaxError: Identifier "a" has already been declared'
-
块级作用域
{ const PLYER='UZI' } console.log(PLYER) '报错:Uncaught ReferenceError: PLYER is not defined'
-
对于数字和对象的元素修改,不算做对常量的修改,不会报错
元素发生了变化,而元素的地址没有发生变化,不会报错 const TEAM=['UZI','MXLG','MINF','LETTme'] TeAM=100 //会报错
-
变量的结构赋值
ES6中 允许按照一定模式从数组和对象中提取值,对变量进行赋值。被称为"解构赋值"
1、数组的结构
const F4=['小沈阳','刘能','赵四','宋小宝']
let [xiao,liu,zhao,song]=F4
console.log(xiao,liu,zhao,song)
2、对象的结构
const zhao ={
name:"赵本山",
age:'不详',
xiaopin:function(){
console.log('演小品')
}
}
let {name,age,xiaopin}=zhao
ES6简化对象写法
ES6中,允许在大括号里面,直接写入变量和函数,作为对象的属性和方法
这样的书写方式更加简洁
let name='黑马程序员'
let change=function(){
console.log('我们可以改变你')
}
const school={
name,
change,
improve(){
console.log('我们可以提高你的代码更加简洁')
}
}
ES6中的箭头函数
ES6允许使用[箭头]
(=>) 定义函数
箭头函数的应用场景
箭头函数适合于this无关的回调, 定时器, 数组的方法回调
//之前
let fn=function(){console.log('ES6之前')}
let fun=(a,b)=>{
console.log('ES6之后')
return a+b
}
let result=fun(1,2)
console.log(result)
注意:
1、this是静态的,this始终
指向函数声明时所在的作用域下的this的值
function getName(){
console.log(this.name)
}
let gerName2=()=>{
console.log(this.name)
}
window.name='黑马程序员'
const school={
name:'ATFUIFU'
}
//直接调用
getName()
getName2()
//使用call方法调用
getName.call(school)
getName2.call(school)
2、不能作为构造实例化对象
let Person=(name,age)=>{
this.name=name
this.age=age
}
let me= new Person('xiao',40)
console.log(me)
//报错
'Uncaught TypeError: Person is not a constructor'
3、不能使用arguments变量
let fn=()=>{
console.log(arguments)
}
fn(1,2,3)
//报错
'Uncaught ReferenceError: arguments is not defined'
4、箭头函数的简写
-
省略小括号,当形参也只有一个的时候
let add=n=>{ return n+n } console.log(add(9))
-
省略花括号,当代码体只有一条语句的时候,此时
return
必须省略,而且语句执行的结果就是函数的返回值
let pow=(n)=>return n*n
console.log(pow(9))
箭头函数适合于this无关的回调, 定时器, 数组的方法回调
//实例1
// 需求1 点击dib 2s 后颜色变换
let ad = document.getElementById('ad')
// 绑定事件
ad.addEventListener('click', function () {
// 保存this的值 ES6之前
let _this = this;
// 定时器
// setInterval(function () {
// // 修改背景颜色 this 找不到当前的this
// // console.log(_this)
// }, 2000)
setInterval(() => {
// 这里的this就指的是function里的this
this.style.background = "skyblue"
}, 2000)
})
//实例二
// 需求2从数组中返回偶数的元素
const arr = [1, 2, 60, 34, 45, 5, 100]
const result = arr.filter(function (item) {
if (item % 2 === 0) {
return true
} else {
return false
}
})
const result = arr.filter(item => item % 2 === 0)
// 箭头函数适合于this无关的回调, 定时器, 数组的方法回调
ES6中的函数参数赋值初识值
1、形参初始值
function add(a,b,c=10){
return a+b+c
}
let result=add(1,2)
console.log(result)
2、与解构赋值结合使用
function connect({host='127.0.0.1',username,password,port}){
console.log(host)
console.log(username)
console.log(password)
console.log(port)
}
connect({
host:'loaclhost',
username:'root',
password:123456,
port:3306
})
rest参数
ES6中引入了rest 参数,用于获取函数的实参,用来带替arguments
//ES5 获取实参的方式
function date(){
console.log(arguments)
}
date(1,2,3,45,6,7,7,8)
///rest参数
function date(...args){
console.log(args)
}
console.log(1,3,4,5,6,7,8)
扩展运算符
概念
[…]扩展运算符能够将[数组]转换为逗号分割的[参数序列]
扩展运算符是放在实参的位置,rest参数是放在形参的位置
const tfboys=['易烊千玺','王俊凯','王源'] //转换为=>'易烊千玺','王俊凯','王源'
//声明一个函数
function chuwan(){
console.log(arguments)
}
chunwan(...tfboys) //chunwan('易烊千玺','王俊凯','王源')
扩展运算符的应用
-
数组的合并
const kuaizi=['王太利','肖央'] const fanghuang=['曾毅','玲花'] const zuixuanxiaopingguo=kuaizi.concat(fenghuang) const zuixuanxiaopingguo=[...kuaizi,...fenghuang] console.log(zuixuanxiaopingguo)
-
数组的克隆
const sanhihua=['E','G','M'] const sanyecai=[...sanzhihua] //['E','G','M'] console.log(sanyecai)
-
将伪数组转为正则的数组
<div></div> <div></div> <div></div> <script> const divs=document.querySelectorAll('div') const divArr=[...divs] console.log(divArr) </script>
Symbol
概念
ES6中引入了一种新的原始数据类型
symbol
,表示独一无二的值
,它是JavaScript
语言的第七种数据类型,是一种类似于字符串的数据类型symbol的特点
- symbol的值是唯一的,用来解决命名冲突的问题
- symbol值不能与其他数据进行运算
- symbol定义的对象属性不能使用
for..in
循环遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名
创建symbol
- 它可以作为对象的属性名,只有字符串和
symbol
类型才能用作对象的属性名 - 没有两个
symbol
的值是相等的
const symbol1 = Symbol(); const symbol2 = Symbol(); symbol1 === symbol2; // false const obj = {}; obj[symbol1] = 'Hello'; obj[symbol2] = 'World'; obj[symbol1]; // 'Hello' obj[symbol2]; // 'World'
尽管调用
Symbol()
让它看起来像是对象,实际上symbol
是 JavaScript 原始数据类型。把Symbol
当作构造函数来用new
会报错。const symbol1 = Symbol(); typeof symbol1; // 'symbol' symbol1 instanceof Object; // false // Throws "TypeError: Symbol is not a constructor" new Symbol();
私有属性
由于任何两个symbol
都是不相等的,在 JavaScript 里可以很方便地用来模拟私有属性。symbol
不会出现在 Object.keys()
的结果中,因此除非你明确地export
一个symbol
,或者用 Object.getOwnPropertySymbols()
函数获取,否则其他代码无法访问这个属性。
function getObj() {
const symbol = Symbol('test');
const obj = {};
obj[symbol] = 'test';
return obj;
}
const obj = getObj();
Object.keys(obj); // []
// 除非有这个 symbol 的引用,否则无法访问该属性
obj[Symbol('test')]; // undefined
// 用 getOwnPropertySymbols() 依然可以拿到 symbol 的引用
const [symbol] = Object.getOwnPropertySymbols(obj);
obj[symbol]; // 'test'
还有一个原因是symbol
不会出现在JSON.stringify()
的结果里,确切地说是JSON.stringify()
会忽略symbol
属性名和属性值:
const symbol = Symbol('test');
const obj = { [symbol]: 'test', test: symbol };
JSON.stringify(obj); // "{}"
用 Symbol
表示对象内部状态,可以很好地隔离用户数据和程序状态。有了它,我们就不再需要某些命名约定了,比如内部属性用'$'
开头。下次碰到需要定义私有属性的时候
模板字符串
在ES6之前我们通常是使用\
和+
来创建模板字符串
$("body").html("This demonstrates the output of HTML \
content to the page, including student's\
" + name + ", " + seatNumber + ", " + sex + " and so on.");
而对ES6来说
- 基本的字符串格式化,将表达式嵌入字符串中进行拼接。使用${}来设置
- ES6
直接
使用反引号(``)
$("body").html(`This demonstrates the output of HTML content to the page,
including student's ${name}, ${seatNumber}, ${sex} and so on.`);
二进制和八进制字面量
ES6
支持二进制和八进制的字面量,通过在数字前面添加0o
或者0O
即可将其转换为八进制值:
let oValue = 0o10;
console.log(oValue); // 8
let bValue = 0b10; // 二进制使用 `0b` 或者 `0B`
console.log(bValue); // 2
for…of 和 for…in
for...of
用于遍历一个迭代器,如数组:
let letters = ['a', 'b', 'c'];
letters.size = 3;
for (let letter of letters) {
console.log(letter);
}
// 结果: a, b, c
for...in
用来遍历对象中的属性:
let stus = ["Sam", "22", "男"];
for (let stu in stus) {
console.log(stus[stu]);
}
// 结果: Sam, 22, 男
ES6中的类
ES6
中支持class
语法,不过,ES6
的class
不是新的对象继承模型,它只是原型链的语法糖表现形式。
函数中使用 static
关键词定义构造函数的的方法和属性:
class Student {
constructor() {
console.log("I'm a student.");
}
study() {
console.log('study!');
}
static read() {
console.log("Reading Now.");
}
}
console.log(typeof Student); // function
let stu = new Student(); // "I'm a student."
stu.study(); // "study!"
stu.read(); // "Reading Now."
类中的继承和超集:
class Phone {
constructor() {
console.log("I'm a phone.");
}
}
class MI extends Phone {
constructor() {
super();
console.log("I'm a phone designed by xiaomi");
}
}
let mi8 = new MI();
extends 允许一个子类继承父类,需要注意的是,子类的
constructor
函数中需要执行super()
函数。
当然,你也可以在子类方法中调用父类的方法,如super.parentMethodName()。
有几点值得注意的是
:
- 类的声明不会提升
(hoisting)
,如果你要使用某个Class
,那你必须在使用之前定义它,否则会抛出一个ReferenceError
的错误- 在类中定义函数不需要使用
function
关键词
Promise
promise为异步编程提供了一种新的方式,Promise把未来将用到的值当做一等对象,Promise在很多前端库中已经有所支持了。
function timeout(duration = 0) {
return new Promise((resolve, reject) => {
setTimeout(resolve, duration);
})
}
var p = timeout(1000).then(() => {
return timeout(2000);
}).then(() => {
throw new Error("hmm");
}).catch(err => {
return Promise.all([timeout(100), timeout(200)]);
})
//11.对象字面量简写法
let type = 'quartz';
let color = 'rose';
let carat = 21.29;
const gemstone = {
type: type,
color: color,
carat: carat
};
console.log(gemstone);
新的数据解构Map,Set
这些是新加的集合类型,提供了更加方便的获取属性值的方法,不用像以前一样用hasOwnProperty
来检查某个属性是属于原型链上的呢还是当前对象的。同时,在进行属性值添加与获取时有专门的get
,``set` 方法。
//Sets
var a = new Set();
a.add("hello").add("world").add("hello");
a.size===2
a.has('hello')===true
//Maps
var b= new Map();
b.set("hello", 42);
b.set(s, 34);
b.get(s) == 34;
Generator生成器
作用
-
generator可以用来模拟同步的,内里本质还是回调异步,也就是说你还是要用异步的思维方式去写异步程序,但可以用同步的方式来表达。
-
generator不是专门为了模拟同步而生,是用来处理多个逻辑流的,也就是模拟并发。
简单使用
function* showWords() {
yield 'one';
yield 'two';
return 'three';
}
var show = showWords();
show.next() // {done: false, value: "one"}
show.next() // {done: false, value: "two"}
show.next() // {done: true, value: "three"}
show.next() // {done: true, value: undefined}
处理异步,生成队列,可适用于ajax多层嵌套等
function fn1(){
setTimeout(function(){
console.log('fn1')
g.next();
},1000)
}
function fn2(){
setTimeout(function(){
console.log('fn2')
g.next();
},1000)
}
function fn3(){
setTimeout(function(){
console.log('fn3')
g.next();
},1000)
}
function* gen(){
yield fn1();
yield fn2();
yield fn3();
return;
}
var g=gen();
g.next();
与一般函数的区别在与
(1)、function 与函数名之间有一个星号( * )存在,推荐星号(*)紧挨着function;
(2)、在函数体内部有yield表达式。yield是暂停标志。
(3)、Generator函数的调用不会立即执行,也不会返回函数运行的结果,而是返回一个指向内部状态的指针对象。即遍历器对象。只有调用next()方法时,才会改变指针的指向,指向下一个状态。