1. let声明变量
- 变量不能重复声明(var可以重复声明),防止变量污染
- 块级作用域(只在代码块里面有效)
// if else while for
{
let girl ='emm';
}
console.log(girl); //此时会报错not define
- 不存在变量提升
console.log(song);
let song = 'pink';
//报错
- 不影响作用域链
{
{
let school = 'gdut';
function fn() {
console.log(school);
}
fn(); //输出gdut
}
}
let经典实例
//遍历绑定事件
for (let i = 0; i < items.length; i++) {
items[i].onclick = function () {
items[i].style.color = 'pink';
}
}
// !!改成let就可以直接用了
2. const定义常量
- 一定要赋初始值
//声明常量
const SCHOOL = 'gdut';
- 一般常量使用大写(潜规则)
- 常量的值不能修改
- 块级作用域
- 对于数组和对象的元素修改,不算对常量的修改,不会报错/
const TEAM = ['A', 'B', 'C', 'D'];
TEAM.push('MAC');
//地址没有变
3. 解构赋值
数组的解构
const F4 = ['A', 'B', 'C', 'D'];
let [a, b, c, d] = F4;
console.log(a);
console.log(b);
console.log(c);
console.log(d);
对象的解构
const zhao = {
name: '赵本山',
age: '18',
xiaopin: function () {
console.log('be able to');
}
};
4. 模板字符串
ES6引入新的声明字符串的方式 `` , '' , ""
- 声明
let str = '这也是一个字符串';
console.log(str,typeof str);
-
内容中可以直接出现换行符
-
变量拼接
let love = 'pink';
let out = `${love}是我最喜欢的颜色`;
console.log(out); //打印出: pink是我最喜欢的颜色
5. 简化对象
ES6允许在大括号里面,直接写入变量和函数,作为对象的属性和方法,使代码更加简洁
let name = 'pink';
let change = function () {
console.log('changeyou');
}
const school = {
name,
change
improve(){
console.log('changeyou');
}
}
console.log(school);
6. 箭头定义函数
ES6 允许使用[箭头] =>定义函数
- this 是静态的, this时钟指向函数声明时所在作用域下的 this 的值
function getName() {
console.log(this.name);
}
let getName2 = () => {
console.log(this.name);
}
window.name = 'pink';
const school = {
name: 'shang'
}
//直接调用
getName(); //pink
getName2(); //pink
//call方法调用
getName.call(school); //shang
getName2.call(school); //pink
- 不能作为构造实例化对象
let Person = (name, age) => {
this.name = name;
this.age = age;
}
let me = new Person('xiao', 30)
console.log(me); //报错
-
不能使用
arguements变量 -
箭头函数的简写
- 省略小括号,当形参有且只有一个的时候
let add = (n) => {
return n+n;
}
console.log(add(9));
2) 省略花括号,当代码体只有一条语句的时候,此时return必须省略,而且语句的执行结构就是函数的返回值
let add = (n) => return n+n;
console.log(add(9));
箭头函数的应用场景
箭头函数适合与this无关的回调,定时器,数组的方法回调。
箭头函数不适合与this有关的回调,事件回调,对象的方法
{
name:'pink',
getName:(){
this.name; //this指向的是这个对象
}
}
************************
{
name:'pink',
getName:() => {
this.name; //this指向的是外层作用域this的值
}
}
绑定事件
let items = document.getElementsById('item');
/*
items.addEventListener('click',function(){
let _this = this; //如果没这个语句,this指向window
setTimeout(function(){
console.log(this);
//当前作用域找不到就往外层找
_this.style.color = 'pink';
},2000)
})
*/
items.addEventListener('click',function(){
let _this = this;
setTimeout(() => {
console.log(this);
//this的值是静态的指向声明时所在作用域this的值(即items)
_this.style.color = 'pink';
},2000)
})
- 从数组中返回偶数的元素
const arr = [1, 6, 78, 4, 2, 99];
/*
const result = arr.filter(function (item) {
if (item % 2 === 0) {
return true;
} else {
return false;
}
})
*/
const result = arr.filter(item => item % 2 === 0);
console.log(result);
7. ES6允许给函数参数赋值初始值
- 形参初始值,具有默认值的参数,一般位置要靠后(潜规则)
function add(a, b, c=10) {
return a + b + c;
}
let result = add(1, 2, 3);
//如果3不传递,返回NaN,可以给c赋初始值
console.log(result);
- 与解构赋值结合
// function connect(options) {
// let host = options.host;
// let username = options.name;
// }
function connect({ host = '127.0.0.1', username, password, port }) {
console.log(host);
console.log(username);
}
connect({
host: 'localhost',
username: 'root',
password: 'root',
port: 3306
})
8. rest参数
- ES6引入了rest参数,用于获取函数的实参,用来代替
arguement。
// es5获取实参的方式
function date() {
console.log(arguments);
}
date('a', 'b', 'c'); //这个一个对象
// es6 rest参数
function date(...args) {
console.log((args)); //可以用filter some every map
}
date('a', 'b', 'c');
//这是一个数组
- rest参数必须要放到参数最后
function fn(a, b, ...args) {
console.log(a);
console.log(b);
console.log(args);
}
fn(1, 2, 3, 4, 5, 6);
// 1给a,2给b, 3456给...args
9. ES6扩展运算符
- [...] 扩展运算符能将【数组】转换为逗号分隔的【参数序列】
// 声明一个数组
const tfboys = ['yyqx', 'wjk', 'wy'];
// 声明一个函数
function chunwan() {
console.log(arguments);
}
chunwan(tfboys); //一个参数['yyqx', 'wjk', 'wy']
chunwan(...tfboys);
//三个参数 0:yyqx; 1:wjk; 2:wy 相当于chunwan('yyqx', 'wjk', 'wy');
扩展运算符应用
- 数组的合并
const kuaizi = ['zhangsan', 'lisi'];
const fenghuang = ['xiaoming', 'xiaohong'];
// const zuixuan = kuaizi.concat(fenghuang);
const zuixuan = [...kuaizi, ...fenghuang]; //返回一个合并数组
console.log(zuixuan);
- 数组的克隆
const sanzhihua = ['E', 'F', 'G'];
const sanyecao = [...sanzhihua];
console.log(sanyecao); //['E', 'F', 'G']
// 如果数组中有引入数据类型就是浅拷贝,否则是深度拷贝
- 将伪数组转换为真正的数组
const divs = document.querySelectorAll('div');
const divArr = [...divs];
console.log(divsArr);
10. Symbol的介绍和创建
ES6引入了一种新的初始数据类型Symbol,表示独一无二的值,类似于字符串的数据类型
- Symbol的值是唯一的,用来解决命名冲突的问题
- Symbol不能与其他数据进行运算
- Symbol不能用 for...in 遍历
// 创建Symbol
let s = Symbol();
// console.log(s, typeof s);
let s2 = Symbol('pink');
let s3 = Symbol('pink');
console.log(s2 === s3); //false
let s4 = Symbol.for('pink');
let s5 = Symbol.for('pink');
console.log(s4 === s5); //true
//不能与其他数据进行运算,会报错
7种数据类型
-
you are so niubility
-
u undefined
-
s string
-
o object
-
n null number
-
b boolean
给对象添加方法
let game = {
}
let methods = {
up: Symbol(),
down: Symbol()
};
game[methods.up] = function () {
console.log('up');
}
game[methods.down] = function () {
console.log('down');
}
console.log(game);
let youxi = {
name: '狼人杀',
[Symbol('say')]: function () {
console.log('fayan');
},
[Symbol('zibao')]: function () {
console.log('zibao');
}
}
console.log(youxi);
Symbol的内置值
a. Symbol.hasInstance
当其他对象使用instanceof运算符,判断是否为该对象实例时,会调用这个方法
class Person {
static [Symbol.hasInstance](param) {
console.log(param); //{} 获取了o的值
console.log('hello');
}
}
let o = {};
console.log(o instanceof Person);
b. Symbol.isConcatSpreadable
该属性等于的是一个布尔值,表示该对象用于Array.prototype.concat()时,是否会展开。
const arr = [1, 2, 3];
const arr2 = [4, 5, 6];
arr2[Symbol.isConcatSpreadable] = false;
console.log(arr.concat(arr2));
// 返回 [1,2,3,456]
11. 迭代器
迭代器是一种接口,为各种不同的数据结构提供统一的访问机制,任何数据结构只要部署Iterator接口,就可以完成遍历操作
- ES6创造了一种新的遍历命令 for...of循环,Iterator接口主要供for...of 消费
- 原生具备iterator接口的数据,可以用for of遍历
- Array
- Arguments
- Set
- Map
- String
- TypedArray
- NodeList
// 声明一个数组
const zimu = ['A', 'B', 'C', 'D'];
for (var v of zimu) {
console.log(v); //ABCD 保存键值
}
for (var v in zimu) {
console.log(v); //0123 保存键名
}
const zimu = ['A', 'B', 'C', 'D'];
let iterator = zimu[Symbol.iterator]();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
结果:
迭代器的应用
//声明一个对象
const banji = {
name: 'yiban',
stus: [
'zhangsan',
'lisi',
'xiaoming',
'xiaohong'
],
[Symbol.iterator]() {
// 索引变量
let index = 0;
let _this = this;
return {
next: function () {
if (index < _this.stus.length) {
const result = { value: _this.stus[index], done: false };
// 返回false 疯狂输出 没有完成
// 下标自增
index++;
return result;
} else {
return { value: undefined, done: true };
}
}
};
}
}
// 遍历这个对象
for (let v of banji) {
console.log(v);
}
// banji.stus.forEach(); 不是面向对象
12. 生成器
生成器函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同
生成器其实就是一个特殊的函数
function* gen() {
console.log('nihao');
}
let iterator = gen();
console.log(iterator); //一个迭代器对象,有一个next的方法
console.log(iterator.next()); //nihao
//遍历
for (let v of gen()) {
console.log(v); //每次返回结果是yield后的表达式或者自变量的值
}
function* gen() {
yield '一只'; //函数代码的分隔符
yield '两只';
yield '三只';
}
let iterator = gen();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
// 返回值如下 false表示遍历还没结束
生成器的函数参数
next方法可以传入实参,而且参数作为上一个yield语句的整体返回结果
function* gen(arg) {
console.log(arg);
let one = yield 111;
console.log(one);
let two = yield 222;
console.log(two);
let three = yield 333;
console.log(three);
}
// 执行获取迭代器对象
let iterator = gen('AAA');
console.log(iterator.next());
console.log(iterator.next('BBB'));
console.log(iterator.next('CCC'));
console.log(iterator.next('DDD'));
生成器函数实例
这样子就不用疯狂嵌套函数啦!
第一个实例~关于定时器,隔1s获取一个数据
// 异步编程 文件操作 网络操作(ajax request) 数据库操作
function one() {
setTimeout(() => {
console.log(111);
iterator.next();
}, 1000);
}
function two() {
setTimeout(() => {
console.log(222);
iterator.next();
}, 2000);
}
function three() {
setTimeout(() => {
console.log(333);
iterator.next();
}, 3000);
}
function* gen() {
yield one();
yield two();
yield three();
}
// 调用生成器函数
let iterator = gen();
iterator.next();
第二个实例
看起来是同步获取数据,实际上是异步噢~
// 模拟获取 用户数据 订单数据 商品数据
function getUsers() {
setTimeout(() => {
let data = '用户数据';
// 调用next方法并且将数据传入
iterator.next(data);
}, 1000);
}
function getOrder() {
setTimeout(() => {
let data = '订单数据';
iterator.next(data);
}, 1000);
}
function getGoods() {
setTimeout(() => {
let data = '商品数据';
iterator.next(data);
}, 1000);
}
function* gen() {
let users = yield getUsers();
console.log(users);
let order = yield getOrder();
console.log(order);
let goods = yield getGoods();
console.log(goods);
}
// 调用生成器函数
let iterator = gen();
iterator.next();
13. Promise
Promise是ES6引入的异步编程的新解决方案。语法上Promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果
- Promise构造函数:
Promise(excutor){} Promise.prototype.then方法Promise.prototype.catch方法
// 1. 引入fs模块
const fs = require('fs');
// 2. 调用方法读取文件
fs.readFile('./es6/test.md', (err, data) => {
// 如果失败,抛出错误
if (err) throw err;
// 如果成功
console.log(data.toString());
})
// 3. 使用Promise封装
const p = new Promise(function (resolve, reject) {
fs.readFile('/es6/test.md', (err, data) => {
// 判断如果失败 reject 调用 then 方法的第二个回调函数
if (err) reject(err);
// 如果成功 resolve 调用 then 方法的第一个回调函数
resolve(data);
})
})
p.then(function (value) {
console.log(value.toString());
}, function (reason) {
console.log('读取失败');
})
Promise封装ajax
// 接口地址:http://api.apiopen.top/getJoke
const p = new Promise((resolve, reject) => {
// 1. 创建对象
const xhr = new XMLHttpRequest();
// 2. 初始化
xhr.open("get", "http://api.apiopen.top/getJoke", true);
// 3. 发送
xhr.send();
// 4. 绑定事件,处理响应结果
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
// 表示成功
console.log(xhr.response);
} else {
console.error(xhr.status);
}
}
}
})
// 指定回调
p.then(function (value) {
console.log(value);
}, function (reason) {
console.error(reason);
})
promise then方法
- 创建promise对象
const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('用户数据');
}, 1000);
// 成功了就执行then的第一个回调函数
})
- 调用then方法 then方法的返回结果是 Promise 对象,对象状态由回调函数的执行结果决定
// 1. 如果回调函数中返回的结果是 非Promise 类型的属性,状态为成功,返回值为对象成功的值
p.then(value => {
console.log(value); // 用户数据
// 1. 非promise类型的属性
// return 123;
// 2. 是promise对象 如果这个promise返回成功,则then方法返回成功,反之成立
return new Promise((resolve, reject) => {
resolve('ok');
})
// 3. 抛出错误
// throw new Error('出错了');
}, reason => {
console.warn(reason);
})
// 链式调用
p.then(value => {
}).then(value => {
})
console.log(result);
promise链式调用
// 引入fs模块
const fs = require("fs");
// 使用promise实现
const p = new Promise((resolve, reject) => {
fs.readFile('es6/test1.md', (err, data) => {
resolve(data);
});
});
// p.then(value => {
// console.log(value.toString());
// })
// then成功失败都可,catch只能是失败的
p.then(value => {
return new Promise((resolve, reject) => {
fs.readFile('es6/test1.md', (err, data) => {
resolve([value, data]);
});
})
}).then(value => {
return new Promise((resolve, reject) => {
fs.readFile('es6/test3.md', (err, data) => {
// 压入
value.push(data);
resolve(value);
});
});
}).then(value => {
console.log(value.join('\r\n'));
})
promise catch
const p = new Promise((resolve, reject) => {
setTimeout(() => {
// 设置p对象的状态为失败,并设置失败的值
reject('出错了');
}, 1000);
})
p.catch(function (reason) {
console.warn(reason);
})
14. set()
let s = new Set();
let s2 = new Set(['1','2','3','4','4']);
// 元素个数
console.log(s2.size); // 4 元素去重
// 添加元素
s2.add('5');
// 删除元素
s2.delete('6');
// 检测
console.log(s2.has('5')); //true
// 清空
s2.clear();
// 遍历
for(let v of s2){
console.log(v); //遍历(也会去重)
}
Set集合事件
1.数组去重
let arr = [1,2,3,4,5,4,3,2,1];
let result = new Set(arr); // 此时result是一个集合
let result = [...new Set(arr)]; // 数组去重
2.交集
let arr = [1,2,3,4,5,4,3,2,1];
// 2. 交集
let arr2 = [4,5,6,5,6];
let result = [...new Set(arr)].filter(item => {
let s2 = new Set(arr2); // 4 5 6
if(s2.has(item)){
return true;
}else{
return false;
}
})
//或者也可以写成
// let result = [...new Set(arr)].filter(item => new Set(arr2).has(item))
console.log(result); // [4,5]
3. 并集
let union = new Set([...arr,...arr2]);//合并
console.log(union); // [1,2,3,4,5,6]
4. 差集
// 谁是主体结果是不一样的 arr有arr2没有的
let diff = [...new Set(arr)].filter(item => !(new Set(arr2).has(item)));
console.log(diff); // [1,2,3]
15. Map()
Map也实现了iterator接口,可以用扩展运算符和【for...of】进行遍历
// 声明Map
let m = new Map();
// 添加元素
m.set('name', 'pink');
m.set('change', function () {
console.log('改变你');
})
let key = {
school: 'pink'
};
m.set(key, ['guangzhou', 'shanghai', 'shenzhen']);
console.log(m.size);
console.log(m);
// 删除
m.delete('name'); m.get('change');
// 获取
console.log();
// 清除
m.clear();
// 遍历
for (let v of m) {
console.log(v);
}
16. class类
通过class关键字,可以定义类,新的class写法只是让对象原型的语法更加清晰
// es5
// 手机
function Phone(brand, price) {
this.brand = brand;
this.price = price;
}
// 添加方法
Phone.prototype.call = function () {
console.log('打电话');
}
let Huawei = new Phone('华为', 666);
Huawei.call();
console.log(Huawei);
//class
class Shouji {
// 构造方法 名字不能修改
constructor(brand, price) {
this.brand = brand;
this.price = price;
}
// 方法必须使用该语法,不能使用es5的对象完整形式
call() {
console.log('打电话');
}
}
let onePlus = new Shouji('1+', 999);
console.log(onePlus);
class静态成员
function Phone() {
}
Phone.name = '手机';
Phone.change = function () {
console.log('changethings');
}
let nokia = new Phone();
console.log(nokia.name);
// 实例对象和构造函数的原型对象是相通的,但是和函数对象是不通的
// 函数对象的属性是属于函数对象的,并不属于实例对象,这样称为静态成员
class Phone {
// 静态属性
static name = '手机';
static change() {
console.log('改变');
}
}
let nokia = new Phone();
console.log(nokia.name); // undefined
console.log(Phone.name); // 手机
// static标注的属性和方法,属于类,而不属于对象
类继承
es5
// 手机
function Phone(brand, price) {
this.brand = brand;
this.price = price;
}
Phone.prototype.call = function () {
console.log('打电话');
}
// 智能手机
function SmartPhone(brand, price, color, size) {
Phone.call(this, brand, price);
// this指向smartphone
this.color = color;
this.size = size;
}
// 设置子级构造函数的原型
SmartPhone.prototype = new Phone;
SmartPhone.prototype.constructor = SmartPhone;
// 声明子类的方法
SmartPhone.prototype.photo = function () {
console.log('拍照');
}
SmartPhone.prototype.playGame = function () {
console.log('玩游戏');
}
const chuizi = new SmartPhone('锤子', 999, '黑色', '5.5');
console.log(chuizi);
// 输出结果
es6
class Phone {
//构造方法
constructor(brand, price) {
this.brand = brand;
this.price = price;
}
// 父类的成员属性
call() {
console.log('打电话');
}
}
class SmartPhone extends Phone { // 必须写extends
// 构造方法
constructor(brand, price, color, size) {
super(brand, price) //super就是父类的contructor方法
this.color = color;
this.size = size;
}
phone() {
console.log('拍照');
}
playGame() {
console.log('玩游戏');
}
}
const chuizi = new SmartPhone('锤子', 999, '黑色', '5.5');
console.log(chuizi);
// 输出结果和上面是一样的~代码简洁了许多
class中的get和set
- get:通常是用来对动态属性进行封装,随着数据的变化而变化
- set:添加更多的控制和判断,是否合法。成功就赋值,失败则不赋值2
// get和post
class Phone {
get price() {
console.log('价格属性被读取了');
return '111';
}
set price(newVal) {
console.log('价格属性被修改了');
}
}
// 实例化对象
let s = new Phone();
console.log(s.price); //price()里面return的值
s.price = 'free'; // 触发set price()方法
17. 数值拓展
1. Object.is 判断两个值是否完全相等 跟===很像
2. Object.assiign(obj1,obj2) //合并 如果都有,后面覆盖前面的 如果前面没有就加上去
3. Object.setPrototypeof(school,cities) //设置原型对象
把
const school = {
name: 'shang'
}
const cities = {
xiaoqu: ['beijing', 'shanghai', 'shenzhen']
}
Object.setPrototypeOf(school, cities);
console.log(Object.getPrototypeOf(school));
console.log(school);
// 输出结果
