let
1、let变量不能重复声明
2、let块级作用域(全局、函数、eval等)
{
let name = "孙悟空";
}
console.log(name);//此处name不能访问
3、不存在变量提升
console.log(song);//会报错
let song = "歌曲";
4、不影响作用域链
let song = "歌曲";
function toSong() {
console.log(song);
}
toSong();//可以正常打印
const
用来声明常量
1、一定要赋初始值
2、一般常量使用大写
3、常量的值不能修改
4、块儿级作用域
5、对数组和对象中的元素修改,不算做对常量的修改,不会报错
const ARR = ["uzi"];
ARR.push("meikou");
变量的解构赋值
1、数组的解构
const FOUR = ["小沈阳","刘能","赵四","宋小宝"];
let [xiao,liu,zhao,song] = FOUR;
console.log(xiao,liu,zhao,song);//小沈阳 刘能 赵四 宋小宝
2、对象的解构
const zhao = {
name:"赵本山",
age:67,
skill: function() {
console.log("演小品");
}
};
let {name,age,skill} = zhao;
console.log(name,age);//赵本山 67
skill();//演小品
模版字符串
1、使用反引号` `
声明
let str = `我是一串模版字符串`;
2、内容中可以直接出现换行符
let str = `<ul>
<li>one</li>
<li>two</li>
</ul>`;
3、变量拼接
使用${ }
进行拼接
let name = `山东`;
let content = `${name}高铁里程第一`;
console.log(content);//山东高铁里程第一
对象的简化写法
es6允许在大括号用,直接写入变量和函数,作为对象的属性和方法
let name = `赵四`;
let skill = function() {
console.log(`会跳高`);
}
const info = {
name,
skill,
study(){
console.log(`学习很好`);
}
}
箭头函数
声明
()=> {}
等价于function() {}
例如:
let fn = (a, b) => {
return a + b;
};
console.log(fn(3,4));//7
特性
1、this
是静态的,this
始终指向函数声明时所在作用域下的this的值;
例如:使用call()
改变this
会报错
2、不能作为构造实例化对象
3、不能使用arguments变量,会报错
4、箭头函数的缩写
1、省略小括号
当形参有且只有一个的时候可以省略小括号
let add = n=> {
return n+ n;
}
2、省略花括号
当代码体只有一条语句的时候可以省略花括号,而且return也要省略。
let add = n => n + n;
函数参数默认值
1、形参初始值,具有默认值的参数,一般位置要靠后
function add(a,b,c=10) {
return a + b + c;
}
let fn = (a, b=10) => {
return a + b;
};
2、与解构赋值结合
function connect({ a = "123", b, c }) {
return a + b + c;
}
let result = connect({
b: "4",
c: "5"
});
console.log(result);//"12345"
rest参数
用于获取函数的实参,用来代替arguments
;
function date(...args) {
console.log(args);
}
date("a","b","c");//['a', 'b', 'c']
如果有多个参数,rest参数必须放在参数的最后。
扩展运算符
能将数组转换为逗号分隔的参数序列
const boys = [`a`, `b`, `c`];
function chunwan() {
console.log(arguments);
}
chunwan(...boys);//等价于chunwan(`a`, `b`, `c`);
可将伪数组转换为真正的数组
window.onload = () => {
let divs = document.getElementsByTagName(`div`);
let realDivs = [...divs];
console.log(realDivs);
}
Symbol---新数据类型
创建
let s = Symbol();
let s1 = Symbol(`描述字符串`);
let s2 = Symbol(`描述字符串`);
console.log(s1 == s2);//false
let s3 = Symbol.for("描述字符串");
let s4 = Symbol.for("描述字符串");
console.log(s3 == s4);//true
不能与其他数据进行运算
对象添加Symbol类型属性
方式一:
let game = { };
let methods = {
up: Symbol(),
down: Symbol()
};
game[methods.up] = function () {
console.log(`上`);
};
game[methods.down] = function () {
console.log(`下`);
};
console.log(game);
方式二:
let game = {
name: `三国杀`,
[Symbol(`say`)]: function () {
}
}
console.log(game);
Symbol内置属性
1、Symbol.hasInstance
当其他对象使用instanceof
运算符,判断是否为该对象实例时,会调用这个方法。
class Person {
static [Symbol.hasInstance](){
console.log("我被用来检测类型的");
return false;
}
}
let obj = {};
console.log(obj instanceof Person);
2、Symbol.isConcatSpreadable
对象的该属性等于的是一个布尔值,表示该对象用于Array.prototype.concat()
时,是否可以展开。
const arr = [1,2,3];
const arr2 = [4,5,6];
arr2[Symbol.isConcatSpreadable] = false;
console.log(arr.concat(arr2));
3、其他属性
属性 | 含义 |
---|---|
Symbol.unscopables |
该对象指定了使用with 关键字,哪些属性会被with 环境排除 |
Symbol.match |
当执行str.match(myObject) 时,如果该属性存在,会调用它,返回该方法的返回值。 |
Symbol.replace |
当该对象被str.replace(myObject) 方法调用时,会返回该方法的返回值 |
Symbol.search |
当该对象被str.search(myObject) 方法调用时,会返回该方法的返回值 |
Symbol.split |
当该对象被str.split(myObject) 方法调用时,会返回该方法的返回值 |
Symbol.iterator |
对象进行for...of 循环时,会调用该方法,并返回该对象的默认遍历器 |
Symbol.toPrimitive |
该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原型类型值 |
Symbol.toStringTag |
在该对象上面调用toString 方法时,返回该方法的返回值 |
Symbol.species |
创建衍生对象时,会使用该属性 |
说白了
Symbol
就是扩展了对象的功能。
迭代器
迭代器(iterator
)是一种接口,为各种不同的数据提供统一的访问机制;任何数据结构只要部署iterator
属性,就可以完成遍历操作。
1、es6创建了新的遍历命令for...of
,iterator
接口,主要提供for...of
消费;
2、原生具备iterator
接口的数据(可用for...of
遍历):
Array
Arguments
Set
Map
String
TypeArray
NodeList
3、工作原理:
1)创建一个指针对象,指向当前数据结构的起始位置;
2)第一次调用对象的next
方法,指针自动指向数据结构的第一个成员;
3)接下来不断调用next
方法,指针一致往后移动,直到指向最后一个成员;
4)每调用next
方法返回一个包含value
和done
属性的对象。
const xiyou = [`唐僧`, `孙悟空`, `猪八戒`, `沙和尚`];
let iterator = xiyou[Symbol.iterator]();
console.log(iterator.next());//{value: '唐僧', done: false}
console.log(iterator.next());//{value: '孙悟空', done: false}
console.log(iterator.next());//{value: '猪八戒', done: false}
console.log(iterator.next());//{value: '沙和尚', done: false}
console.log(iterator.next());//{value: undefined, done: true}
自定义遍历数据
const xiyouji = {
name: `西游记`,
persons: [`唐僧`, `孙悟空`, `猪八戒`, `沙和尚`],
//工作原理:1)创建一个指针对象,指向当前数据结构的起始位置;
[Symbol.iterator]() {
let index = 0;
let _this = this;
return {
//2)第一次调用对象的```next```方法,指针自动指向数据结构的第一个成员;
next: function () {
if (index < _this.persons.length) {
const result={value: _this.persons[index],done: false};
//3)接下来不断调用```next```方法,指针一致往后移动,直到指向最后一个成员;
index++;
//4)每调用```next```方法返回一个包含```value```和```done```属性的对象。
return result;
} else {
return {value: undefined, done: true};
}
}
}
}
};
for (const person of xiyouji) {
console.log(person);
}
生成器
其实就是一个特殊的函数;
异步编程,纯回调函数:node
、fs
、ajax
、mongodb
声明:声明函数,函数名前加*
,通过yield
把函数分为多段,每次调用next
方法都会执行一段
function* gen() {
console.log(`第一段`);
yield `1`;
console.log(`第二段`);
yield `2`;
console.log(`第三段`);
yield `3`;
console.log(`第四段`);
}
// let iterator = gen();
// iterator.next();
// iterator.next();
// iterator.next();
// iterator.next();
for (const y of gen()) {
console.log(y);
}
//输出结果
/*
第一段
1
第二段
2
第三段
3
第四段
*/
生成器函数参数
next()方法是可以传参的,会作为yield的返回结果
function* gen(arg) {
console.log(arg);
let one = yield `1`;
console.log(one);
let two =yield `2`;
console.log(two);
let three = yield `3`;
console.log(three);
}
let iterator = gen(`AAA`);
console.log(iterator.next());//AAA {value: '1', done: false}
console.log(iterator.next("BBB"));//BBB {value: '2', done: false}
console.log(iterator.next("CCC"));//CCC {value: '3', done: false}
console.log(iterator.next("DDD"));DDD {value: undefined, done: true}
生成器函数实例
function one() {
setTimeout(() => {
console.log(111);
iterator.next();
}, 1000);
}
function two() {
setTimeout(() => {
console.log(222);
iterator.next();
}, 1000);
}
function three() {
setTimeout(() => {
console.log(333);
iterator.next();
}, 1000);
}
function *gen() {
yield one();
yield two();
yield three();
}
let iterator = gen();
iterator.next();
Promise
是es6
引入的异步编程的新解决方案,Promise
是一个构造函数;
用来封装异步操作并可以获取其成功或失败的结果。
1)
Promise
构造函数:Promise(excutor){}
2)Promise.prototype.then
方法
3)Promise.prototype.catch
方法
创建
成功调用resolve方法获取数据,失败调用reject方法返回错误。
const p = new Promise(function (resolve, reject) {
setTimeout(() => {
let data = `数据库中的用户数据`;
//成功
resolve(data);
//ject(`失败`);
}, 1000);
});
p.then(function (value) {
//成功
console.log(value);
}, function (reason) {
//失败
console.error(reason);
});
Promise封装读取文件
需要Node.js
环境
const fs = require(`fs`);
const p = new Promise(function (resolve, reject) {
fs.readFile(`./es6/为学.md`, (error, data) => {
if (error) reject(error);
resolve(data);
});
});
p.then(function (value) {
console.log(value.toString());
}, function (reason) {
console.error(reason);
});
Promise封装Ajax请求
const p = new Promise(function (resolve, reject) {
//创建对象
const xhr = new XMLHttpRequest();
//初始化
xhr.open("GET", "https://api.apiopen.top/getJoke");
//发送
xhr.send();
//绑定事件处理结果
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
//判断是200-299
if (xhr.status >= 200 && xhr.status < 300) {
resolve(xhr.response);
} else {
reject(xhr.status);
}
}
};
});
p.then(function (value) {
console.log(value);
}, function (reason) {
console.error(reason);
});
Promise嵌套处理多个请求
const fs = require(`fs`);
const p = new Promise(function (resolve, reject) {
fs.readFile(`./es6/为学.md`, (error, data) => {
if (error) reject(error);
resolve(data);
});
});
p.then(function (value) {
//这里返回一个Promise对象,便于then接收
return new Promise(function (resolve, reject) {
fs.readFile(`./es6/爱莲说.md`, (error, data) => {
if (error) reject(error);
resolve([value, data]);
});
})
}, function (reason) {
console.error(reason);
}).then(value => {
console.log(value.join(`\r\n`));
}, reason => {
console.error(reason);
});
catch方法
相比then
方法,catch
方式只指定失败的参数
p.catch(function (reason) {
console.error(reason);
});
集合Set
声明
Set
可以对数组进行去重
let s = new Set([`1`,`2`,`3`,`1`,`2`]);
console.log(s);// 1 2 3
方法
add
添加
delete
删除
has
检查
clear
清空
s.add(`6`);
s.delete(`1`);
console.log(s.has(`2`));
s.clear();
可以使用for...of
遍历
for (const n of s) {
console.log(n);
}
实践
1、数组去重
使用...
把Set
转回数组
let arr = [`1`, `2`, `3`, `1`, `2`];
let result = [...new Set(arr)];
console.log(result);
2、交集
let arr = [`1`, `2`, `3`, `1`, `2`];
let arr2 = [`1`, `2`, `3`, `5`, `6`];
let result = [...new Set(arr)].filter(item=>(new Set(arr2)).has(item));
console.log(result);
3、并集
let arr = [`1`, `2`, `3`, `1`, `2`];
let arr2 = [`1`, `2`, `3`, `5`, `6`];
let result = [...new Set([...arr,...arr2])];
console.log(result);
注意:
...数组
是把数组转化为以逗号隔开的字符串
4、差集
相当于交集取反
let result = [...new Set(arr)].filter(item=>!(new Set(arr2)).has(item));
注意前后差集是不一样的
Map
声明
键值对形式,键值可以是字符串、对象、函数等等
let m = new Map();
属性方法
set
添加
size
大小
delete
删除
get
获取
clear
清空
m.set(`name`,`名字`);
console.log(m.size);
m.delete(`name`);
console.log(m.get(`name`));
m.clear();
还可以通过for...of
遍历
for (const v of m) {
console.log(v);
}
遍历后v
是一个数组,第一个元素是key
,第二个元素是value
Class---类
声明
class Phone {
//必须使用constructor关键字,不能修改
constructor(brand, price) {
this.brand = brand;
this.price = price;
}
//必须使用call(){}语法
call() {
console.log(`我可以打电话`);
}
}
let apple = new Phone(`iPhone 17`,5999);
console.log(apple);
class静态成员
类的属性和方法是属于类的,不是属于实例的
class Phone {
static name = `手机`;
static change() {
console.log(`我可以改变世界`);
};
}
let nokia = new Phone();
console.log(nokia.name);//undefined
console.log(Phone.name);//手机
Phone.change();//我可以改变世界
class继承
class SmartPhone extends Phone {
constructor(brand, price, color, size) {
super(brand, price);
this.color = color;
this.size = size;
}
}
let xiaomi = new SmartPhone(`小米`,799,`黑色`,`4.7inch`);
console.log(xiaomi);
xiaomi.call();
子类重写父类方法
子类中声明一个和父类相同的方法,即实现重写
class的getter和setter方法
class Car {
constructor(price) {
this._price = price;
}
get price() {
console.log(`走getter了`);
return this._price;
}
set price(newValue) {
console.log(newValue);
this._price = newValue;
}
}
let car = new Car();
car.price = `30w`;
console.log(car.price);
数值/对象方法扩展
扩展 | 含义 |
---|---|
Number.EPSILON |
属性,表示最小精度,用于判断浮点数是否相等,如果两个数的差小于该值,就判断这两个数相等 |
Number.isFinite |
方法,检测一个数值是否为有限数 |
Number.isNaN |
方法,检测一个数值是否为NaN
|
Number.parseInt 、Number.parseFloat
|
方法,字符串转整数、浮点数 |
Number.isInteger |
方法,判断一个数是否为整数 |
Math.trunc |
方法,将数字的小数部分抹掉 |
Math.sign |
方法,判断一个数到底是正数(返回1)、负数(返回-1)、还是零(返回0) |
进制 |
0b 开头二进制0o 开头八进制0x 开头十六进制 |
Object.is |
方法,判断两个值是否完全相等 |
Object.assign |
方法,对象的合并 1、如果参数相同,后面对象会把前面对象覆盖 2、不同会合并 |
Object.setPrototypeOf 、Object.getPrototypeOf
|
方法,设置原型对象、获取原型对象 |