1. 块级作用域绑定
1.1 let变量声明及声明特性
- 变量不可以重复定义 (var可以)
- 块级作用域 还有全局 函数 eval
- 不存在变量的提升
- 不影响作用域链
小练习:
1.2 const
注意:
- 一定要赋值
- 一般常量使用大写
- 常量的值不能修改下
- 也是块级作用域
- 对于数组和对象的元素的修改,不算是对常量的修改 不会报错
a. 声明常量
const SCHOOL=“西安”;
1.3 解构赋值
ES6允许按照一定的模式从数组和对象中提取值,对变量进行赋值
- 数组结构
- 对象的解析
2.模板字符串
ES6引入新的声明字符串的方式,[``] ’ ’ " "
模板字符串的特点:
- 内容中可以直接出现换行符
- 变量拼接
/*ES6引入新的声明字符串的方式 【``】 ' ' " "
*/
/*1. 声明:*/
let str=`我是一个字符串哦`;
console.log(str,typeof str);
/**
* 特性:
* 1. 内容中可以直接出现换行符
* 2. 变量拼接
*/
let kk =`<ul><li>沈腾</li><li>玛丽</li><li>艾伦</li><li>费翔</li></ul>`
let man=`kunkun`;
let things=`${man}真厉害`;
console.log(things);
3.对象的简化写法
1. ES6允许大括号里面,直接写入变量和函数,作为对象的属性和方法
2.ES6声明函数变简单了 取消了function
ES6以前:
const abc={
up:function(){
}
}
ES6:
const abc={
up(){
}
}
4.箭头函数
ES6允许使用箭头函数:(=>)来定义函数
ES6之前:
声明一个函数:
let fn=function(){
}
ES6:
let fn =(形参列表)=>{
函数的实体
}
调用函数:
let result=fn(实参);
1. this是静态的,this始终指向函数声明时,所在作用域下的this的值(很重要)
并无自己的this
2. 不能作为构造函数实例化对象
3. 不能使用arguments变量
let fn=()=>{
console.log(arguments)}
4.箭头函数的简写
a. 省略小括号:当形参有且仅有1个
let add=(n)=>{
return n+n;
}
可以换成: let add=n=>{
return n+n;
}
b.省略花括号:当代码只有一条语句的时候可以省略,此时return 必须省略 ,而且语句的执行结果就是函数的返回值
let pow=(n)=>n*n;
console.log(pow(8));
4.1 箭头函数的实践
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>箭头函数</title>
<style type="text/css">
div{
width:200px;
height: 200px;
background-color: chartreuse;
}
</style>
</head>
<body>
<div id="ad">
</div>
<script >
/*需求:点击 div后两秒将颜色切换为粉色
*/
//1. 获取元素
let ad=document.getElementById("ad");
/*绑定事件*/
ad.addEventListener("click",function(){
//定时器:
setTimeout( () => {
//修改背景颜色
this.style.backgroundColor="pink";
},2000)
});
//2.从数组中返回是偶数的元素
const str=[100,200,201,206,205];
const result=str.filter(function (arr) {
if(arr%2===0){
return true;
}else {
return false;
}
});
console.log(result);
const results=str.filter(item=>item%2===0
);
console.log(results);
/**
* 箭头函数适合与this无关的问题,定时器,数组的方法回调
* 箭头函数不适合与this有关的回调,事件回调,对象的方法
*/
</script>
</body>
</html>
箭头函数适合与this无关的问题,定时器,数组的方法回调 箭头函数不适合与this有关的回调,事件回调,对象的方法
5.函数参数的默认值
ES6允许给函数参数赋值初始值
- 形参初始值: 具有默认值的参数,一般位置要靠后(潜规则)
- 与结构赋值结合使用
//与结构赋值结合:
function connect({host='127.0.0.1',username,password,prot}) {
console.log(host);
console.log(username);
console.log(password);
console.log(prot);
}
connect({
host:'localhost',
username:'kunkun',
password:"tjk",
prot:3306
})
6. rest参数
ES6 引入rest参数,用于获取函数的实参,用来代替arguments
<body>
<script >
//获取实参的方式:
function date() {
console.log(arguments);
}
date('kunkun','tjk','田甲坤');
date1('kunkun','tjk','田甲坤');
function date1(...args) {
console.log(args);
}
</script>
</body>
区别:arguments 获取的数据是object类型的数据
rest参数是数组类型的==可以使用数据的api
rest参数必须放在参数之后
7.扩展运算符
...
扩展 运算符能将数组转化为逗号分隔的参数序列
<script >
const tfbosys=['易烊千玺','王元','王俊凯'];
function chunwan() {
console.log(arguments)
};
chunwan(tfbosys);
chunwan(...tfbosys);
</script>
7.1 扩展运运算符的应用-数组的合并
//1. 数组的合并
const kuaizi=['王太利','小样'];
const fenghuangchuanqi=['增益','零花'];
const result=[...kuaizi,...fenghuangchuanqi];
console.log(result);
7.2 扩展运算符的应用-数组的克隆
<script >
//数组的克隆
const sanzhihua=['B','G','M'];
const sanyecao=[...sanzhihua];
console.log(sanyecao);
</script
7.3将伪数组转化为数组
<body>
<div></div>
<div></div>
<div></div>
<script >
//将伪数组转化为数组
const divs=document.querySelectorAll("div");
console.log(divs);
const divss=[...divs];
console.log(divss);
</script>
8.symbol 的介绍与创新
8.1 Symbol对象的创建
ES6引入一种新的数据类型symbol,表示独一无二的值,是一种类似与字符串的数据类型
- 特点:
- Symbol的值是唯一的,用来解决命名冲突问题
- Symbol的值不能与其他数据类型相运算
- Symbol定义的对象属性,不能使用for in循环遍历,但可以使用Relect.ownKeys来获取对象的所有键名
<script >
//symbole的介绍
//(1)创建Symbol
let s= Symbol();
console.log(s ,typeof s);
//(2)创建Symbol
let s2=Symbol("tjk");
let s3=Symbol("Kunkun"); //加入参数只是对该Symbol对象进行描述.无实际作用
console.log(s2===s3);
//(3)创建Symbol 此方法创建了一个symbol对象 描述具有实际作用,用以确定对象一致
let s4=Symbol.for("kunkun");
let s5=Symbol.for("kunkun");
console.log(s4===s5);
console.log(s4,typeof s4);
/**
* 注意事项:
* 1. 不能与其他数据进行运算
* 2. 那么js的数据类型有USONB
*/
</script>
8.2 对象添加symbol类型的属性
8.2.1:第一种:
<script >
//symbole向对象中添加方法 up down
let game={
name:"tjk",
up:function (){},
down:function () {}
}
//声明一个对象:
let methods={
up:Symbol(),
down:Symbol()
};
game[methods.up]=function () {
console.log("我可以改变形状");
};
game[methods.down]=function () {
console.log("我可以快速的下降");
};
console.log(game)
</script>
8.2.2 第二种:
//第二种:
let youxi={
name:"狼人杀",
[Symbol('say')]:function () {
console.log("我可以发言");
},
[Symbol("自爆")]:function () {
console.log("zibaol ");
}
}
console.log(youxi);
8.3 Symbol的内置属性
除了定义自己使用的 Symbol 值以外, ES6 还提供了 还提供了 11个内置的 Symbol值指向语言内部使用的方法。 可以称这些方法为魔术,因它们会在特定的场景下自动执行。
Symbol.hasInstance | 当其他对象使用 instanceof运算符,判断是否为该对对象的实例,会调用这个方法 |
Symbol.isConcatSpreadable | 对象的 Symbol.isConcatSpreadable属性等于的是一个 布尔值,表示该对象用于 Array.prototype.concat()时, 是否可以展开。 是否可以展开。 |
Symbol.species | 创建衍生对象时,会使用该属性 |
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.iterator方法, 返回该对象的默认遍历器 |
Symbol.toPrimitive | 该对象被转为原始类型的值时,会调用这个方法,返回该对象应的原始类型值。 |
Symbol. toStringTag | 在该对象上面调用返回该方法的返回值 |
Symbol. unscopables | 该对象指定了使用 with关键字时,哪些属性会被 with环境排除。 |
9.迭代器
9.1 迭代器的基本知识
迭代器(iterator) 是一种接口,为各种不同的数据结构提供统一的访问机制,任何数据结构只要部署iterator接口,就可以完成遍历操作
1)ES6 创造了一种新的遍历命令 for…of,iterator主要供for…of消费
2)原生具备iterator接口的数据
array,Arguments,set,map,string,TypedArray,nodeList
3)工作原理:
创建一个指针对象,指向当前的 数据结构的起始位置
第一个调用对象的next方法,指针自动指向数据结构的第一个成员
接下来不断调用next方法,指针一直往后移,直到最后一个对象
每调用next方法返回一个包含value和done属性的对象
注意:需要自定义遍历数据的时候,要想到迭代器
for in
for of
9.2 自定义迭代器遍历数据
<script >
const stu={
name:"kunkun",
stus:[
"xiaoming",
"xiaohong",
"xiaoliang",
"xaiozhang"
],
//增加迭代器接口
[Symbol.iterator](){
let index=0;
// let _this=this;
return {
//指针函数用以方便this的指定
next:() =>{
if (index<this.stus.length){
const result={value:this.stus[index],done:false};
index++;
return result;
}else{
return {value:undefined,done:true};
}}}}}
//使用迭代器遍历数据
for (let v of stu){
console.log(v);
}
</script>
10. 生成器
10.1 生成器的基础
<script >
//生成器其实就是一个特殊的函数
//异步编程 纯回调函数
function *gen() {
console.log("111");
yield '11111111'; //函数代码的分隔符
console.log("222");
yield '22222222';
console.log("333");
yield '33333333';
console.log("444");
yield '44444444';
}
let iterator=gen();//调用后并没执行
iterator.next();//执行了
iterator.next();
iterator.next();
iterator.next();
</script>
生成器函数声明的时候必须在function后加* ,调用的时候直接调用不会执行,调用必须用next函数才可执行,并且执行一次只能在一块代码分割符中的代码
10.2 生成器的参数
<script >
//生成器其实就是一个特殊的函数
//异步编程 纯回调函数
function *gen(args) {
console.log(args);
let one= yield '11111111'; //函数代码的分隔符
console.log(one);
let two=yield '22222222';
console.log(two);
let three= yield '33333333';
console.log(three);
let four= yield '44444444';
console.log(four);
}
//执行获取迭代器对象
let iterator=gen('AAA');//调用后并没执行
//next 方法可以传入实参
console.log(iterator.next());
console.log(iterator.next("bbb"));//第二次调用next语句,传入的实参是作为第一个yield整体的返回结果
console.log(iterator.next('ccc'));
console.log(iterator.next('ddd'));
</script>
第二次调用next 的方法,传入的参数是作为第一个yeild的语句的返回值结果
10.3 生成器的实例
<script >
//异步编程:文件操作 数据库操作 网络操作 (ajax request)
//1s后控制台输出111 2s后控制台输出222 3s后红纸太输出333
--第一种:
/* setTimeout(()=>{
console.log("111");
setTimeout(()=>{
console.log("222");
setTimeout(()=>{
console.log("333"); //地狱回调
},3000)
},2000)
},1000)*/
--第二种
//用生成器函数
function one(){
setTimeout(()=>{
console.log("111");
iter.next();
},1000)
}
function two(){
setTimeout(()=>{
console.log("222");
iter.next();
},2000)
}
function three(){
setTimeout(()=>{
console.log("333");
},3000)
}
function *iterator() {
yield one();
yield two();
yield three();
}
let iter=iterator();
iter.next();//这样做可以避免地狱回调
</script>
10.4生成器实例2
<script >
//模拟获取, 用户数据 订单数据 商品数据
function getUser() {
setTimeout(()=>{
let data='用户数据';
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 user= yield getUser();
console.log(user);
let order=yield getOrder();
console.log(order);
let goods= yield getGoods();
console.log(goods);
}
//调用生成器函数
let iterator=gen();
iterator.next();
</script>
11.Promise
11.1 介绍和基本使用
promise是ES6引入的异步编程的新解决方案,语法上promise是一个构造函数,用来封装异步操作,并可以获得其成功和失败的结果
- promise构造函数:Promise(excutor){}
- Promise.prototype.then方法
- Promise.prototype.catch方法
<script>
//实例化promise对象
const p=new Promise(function (resolve ,reject) {
setTimeout(function () {
let data='数据库中的数据';
//resolve//表示成功
// resolve(data);
let error='数据抽取失败';
reject(error);//表示失败了
},1000)
});
//调用promise对象的then方法
p.then(function (value) {
//成功的参数是value
console.log(value);
},function (reason) {
//失败的参数是reason
console.error(reason);
})
</script>
11.2 promise-ajax
<script>
const p=new Promise((resolve,reject)=>{
//创建对象
const xhr=new XMLHttpRequest();
//初始化
xhr.open('GET','https://api.apiopen.top/getJoke');
//发送
xhr.send();
//绑定事件
xhr.onreadystatechange=function () {
//判断
if (xhr.readyState===4){
//判断响应状态
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);
})
</script>
11.3 Promise.then 的返回值
调用then方法,then方法的返回结果是promise对象,对象状态由回调函数的执行结果决定
- 如果回调函数中返回结果是非promise类型的属性,状态为成功,返回值为对象的成功
- 返回值类型还可以是promise 类型的
- 还可以链式调用
catch方法:
<script>
const p=new Promise((resolve,reject)=>{
setTimeout(()=>{
//设置p对象的状态为失败,并设置失败的值
reject("出错了!");
},1000);
});
p.catch((reason)=>{
console.warn("出错了");
})
</script>
12 集合
12.1 set集合
<script>
const s1=new Set();
const s2=new Set(['大事儿','小事儿','好事儿','坏事儿','小事儿']);//会自动清除重复的数据
console.log(s2);
s2.add('tjk');//添加数据
s2.delete('小事儿');//删除数据
console.log( s2.has('大事儿'));//查看数据是否存在
//清空
s2.clear();
console.log(s2);
//for .. of循环遍历
for (let ss2 of s2){
console.log(ss2);
}
</script>
12.2 Set集合实践
<script>
let arr=[1,2,2,3,4,5,6,4,5,6,7,8,9];
//1.数组去重
let result=new Set(arr);
console.log(result);
//2.交集
let arr2=[2,3,5,6];
let result2=[...new Set(arr)].filter(item=>{
let s2=new Set(arr2);
if(s2.has(item)){
return true;
}else{
return false;
}
})
console.log(result2);
//3.并集
let union=[...arr,...arr2];
console.log(union);
let result3=new Set(union);
console.log(result3);
//4.差集
let diff=[...new Set(arr)].filter(item=>!(new Set(arr2).has(item)));
console.log(diff);
</script>
12.3 map集合
ES6提供了Map数据结构。它类似于对象, 也是键值对集合
<script>
//声明Map
let m=new Map();
//添加元素
m.set("name",'tjk');
console.log(m);
m.set('key',['中国','陕西','韩城']);
//删除
m.delete('name');
console.log(m);
//获取
console.log(m.get('key'));
//for of
for (let mm of m){
console.log(mm);
}
//清空
m.clear();
</script>
13 Class
引入class类的概念是为了将ES6表现得更像传统语言的写法,使对象的原型更加清晰,更像是面向对象编程
ES5利用构造方法来实现实例化对象
<script>
//手机
function Phone(brand,price) {
this.brand=brand;
this.price=price;
}
//添加方法
Phone.prototype.call=function () {
console.log("我可以打电话");
}
//实例化对象
let huawie=new Phone('华为','5999');
huawie.call();
console.log(huawie);
</script>
ES6
class Phone{
//构造方法,名字不能重复
constructor(brand,price){
this.brand=brand;
this.price=price;
}
//方法必须使用该语法
call(){
console.log("我可以打电话");
}
}
let huawei=new Phone("1+",'59999');
huawei.call();
console.log(huawei);
13.1 Class静态变量
<script>
class Phone{
//构造方法,名字不能重复
static name='手机';//是属于类的name 不是实例化对象的name
static change(){
console.log("是吗,是的");
}
}
let nokia=new Phone();
console.log(nokia.name);
console.log(Phone.name);
</script>
类中的静态变量和方法,是属于类的,重新实例化以后不属于实例化对象
13.2 ES5的构造函数和继承
<script>
//手机
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.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('锤子',2499,'黑色','5.5inch');
console.log(chuizi);
</script>
13.3 ES6类的继承
<script>
class phone{
//构造函数
constructor (brand,price){
this.brand=brand;
this.price=price;
}
//成员属性
call(){
console.log("我可以打电话");
}
}
//子类
class smartPhone extends phone{
constructor(brand,price,color,size){
super(brand,price);
this.color=color;
this.size=size;
}
puoto(){
console.log("我可ui拍照");
}
palyGanme(){
console.log("我可以玩游戏");
}
}
const xiaomi=new smartPhone("小米",'3444','heise','5.99' );
console.log(xiaomi);
xiaomi.palyGanme();
xiaomi.puoto();
</script>
13.4 Get 和Set
<script>
// get 和 set
class Phone{
get price(){
console.log("价格属性被读取了");
return 'iloveyou';
}
set price(newVal){
console.log('价格属性被修改了');
}
}
//实例化对象
let s = new Phone();
// console.log(s.price);
s.price = 'free';
</script>
14.其余细节
14.1 数值扩展
<script>
//0. Number.EPSILON 是 JavaScript 表示的最小精度
//EPSILON 属性的值接近于 2.2204460492503130808472633361816E-16
function equal(a, b){
if(Math.abs(a-b) < Number.EPSILON){
return true;
}else{
return false;
}
}
console.log(0.1 + 0.2 === 0.3);
console.log(equal(0.1 + 0.2, 0.3))
//1. 二进制和八进制
let b = 0b1010;
let o = 0o777;
let d = 100;
let x = 0xff;
console.log(x);
//2. Number.isFinite 检测一个数值是否为有限数
console.log(Number.isFinite(100));
console.log(Number.isFinite(100/0));
console.log(Number.isFinite(Infinity));
//3. Number.isNaN 检测一个数值是否为 NaN
console.log(Number.isNaN(123));
//4. Number.parseInt Number.parseFloat字符串转整数
console.log(Number.parseInt('5211314love'));
console.log(Number.parseFloat('3.1415926神奇'));
//5. Number.isInteger 判断一个数是否为整数
console.log(Number.isInteger(5));
console.log(Number.isInteger(2.5));
//6. Math.trunc 将数字的小数部分抹掉
console.log(Math.trunc(3.5));
//7. Math.sign 判断一个数到底为正数 负数 还是零
console.log(Math.sign(100));
console.log(Math.sign(0));
console.log(Math.sign(-20000));
</script>
14.2 对象的扩展
<script>
//1.Object is判断两个值是否完全相等
console.log(Object.is(200,200));//从一定程度上可以认为是===
console.log(Object.is(NaN,NaN));//从一定程度上可以认为是===
console.log(NaN===NaN);
//2.Object.assign对象合并
const config1={
host:'localhost',
port2:'3306',
name:"tjk",
password:'tjk',
test1:'test1'
};
const config2={
host:'127.0.0.1',
port1:'33060',
name:"tjktzz",
password:'tjktzz',
test1:'test2'
}
console.log(Object.assign(config2,config1));
//3. Object.setPrototypeOf();//设置原型对象 Object.getPrototypeOf();
const school={
name:'西安',
age:'10086',
pass:'100788'
}
const classRoom={
name:10099,
location:'xian'
}
console.log(Object.setPrototypeOf(school,classRoom));
</script>
14.3 模块化
模块化是指将一个很大的程序文件,拆分成许多小的文件,然后将小文件组合起来
- 模块化的好处:
- 防止命名冲突
- 代码复用
- 高维护性
还可以这样进行暴露:
export{Object1,Object2}
默认暴露
exprot default{
Object1,Object2
}
- 引入:
简便形式的引入只能针对于默认暴露