1:ES6声明变量
1.变量var声明变量的问题 ES5
- 可以重复声明变量
- 可以先使用再声明
- 造成全局变量污染
2.let声明变量特点 ES6
- 不能先使用再说明
- 不能重复定义一个变量
- 具有块级作用域
3.const声明变量特点 ES6
- 不能先使用再说明
- 一旦声明必须赋值
- 赋值之后不能修改
- 具有块级作用域
- 声明变量,可以修改变量
- 声明常量不可修改恒改不变
注意:const声明一个常量,这个常量是引用数据类型(对象,数组,函数....),一旦赋值(引用地址不能修改),改的是值。
2:Symbol()
用于表示一个独一无二的值,不能与其他数据类型进行运算
3:模板字符串
var name="lzj"
console.log(`我是${name}`)
用法:`${}`
4:解构
var obj={
name:"ljz";
age:12;
}
const {name,age}=obj
对象解构语法: let {变量,变量,变量}=对象,要和变量同名才可以解构。
let arr=[10,11,23]
let [a,b,c]=arr
数组解构语法:let[变量,变量...]=arr。将数组中的值赋值给变量
5:扩展运算符
let arr =[10,11,12]
console.log(...arr)
扩展运算符:将数组或对象中的值一个一个拿出来。
6:箭头函数
function fn(a,b){
return a+b
}
console.log(fn(1,3))
var fn =function(){
console.log("我也很普通")
}
(function() {
console.log('1111')
}
)()
let fn =()=>{ console.log('1111') }
箭头函数中,this指向外层作用域。
7、箭头函数中的this
箭头函数没有自己的作用域,即箭头函数 this 指向其外层作用域
function People(name,age){
this.name=name;
this.age=age;
this.say = function () {
// console.log(this.name);
setTimeout(function () {
console.log(this.name);
},1000);
}
}
var p1 = new People("zhangsan", 15);
p1.say(); // undefined
function People2(name,age){
this.name=name;
this.age=age;
this.say = function(){
// console.log(this.name);
setTimeout(()=>{
console.log(this.name);
},1000);
}
}
var p2 = new People2("lisi", 15);
p2.say(); //lisi
//但如果创建的是字面量对象,不适合书写箭头函数
let obj1 = {
name:"nodejs",
age:"11",
say:()=>{
console.log(this.name); //this不指向obj
};
obj1.say(); // undefined
在dom操作中使用箭头函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.box{
width: 200px;
height: 200px;
background-color: pink;
}
</style>
</head>
<body>
<div id="odiv" class="box"></div>
<script>
var obj = document.getElementById("odiv");
obj.onclick = function(){
// setTimeout(function(){
// this.style.width="300px" //修改不了
// },1000);
setTimeout(()=>{
this.style.width="300px" //修改成功
},1000);
}
</script>
</body>
</html>
八、面向对象(重点)
一般面向对象的语言里面,都有类,实例对象这些概念。我们通过实例化类,得到实例对象。
类:定义一个 类,需要使用 class 关键字,但是es5里面,使用构造函数(首字母大写)来实现的。
继承:一般使用 extends 关键字来进行继承,但是在es5里面,也是没有extends继承,而是使用的prototype原型继承完成的。
ES6之前的写法:
// 用函数定义类
function Animal(name){
this.name = name;
}
// 给类的实例定义方法
Animal.prototype.showName = function(){
console.log(this.name);
}
// 给类定义静态方法
Animal.eat = function(){
console.log('进食');
}
// 根据函数实例化对象
var a = new Animal("Tom");
// 调用对象的方法
a.showName();
// 调用类的静态方法
Animal.eat();
ES6的写法: (掌握)
class Animal{
// 定义构造函数
constructor(name){
// console.log("constructor");
this.name = name
}
// 定义一个方法
showName(){
console.log(this.name);
}
//定义静态方法
static eat(){
console.log("吃---");
}
}
let obj = new Animal("Tom");
obj.showName();
Animal.eat();
九、关于继承
ES6之前的写法(仅做了解)
function Animal(name){
this.name = name;
}
Animal.prototype.showName = function(){
console.log(this.name);
}
Animal.eat = function(){
console.log('进食');
}
// 定义子类
function Mouse(name, color){
// 子类继承父类的属性 需要将 this 指向父类中的 name
Animal.call(this, name);
this.color = color;
}
// 子类继承父类的方法
Mouse.prototype = new Animal();
// 给子类实例添加新方法
Mouse.prototype.showInfo = function(){
console.log(this.name, this.color);
}
var m = new Mouse('Jerry', 'gray');
m.showName();
m.showInfo();
Animal.eat();
ES6的写法:(掌握)
class Animal{
// 定义构造函数
constructor(name){
// console.log("constructor");
this.name = name;
}
// 定义一个方法
showName(){
console.log(this.name);
}
//定义静态方法
static eat(){
console.log("吃---");
}
}
class Cat extends Animal{
}
let cat1 = new Cat("Tom");
cat1.showName();
Cat.eat();
继承中的子类constructor的写法:
在ES6中使用继承时,constructor中必须调用super()方法,其本质是在调用父类的constructor方法。通过这样的方式来达到属性继承的效果
class Animal{
// 定义构造函数
constructor(name){
console.log("constructor");
this.name = name;
this.age = 0;
this.color = "white";
}
// 定义一个方法
showName(){
console.log(this.name);
}
//定义静态方法
static eat(){
console.log("吃---");
}
}
class Cat extends Animal{
//注意:在ES6中使用继承时,constructor中必须调用super()方法,其本质是在调用父类的constructor方法。通过这样的方式来达到属性继承的效果
constructor(name){
super(name);
// console.log("constructor");
this.color = "yellow";
}
//定义Cat类特有的方法
catchMouse(){
console.log("抓老鼠");
}
//重写父类方法
showName(){
console.log(this.name, "喵喵");
}
}
let cat1 = new Cat("Tom");
console.log(cat1.color);
console.log(cat1.age);
console.log(cat1.name);
cat1.catchMouse();
cat1.showName();
10、静态属性和静态方法
Math.max(10, 20 30, 16) 把构造函数当成普通对象来调用某个方法,这个方法叫静态方法,如果是属性,我们就称它为静态属性。
定义静态方法,再类中通过加static关键字来定义。
关于静态属性,目前暂时没有关键字来定义,想要实现的话就在定义完类之后直接在类上添加属性,获取的时候通过类名来获取这个属性。
class Animal{
// 定义构造函数
constructor(name){
// console.log("constructor");
this.name = name
}
// 定义一个方法
showName(){
console.log(this.name);
}
//定义静态方法,再类中通过加static关键字来定义
static eat(){
console.log("吃---");
}
}
let obj = new Animal("Tom");
obj.showName();
Animal.eat();
// 关于静态属性,目前暂时没有关键字来定义,想要实现的话就在定义完类之后直接在类上添加属性,获取的时候通过类名来获取这个属性
Animal.type = "动物";
console.log(Animal.type);
11、全局对象
JavaScript 中有一个特殊的对象,称为全局对象(Global Object),它及其所有属性都可以在程序的任何地方访问,即全局变量。
在浏览器 JavaScript 中,通常 window 是全局对象, 而 Node.js 中的全局对象是 global,所有全局变量(除了 global 本身以外)都是 global 对象的属性。
后面看到所有的全局变量,例如 console,setTimeout 和 process 是 global 变量的成员。我们甚至可以向全局变量添加成员,使其在任何地方都可用。
// 1. nodejs 里面没有 window全局对象,但是存在一个 gloabal 全局对象。之前使用 console. setTimeout 这些全局的函数都是 global 上面的属性
// console.log(window); // 报错 ReferenceError: window is not defined
// console.log(global);
// 2. nodejs 里面声明的变量,并不会被挂载带 global 全局对象
let b = 20;
console.log(global.b); //undefined
// 3. 可以向global添加成员,使其在任何地方都可用
global.a = 10;
console.log(a); //10
// 4. 在nodejs执行js文件的过程中,里面也存在 this ,但是这个 this 和 global 并不是相等。
console.log(global === this); //false
// 实际上,在 nodejs 里面的this代表的当前这个 js模块(暂且认为 this 代表当前这个js文件)
12:promise对象
一个promise对象有以下几种状态:
- pending:初始化状态
- fullfilled:成功状态
- rejected:失败状态。
promise对象有以下两个特点:
1.对象的状态不受外界影响。
2.一旦状态改变,就不会再变。
解决问题:回调地狱、ajax 请求和响应需要时间 顺序不可控 。目的 控制顺序。
// 假装flag是状态
let flag=false
let p= new promise((resolve,reject)=>{
if(flag){
resolve("返回数据")
}else{
reject("抛出异常")
}
}
// .then()处理成功的回调 也就是resolve打包的数据
// .catch()处理失败的回调 也就是reject暴露的异常
p.then(data=>{
console.log(data);
}).catch(error=>{
console.log(error);
})
promise本身是同步的,.then()和.catch()是异步的
promise的all和race方法
let p1= new promise((resolve,reject)=>{
setTimeout(()=>{
resolve("成功")
},3000)
})
let p2= new promise((resolve,reject)=>{
setTimeout(()=>{
// resolve("成功")
reject("失败二")
},2000)
})
let p3= new promise((resolve,reject)=>{
setTimeout(()=>{
resolve("成功")
},1000)
})
let p=Promise.all([p1,p2,p3]);
p.then(data=>{
console.log(data);
}).catch(error=>{
console.log(error);
})
Promise.all([多个Promise对象]) 统一处理多个异步程序(定时器,时间可控)
1:如果多个异步程序都是成功的状态,p的状态就是成功,多个异步程序的成功结果会打包成一个数组统一返回。
2:但凡发现一个失败,最快得到的失败结果的直接返回
let p1= new promise((resolve,reject)=>{
setTimeout(()=>{
resolve("成功")
},3000)
})
let p2= new promise((resolve,reject)=>{
setTimeout(()=>{
// resolve("成功")
reject("失败二")
},2000)
})
let p3= new promise((resolve,reject)=>{
setTimeout(()=>{
resolve("成功")
},1000)
})
let p=Promise.all([p1,p2,p3]);
p.then(data=>{
console.log(data);
}).catch(error=>{
console.log(error);
})
Promise.race()谁快返回谁。
13:async和await
- async用来修饰函数,表示这是一个异步函数
- await 在异步函数中使用,表示同步代码(异步程序变成同步程序)
async function getVal(){
await p1.then(res=>console.log(res));
await p1.then(res=>console.log(res));
await p1.then(res=>console.log(res));
}
async/awiat的使用规则:
async 表示这是一个async函数, await只能用在async函数里面,不能单独使用
async 返回的是一个Promise对象,await就是等待这个promise的返回结果后,再继续执行
await 等待的是一个Promise对象,后面必须跟一个Promise对象,但是不必写then(),直接就可以得到返回值
14:新增数组方法
ES6新增了许多有用的数组方法,下面是其中一些常用的方法:
- Array.from(): 将类数组对象或可迭代对象转换为真正的数组。
- Array.of(): 根据传入的参数创建一个新的数组。
- Array.prototype.find(): 返回满足条件的第一个元素。
- Array.prototype.findIndex(): 返回满足条件的第一个元素的索引。
- Array.prototype.includes(): 判断数组是否包含某个元素。
- Array.prototype.fill(): 用指定的值填充数组。
- Array.prototype.flat(): 将嵌套的数组扁平化。
- Array.prototype.flatMap(): 对数组中的每个元素执行映射函数后,再将结果扁平化为一个新数组。
- Array.prototype.keys(): 返回包含数组索引的新迭代器对象。
- Array.prototype.values(): 返回包含数组值的新迭代器对象。
1.Array.from() 可接受3个参数(后两个参数可以没有)
Array.from(arraylLike, MapFn, thisArg)
- arrayLike:第一个参数,指定一个类数组对象or可迭代对象(如果只有一个参数就是把形参转变成数组)
- MapFn(可选):第二个参数,新数组中的每一个元素执行该回调函数
- thisArg(可选):第三个参数,执行回调函数MapFn时的this对象
- 返回值:一个新数组实例
2:includes()方法 查看数组某个元素是否存在
3.Array.of构建数组
4:forEach不改变原数组,若要改变需要配合index
传入一个函数,函数参数依次为 value、index、arr
- value:数组当前项的值(必填)
- index:数组当前项的索引(可选)
- arr:数组对象本身(可选,一般不选)
5.map 一般用于取数组中某个值返回出来
map() 和 forEach() 的区别就是 map() 会返回一个新数组
6.filter 筛选数组,返回筛选后的数组
新方法中的元素是通过指定数组中符合条件的所有元素
- value:数组当前的值
- index :数组当前的索引
- arr:数组对象本身(一般省略不写)
7:every()依据判断条件,数组的元素是否全满足,若满足则返回ture
callback的参数:
value --当前索引的值
index --索引
8:some() 方法用于检测数组中的元素是否满足指定条件,通俗一点 查找数组中是否有满足条件的元素
15:新增对象方法
ES6新增了很多对象方法,这些方法使得对象的操作更加方便和灵活。以下是一些常用的ES6新增的对象方法:
- Object.assign():用于将源对象的属性复制到目标对象中。
- Object.keys():返回一个包含所有可枚举属性名称的数组。
- Object.values():返回一个包含所有可枚举属性值的数组。
- Object.entries():返回一个包含所有可枚举属性键值对的数组。
- Object.getOwnPropertyDescriptors():返回一个对象的所有自身属性的描述符。
- Object.freeze():冻结一个对象,使其属性不可修改。
- Object.seal():密封一个对象,使其属性不可删除,但可修改。
- Object.is():比较两个值是否相同,类似于严格相等运算符(===)。
- Object.setPrototypeOf():设置一个对象的原型。
- Object.getOwnPropertySymbols():返回一个包含所有Symbol类型属性的数组。
1.Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
Object.assign(target, ...sources)
参数:target--->目标对象
source--->源对象
返回值:target,即目标对象
有多个源对象情况也是和一个源对象一样的。没有同名的属性会直接复制到目标对象上,同名的属性后面的属性值会覆盖前面的同名属性值。
2:Object.keys():返回一个包含所有可枚举属性名称的数组。
作用:遍历对象
返回结果:返回对象中每一项key的数组
3:Object.values():返回一个包含所有可枚举属性值的数组。
4:Object.entries():返回一个包含所有可枚举属性键值对的数组。
16.Set和map
Set
add()
delete()
has()判断指定值是否存在
clear()清除所有值
for ...of由于Set只有键值没有键名,所以说keys和values返回值相同
entries实现键值对
利用Set实现数组去重
set实现交集 A∩B
实现并集A∪B
实现差集A-B
// 主要用于数组去重,字符串去重
// let set = new Set()
// 1:add添加
// set.add('ljz')
// set.add('xzq')
// set.add('hzd').add('plf')
// console.log(set);
// 2:delete删除
// set.delete('plf')
// console.log(set);
//3:判断指定值是否存在has
// console.log(set.has('plf'));
// console.log(set.has('hzd'))
// 4clear 清除所有值
// set.clear()
// console.log(set);
// 遍历for...of
// for (let i of set.keys()) {
// console.log(i);
// }
// for (let i of set.values()) {
// console.log(i);
// }
// 实现键值对
// for (let i of set.entries()) {
// console.log(i);
// }
// Set实现数组去重
// let arr = [1, 2, 3, 4, 2, 3, 1, 3, 6]
// let set = new Set(arr);
// let result = [...set]
// console.log(result);
// set实现交集
let arr1 = [1, 2, 3, 4, 5, 6, 7]
let arr2 = [2, 3, 4, 7]
let set1 = new Set(arr1)
let set2 = new Set(arr2)
console.log(...set1);
// let result = [...new Set(arr1)].filter(item => set.has(item))
// console.log(result);
// 实现并集
// let result1 = [...new Set([...arr1, ...arr2])]
// console.log(result1);
// 实现差集A-B
let result = [...set1].filter(item => !set2.has(item))
console.log(result);
Map集合
类似于对象,也是键值对的集合,但是键的范围不局限于字符串,各种类型的值都可以当做键
1.set()给Map添加数据
2:get()获取某个key的值,返回key的值
3:has监测是否存在某个key,返回布尔值存在:true;不存在:false
4:delete()删除某个key及其对应的value,返回布尔值
5:clear()清除所有值
6:for...of遍历
7:keys():获取Map的所有key、
8:values()获取Map的所有值
9:entries():获取Map所有成员
10:转为数组
11:forEach遍历
// 1:set()添加数据
// let map = new Map()
// map.set('name', '小王').set('age', 18);
// console.log(map);
// 2:get()获取某个key的值,返回key的值
// console.log(map.get('name'));
// 3:has监测是否存在某个key,返回布尔值存在:true;不存在:false
// console.log(map.has('age'));
// 4:delete()删除某个key及其对应的value,返回布尔值
// console.log(map.delete('age'));
// console.log(map);
// 5:clear()清除所有值
// console.log(map.clear());
// console.log(map);
// for...of遍历
// map.set('syudy', function () {
// console.log('有在好好学习');
// })
// console.log(map);
// keys():获取Map的所有key、
// for (let key of map.keys()) {
// console.log(key);
// }
// values()获取Map的所有值
// for (let value of map.values()) {
// console.log(value);
// }
// entries():获取Map所有成员
// for (let item of map.entries()) {
// console.log(item);
// }
// 转为数组
const map = new Map([[1, 'one'], [2, 'tow'], [3, 'three']])
// console.log([...map.keys()]);
// console.log([...map.values()]);
// console.log([...map.entries()]);
// console.log([...map]);
// forEach遍历
console.log(map);
map.forEach((value, key, map) => {
console.log(value, key, map);
})
set和map是es6新增的集合类型。
Set
创建:可以用new set()进行创建。
方法:add,添加一个集合到末尾;has判断集合中是否存在对应的数据。clear清空集合。set也可以用于去重,new set([]),原理主要根据Object.is进行判断。
循环:for…of 或者 集合也可以用forEach进行循环,和循环数组的组别在于,forEach的第二个参数,因为set中不存在下标,所以第二个参数也是集合的元素。
map:
创建:new Map()
用于存储多个键值对数据。在map出现之前使用对象存储键值对,但是有几个问题,键名只能是字符串,获取数据的数量不方便。键名容易和原型上的名称冲突。
当描述一个整体,且属性不能随意添加删除时,适合用对象,当存储一些数据可以随意添加删除时可以用map。
方法:可以用size或者键的数量。可以用set设置一个键值对,如果存在就修改它的值,不存在就添加。判断方法和set一样。delete用于删除指定的键值。
遍历:遍历也可以用forEach和for of