目录
箭头函数中 不能使用arguments 如果想使用可以通过...rest来替代:
一、解构赋值
定义:es6允许开发者按照一定的模式将数组或对象中的数据提取出来 赋值给变量 这样的过程被称为解构函数。
数组的解构赋值
1.完全解构
let arr=["张三","李四","王五"];
//完全解构
let [a,b,c]=arr;
console.log(a,b,c);//张三 李四 王五
2.不完全解构
let arr=[1,2,3,4,5,6];
let [a,b,c]=arr;
console.log(a,b,c);//1,2,3
3.设置缺省值
let arr=[1,2,3,4];
let [a,b,,c]=arr;
console.log(a,b,c);//1 2 4
4.解构失败
let arr=[1,2,3];
let [a,b,c,d]=arr;
console.log(a,b,c,d);//1 2 3 undefind
5.解构默认值
let arr=[1,2,3,4];
let [a,b,c,d="哈哈"]=arr;
console.log(a,b,c,d);//1,2,3,哈哈
对象的解构函数
1.完全解构
let obj={
name :"张三",
age: 18,
gender: "男",
skill: ["吃", "喝", "玩", "乐"],
hobbies:"男"
}
let {name,age,gender,skill,hobbies}=obj;
console.log(name,age,gender,skill,hobbies);//张三 18 男 吃 喝 玩 乐 男
2.不完全解构
let {name,age,gender}=obj;
console.log(name,age,gender);//张三 18 男
3.解构失败
let {name:a, age: b, gender: c,skill:d,hobbies:e}=obj
console.log(a,b,c,d,e,f)
4.设置解构默认值
let {name:a,age:b,gender:c,skill:d,hobbies:e="女"} = obj;
console.log(a,b,c,d,e);
函数解构赋值
完全解构
function fn({name,age}){
console.log(name,age);
};
fn({name:"张三",age:18});
可以给函数的形参设置默认值 一般我们在实际操作中 会使用默认值给一些比较核心的形参 设置默认值 来确保代码的容错率
function fn({ name, age=10 }) {
//let {name:name,age:age}(形参) = {name:"张三",age:18}(实参)
//let {对象的属性名1:变量名1,对象的属性名2:变量名2,...} = 对象
//先声明两个变量
//name = 实参对象的name属性值(“张三”)
//age = 实参对象的age属性值(“18”)
console.log(name, age)//张三 18
}
fn({ name: "张三",age:18});
二、运算符
拓展运算符
rest:用在函数的参数中,存在一个rest参数 用来接收函数后续剩余参数。
function fn(a,b,...rest){
//形参中...rest就表示 接收后面的所有形参
console.log(a);//1
console.log(b);//2
console.log(rest);//3,4,5,6
}
fn(1,2,3,4,5,6)
注意:在形参中 ...rest必须写在最后面 否者报错
* 类似于arguments 也是类似的实参列表 但是接收后续参数的而不像是arguments那样获取所有的实参。
...运算符
拓展运算符...可以自动循环 具有iterator接口的所有合集(数组,字符串,伪数组(元素合集,set,map),对象);
循环写法:
let arr=[1,2,3,4,5,6];
//打印数组中 所有数组项
console.log(...arr);
拓展运算符(...)的实际应用
数组的合并
let arr1=[1,2,3];
let arr2=[4,5,6];
//将两个数组合并
//es5写法
let arr=arr1.concat(arr2);
//es6写法
let arr=[...arr1,...arr2];
伪数组转数组
let set =new Set([1,2,3]);
//将set数据产生的伪数组 转换为真数组
let arr=[...set];
数组的浅拷贝
let arr=[1,2,3,4,5,["张三","李四"]];
let arr1=[...arr];
对象的浅拷贝
let obj={
name:"张三",
age:18,
hobbies:["吃","喝"]
}
let obj1={...obj};
对象中解决实际问题
let obj = [
{
username: "张飞",
gender:"男",
salary:55000
},
{
username: "关羽",
gender:"男",
salary:60000
},
];
//给数组中 添加数据
//map方法的用法:数组.map(function(item,idx){return 操作});
//作用:map 会自动循环数组 并给每一个数组项执行return的操作 最后将操作完的数组返回出来
//给数组中 每一个对象 的 工资属性 添加2000块
let arr=obj.map(function(item,idx){return{...item,salary:item.salary+2000}})
//如果后续 添加的属性 属性名 和之前的一样 就 进行覆盖操作
console.log(arr);
三、函数的增强--箭头函数
箭头函数
写法:
let 变量名 =(形参)=>{函数体内容}
简化写法:
1.没有形参
()=>{函数体内容}
2.只有一个形参
形参=>{}//形参的小括号可以省略
3.有多个参数 则不能简写
4.如果有返回值且没有其他函数体代码
()=>返回值
注意:在某些特殊情况下 箭头函数的简写形式 会导致 代码歧义
例如:我们要返回一个对象
let fn3 = ()=>{name:"张三",age:18};
//这里 js就无法区分 大括号是函数体的还是对象的 从而产生歧义
解决方法:
直接将返回值 用小括号包裹起来即可
let fn3 = ()=>({name:"张三",age:18});
箭头函数和ES5中函数的区别
箭头函数中的this
定义:箭头函数中的this指向 和 父级作用域的this 完全相同,并且 箭头函数的this不能改变
let obj={
name:"张三丰",
skill:["太极拳","太极剑"]
}
function fn(){
console.log(this);
setTimeout(()=>{
console.log(this);//箭头函数的this值 和 父级作用域的this 相同
},1000);
}
/* fn();//fn的this--->window 箭头函数的this--->父级作用域(fn函数)的this--->window */
fn.call(obj);//fn的this被修改为 obj对象 因此 箭头函数的this 也指向obj对象
箭头函数没有构造器 因此不能作为构造函数使用
es5写法:
function Fn(name,age){
//1.js自动创建一个空对象
//2.js将构造函数的this 指向空对象
//3.执行构造函数代码 通过this 给空对象 添加属性和方法
this.name = name;
this.age = age;
//4.js将添加好属性和方法的对象 自动返回出来
}
var obj = new Fn("张三",18);
//我们要写的代码 只有第三步 1、2、4这三步代码 都是js自动帮我们执行的
//js之所以可以自动帮我们执行代码 主要原因是因为 es5声明的函数 存在 构造器
注意:箭头函数是没有构造器的因此不能当做构造函数使用 否则会报错
箭头函数中 不能使用arguments 如果想使用可以通过...rest来替代:
let fn4=(...rest)=>{
// console.log(arguments); 报错 arguments is not defined
console.log(rest)
}
fn4(1,2,3,4)
四、类
定义:是一个类似于构造函数的解构 也可以创建对象(类是es6给我们提供的一个构造函数的语法糖)
构造函数的语法糖 : 构造函数写起来比较复杂,因此我们可以使用类来优化构造函数的代码
类的使用:
//在es5中 我们想创建对象 需要通过构造函数来实现
var Fun = function(){
this.name = "张三";
this.age = 18;
}
var obj = new Fun();
//es6中 我们想创建对象 可以通过构造函数 也可以通过类来实现
class 类名{
//在类的内部 写入我们要绑定给对象的属性
name="张三";
age=18
}
//类创建对象的方式 和 调用构造函数完全相同
let 变量名 =new 类名();
//变量 就会接收到类创建出来的对象
传入实参写法:
//在es5中 我们想创建对象 需要通过构造函数来实现
var Fun = function(name,age){
this.name = name;
this.age = age;
}
var obj = new Fun("张三",18);
//在es6中 使用类 写法如下
//1.先创建类
class 类名{
//如果想传参 需要使用到constructor函数 写法如下
constructor(形参1,形参2,.....){
this.name=形参1;
this.age=形参2;
}
//}
混合创建类的写法:
//在es5中的混合式创建
//将容易改变的属性 放在构造函数中绑定
function Fn(name,age){
this.name = name;
this.age = age;
}
//将不容易改变的属性 放在原型中 保存
Fn.prototype.say = function(){
console.log("我爱你,塞北的雪");
}
var obj = new Fn("张三",18);
//es6中 类写法如下
class 类名{
constructor(name,age){
this.name = name;
this.age = age;
}
//原型中的属性 我们可以直接写到类里面 效果和之前写到原型中 完全一样
say =function(){
console.log("我爱你,我的家")
}
}
//原型中的属性 我们可以直接写到类里面 效果和之前写到原型中 完全一样
类的静态属性和方法
写法
class 类名{
constructor(形参1,形参2){
this.name = 形参1;
this.age = 形参2;
}
//当我们个类中的某一属性或方法 前面添加 static关键字的时候 这个属性/方法 就会变成静态属性/方法
static gender = "男";
say = ()=>{
console.log("我爱你,塞北的雪")
}
}
静态属性/方法和普通属性/方法的区别
普通属性/方法 由对象来使用
静态属性/方法 由类来使用
class Person{
constructor(name,age){
this.name1=name;//静态属性/方法带有name属性
this.age=age;
}
static gender="男";
static say =()=>{
console.log("我爱你,我的家");
}
}
//上述类中 gender 和 say 就是 静态属性 和 静态方法
let obj=new Person("张三",18);//张三 18;
console.log(obj.name1,obj.age);//非静态属性 只能由对象调用
console.log(Person.name1,Person.age);//类不能调用 报错
//静态属性 则可以由 类 调用
console.log(obj.gender);//静态属性和方法 不能由对象调用
console.log(Person.gender);//只能由类调用
继承
在es5中 我们讲过 四种继承方式——原型链继承、对象冒充继承、组合式继承、寄生组合式继承
通过类实现原型链继承
//在类的继承中 我们所谓的原型链继承 其实是 子类继承父类
//子类继承父类
//现在有一个现成的父类
class Parent{
money = "100w";
house = "大别墅";
}
//现在有一个子类 Child 想继承到父类中所有属性 money 和 house 写法如下
/*
class 子类名 extends 要继承的父类名{
//子类的内容
}
*/
class Child extends Parent{
play=()=>{
console.log("造作")
}
}
如果父类中 存在参数 子类继承父类的代码:
//class Parent{
constructor(money,house){
this.money = money;
this.house = house;
}
work(){
console.log("挣钱")
}
}
//现在有一个子类 想继承父类中 所有属性和方法 写法如下
class 子类名 extends 要继承的父类名{
constructor(money1,house1){
//调用super方法 继承父类中的带参数的属性
super(money1,house1);
}
play(){
console.log(造作)
}
}
注意:super方法 在继承的时候只能用一次
如果想继承多个带有参数的父类属性 可以写作:super(要继承的第一个属性的参数,要继承的第二个属性的参数,...)