ES6----

本文详细介绍了ECMAScript 6(ES6)的关键特性,包括let和const变量声明、解构赋值、模板字符串、箭头函数、Promise、Set与Map数据结构以及类和模块化等。通过实例代码展示了如何在实际开发中应用这些特性,帮助开发者掌握ES6的最新编程技巧。
摘要由CSDN通过智能技术生成

一、ECMAScript相关介绍

1.1什么是ECMA
ECMA(European Computer Manufactruers Association)中文名称为欧洲计算机制造协会。这个组是的目标是评估、开发和认可电信和计算机标准。

1.2、什么是ECMAScript
ECMAScript是由Ecma国籍通过ECMA-262标准化的脚本程序设计语言。

1.3什么是ECMA-262
Ecma国际制定了很多标准,ECMA-262只是其中一个

1.4为什么要学习ES6
(1)ES6的版本变动内容最多,具有里程碑意义
(2)ES6加入许多新的语法特征,编程实现更简单,高效
(3)ES6是前端发展趋势,就业必技能

二、let变量声明以及声明特征

1、变量不能重复声明
2、块级作用域(if else while for)全局 函数 eval
3、不存在变量提升
4、不影响作用域链

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script>
    声明变量
    let a;
    let b,c,d;
    let e = 100;
    let  f=432,g='fdsf',h=[];

    1、变量不能重复声明
    let star = "赵丽颖";
    let star  = "花千骨";

    2、块级作用域(if else while for)  全局   函数   eval
    {
        let girl = "小青";
    }
    console.log(girl);

    3、不存在变量提升
    console.log(per);
    let per = "花千骨";

    4、不影响作用域链
    {
        let school = "北京大学";
        function f1() {
            console.log(school);
        }
        f1();
    }
</script>
let经典案例实现
<!DOCTYPE html>
    <style>
        .page-header {
            border-bottom: 1px solid darkgray;
        }
        .item {
            width: 100px;
            height: 50px;
            border: 1px solid lightseagreen;
            float: left;
            margin-right: 20px;
            margin-top: 30px;
        }
    </style>
<div class="container">
    <h2 class="page-header">点击切换颜色</h2>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
</div>
<script>
    let itemObj = document.getElementsByClassName("item");
    for (let i=0;i<itemObj.length;i++){
        itemObj[i].onclick = function () {
            itemObj[i].style.backgroundColor = "pink";
        }
    }
</script>

三、const声明常量以及特点

1、一定要赋初始值
2、一般常量使用大写
3、常量的值不能修改
4、块级作用域
5、对于数组和对象的元素修改,不算做对常量的修改,不会报错

<script>
    声明常量
    const SCHOOL = "北京大学";
    const TEAM = ['uzi','akm','m416','awm'];
    TEAM.push('vector');
</script>

四、变量解构赋值

ES6允许按照一定模式从数组和对象中提取值,对变量进行赋值,这被称为解构赋值。
1、数组的解构
2、对象的解构

<script>
    1、数组的解构
    const F4 = ['刘能','赵四','宋小宝'];
    let [liu,zhao,song] = F4;
    console.log(liu);
    console.log(zhao);
    console.log(song);

    2、对象的解构
    const zhao1 = {
        name:'赵本山',
        age:12,
        xiaopin:function () {
            console.log("我能演小品");
        }
    };
    let  {name,age,xiaopin} = zhao1;
    console.log(name);
    console.log(age);
    console.log(xiaopin);
</script>

五、模板字符串

ES6引入新的声明字符串的方式``(反引号)
1、内容中可以直接出现换行符
2、变量拼接${}

<script>
    1、声明
    let str = `我是一个字符串`;
    console.log(str);

    2、内容中可以直接出现换行符
    let str1 = `<ul>
               <li>沈腾</li>
               <li>沈腾</li>
               <li>沈腾</li>
                `
    3、变量拼接${}
    let love = "沈腾";
    let out = `${love}是最搞笑的明星`;
    console.log(out);
</script>

六、对象的简化写法

ES6允许在大括号里面。直接写入变量和函数值,作为对象的属性和方法。这样书写更加简洁。

<script>
    let name = "北京";
    let change = function () {
        console.log("你好");
    }
    const school ={
        name,
        change,
        import(){
            console.log("嘿嘿");
        }
    }
    console.log(school);
</script>

七、箭头函数以及声明特点

ES6 允许使用 =>(箭头函数) 定义函数
1、this 是静态的,this始终指向函数声明时所在作用域下的this的值
2、不能作为构造函数实例化对象
3、不能使用arguments变量
4、箭头函数的简写
(1)省略小括号,当形参有且只有一个的时候
(2)省略花括号,当代码只有一条语句的时候,此时return必须省略,而且语句的执行结果就是函数的返回值。

<script>
    let fn = (a,b) => {
        return a+b;
    }
    let fn1 = fn(1,2);
    console.log(fn1);

    1this 是静态的。this 始终指向函数声明时所在作用域下的this的值
    function getName() {
        console.log(this.name);
    }
    let getName2 = () => {
        console.log(this.name);
    }

    设置window对象的name属性
    window.name = '北京';
    const school = {
        name:"beijing"
    }

    直接调用
    getName();//北京
    getName2();//北京

    call方法调用
    getName.call(school);//beijing
    getName2.call(school);//北京

    2、不能作为构造函数实例化对象
    let Person = (name,age) => {
        this.name = name;
        this.age = age;
    }
    let me = new Person('xiao',12);
    console.log(me);

    3、不能使用arguments变量
    let fn = () => {
        console.log(arguments);
    }
    fn(1,2,3);

    4、箭头函数的简写
       1)省略小括号,当形参有且只有一个的时候
    let add = n =>{
        return n+n;
    }
    console.log(add(9));
       2)省略花括号,当代码只有一条语句的时候,此时return必须省略
    而且语句的执行结果就是函数的返回值
    let pow =n => n*n;
    console.log(pow(9));
</script>
箭头函数适合与this无关的回调 ,定时器  数组的方法回调
箭头函数不适合与this 有关的回调 事件回调 对象的方法
    <style>
        div {
            width: 200px;
            height: 200px;
            background-color: #5588aa;
        }
    </style>
<div id="ad"></div>
<script>
    需求-1  点击div 2s后变成粉色
    let ad = document.getElementById("ad");
    ad.addEventListener("click",function () {
        //保存 this 的值
        //let _this = this;
        //定时器
       setInterval(() => {
            //修改背景颜色
           //_this.style.backgroundColor = "pink";
           this.style.backgroundColor = "pink";
       },2000);
    });
    
    需求-2  从数组中返回偶数的元素
    const arr =[1,3,5,6,8,9];
    const result = arr.filter(item => item % 2 === 0);
    console.log(result);
</script>

八、箭头函数与普通函数的区别

1、this指向问题
(1) 箭头函数的this指向的是父级作用域的this,是通过查找作用域链来确定 this 的值,也就是说,看的是上下文的this,指向的是定义它的对象,而不是使用时所在的对象;普通函数指向的是它的直接调用者。
(2) 箭头函数没有this,它的this是继承来的,默认指向定义它的时候的对象,就是我们说的宿主对象,而不是执行它的对象。
(3)我们不可以用 call()、apply()、bind() 这些方法去改变this的指向。

2、不可以被当做构造函数
不能被当作构造函数来使用,通过new命令来作为构造函数会报错,这里没有构建原型的说法,不存在prototype这个属性,也不能通过super访问原型的属性,而且new target也是不能用的

3、不可以使用arguments对象,该对象在函数体内不存在,如果要用就用rest参数替代。

4、不可以使用yield命令,因此箭头函数不能用作 Generator 函数。

5、不适用场合
(1)定义对象的方法,且该方法内部包括this时。
(2)需要动态this的时候,也不应使用箭头函数。

const cat = {
  lives: 9,
  jumps: () => {
    this.lives--;
  }
}

九、函数参数的默认值设置

ES6允许给函数参数赋值初始值
1、形参初始值,具有默认值的参数,一班位置要靠后(潜规则)
2、与解构赋值结合

<script>
    1、形参初始值,具有默认值的参数,一般位置要靠后(潜规则)
    function add(a,b,c=10) {
        return a+b+c;
    }
    let result = add(1,2);
    console.log(result);

    2、与解构赋值结合
    function connect(name,username,password,port) {
        console.log(host);
        console.log(username);
        console.log(password);
        console.log(port);
    }
    connect({
        name:'localhost',
        username:'root',
        password:'root',
        port:'3306'
    })
</script>

十、rest参数

ES6引入rest参数,用于获取函数的实参,用来代替arguments
1、rest参数必须要放到参数最后

<script>
    ES6获取实参的方式
    function date() {
        console.log(arguments);
    }
    date("张三","李四","王五");

    rest参数
    function date(...args) {
        console.log(args);
    }
    date("张三","李四","王五");
    rest参数必须要放到参数最后
    function f(a,b,...args) { }
</script>

十一、扩展运算符的介绍

… 扩展运算符 能将【数组】转换为逗号分隔的【参数序列】

<script>
    声明一个数组
    const tfboys = ["易烊千玺","王源","王俊凯"];
    声明一个函数
    function chunwan() {
        console.log(arguments);
    }
    chunwan(tfboys); //length=1
    chunwan(...tfboys); //length=3
</script>
扩展运算符的应用
<div></div>
<div></div>
<div></div>
<script>
    数组的合并
    const temp1 = ['11','22'];
    const  temp2 = ['33','44'];
    const  temp = [...temp1,...temp2];
    console.log(temp);

    数组的克隆
    const arr = ['张三','李四','王五'];
    const arr1 = [...arr];
    console.log(arr1);  //['张三','李四','王五']

    将伪数组转为真正的数组
    let dv = document.querySelectorAll("div");
    const divArr = [...dv];
    console.log(divArr);
</script>

十二、Symbol的介绍与创建

**1、Symbol:**ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。它是javaScript语言的第七种数据类类型,是一种类似于字符串的数据类型。
2、Symbol特点:
(1)Symbol的值是唯一的,用来解决命名冲突的问题
(2)Symbol值不能与其它数据类型进行运算
(3)Symbol定义的对象属性不能使用for…in循环遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名。
3、Symbol不能进行计算

<script>
    创建Symbol
    let s = Symbol();
    let s2 = Symbol('张三');
    let s3 = Symbol('张三');
    //Symbol.for 创建
    let s4 = Symbol.for('张三');
    let s5 = Symbol.for('张三');
    
    console.log(s2==s3);  //false
    console.log(s2==s4);  //false
    console.log(s4==s5); //true
</script>

十三、对象添加Symbol类型的属性

<script>
    let game;
    声明一个对象
    let method = {
        up:Symbol(),
        down:Symbol()
    };
    game[method.up] = function () {
        console.log("我可以改变形状");
    }
    game[method.down] = function () {
        console.log("我可以快速下降");
    }
    console.log(game);


    第二种方式
    let youxi = {
        name:'狼人杀',
        [Symbol('zibao')]:function () {
            console.log("我可以发言");
        },
        [Symbol('say')]:function () {
            console.log("自爆");
        }
    }
</script>

十四、Symbol的内置属性

作为对象的属性,用于扩展对象的功能的
Symbol.hasInstance
Symbol.isConcatSpreadable
Symbol.unscopables
Symbol.match
Symbol.replace
Symbol.search
Symbol.split
Symbol.iterator
Symbol.toPrimitive
Symbol.toStringTag
Symbol.species

<script>
    class Person {
        static [Symbol.hasInstance](param){
            console.log(param);
            console.log("我被用来检测类型了");
            return false;
        }
    }
    let o = {};
    console.log(o instanceof Person);

    const arr = [1,2,3];
    const  arr2 = [4,5,6];
    arr2[Symbol.isConcatSpreadable] = false;  //控制数组的值是否展开
    console.log(arr.concat(arr2));
</script>

十五、迭代器

1、 迭代器(iterator)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Iterator接口,就可以完成遍历操作
2、Iterator接口:对象里面的一个属性
(1)ES6创造了一种新的遍历命令 for…of 循环,Iterator接口主要供for…of消费
(2)原生具备iterator接口的数据(可用for of遍历)
Array
Arguments
Set
Map
String
TypedArray
NodeList
3、工作原理:
(1)创建一个指针对象,指向当前数据结构的起始位置
(2)第一次调用对象的next方法,指针自动指向数据结构的第一个成员
(3)接下来不断调用next方法,指针一直往后移动,直到指向最后一个成员
(4) 每调用next方法返回一个包含value和done属性的对象
注意:需要自定义遍历数据的时候,要想到迭代器

<!DOCTYPE html>
<script>
    声明一个数组
    const arr = ['11','22','33','44'];
    arr[Symbol.iterator]()
    调用对象的next方法
    console.log(iterator.next());
    console.log(iterator.next());
    console.log(iterator.next());
    console.log(iterator.next());
    console.log(iterator.next());
</script>
迭代器应用-自定义遍历数组
<script>
    声明一个对象
    const banji ={
        name:'终极一班',
        stus:[
            'xiaoming',
            'xiaoqiang',
            'xiaodong'
        ],
        [Symbol.iterator](){
            //索引变量
            let index = 0;
            let _this = this;
            return {
                next:function () {
                    if (index<_this.stus.length){
                        const result = {value:_this.stus[index],done:false};
                        //下标自增
                        index++;
                        //返回结果
                        return result;
                    }else{
                        return {value: undefined,done: true};
                    }
                }
            }
        }
    }
</script>

十六、生成器函数声明与调用

生成器函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同。
yield 函数代码的分隔符

<script>
    function * gen() {
        console.log(111);
        yield '1';
        console.log(222);
        yield '2';
        console.log(333);
        yield '3';
        console.log(444);
    }
    let iterator = gen();
    iterator.next();  //111
    iterator.next();  //222

    for (let v of gen()){
        console.log(v);
    }
</script>
</body>
</html>

十七、生成器函数的参数传递

<script>
    function * gen(args) {
        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());
    //next方法可以传入实参
    console.log(iterator.next('BBB'));
    console.log(iterator.next('CCC'));
    console.log(iterator.next('DDD'));
</script>
生成器函数实例
<script>
    /*
    * 异步编程
    * 1s 后控制台输出 111 2s 后输出 222  3s后输出 333
    * */
    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();
</script>

十八、Promise

promise是ES6引入的异步编程解决方案。语法上Promise是一个构造函数,用来封装异步操作并可以获取其成功后失败的结果
(1)Promise构造函数:Promise(excutor){}
(2)Promise.prototype.then方法
(3)Promise.prototype.catch方法

<script>
    //实例化Promise对象
    const p = new Promise(function (resolve,reject) {
        setTimeout(function () {
          //  let data = '数据库中的用户数据';
          //  resolve(data); //对象状态  成功
            let err = '数据读取失败';
            reject(err);
        },1000)
    });
    //调用promise对象的then方法
    p.then(function (value) {  //成功
        console.log(value);  //数据库中的用户数据
    },function (reason) {  //失败
        console.error(reason);
    })
</script>

十九、Promise封装Ajax请求

<script>
    const p = new Promise((resolve,reject)=>{
    //1、创建对象
    const xhr = new XMLHttpRequest();
    //2、初始化
    xhr.open("GET","https://api.apiopen.top/getJoke");
    //3、发送
    xhr.send();
    //4、绑定事件,处理响应结果
    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.log(reason);
    })
</script>

二十、Promise.prototype.then方法

<script>
    //创建Promise对象
    const p = new Promise((resolve,reject)=>{
        setTimeout(()=>{
            resolve('用户数据');
        },1000)
    })
    调用then方法 then方法的返回结果是Promise 对象,对象状态由回调函数的执行结果决定
    如果回调函数中返回的结果是 非Promise类型的属性,状态为成功,返回值为对象的成功的值
    p.then(value => {
        console.log(value);
    },reason => {
        console.warn(reason);
    })
</script>

二十一、Promise对象catch方法

<script>
    const p = new Promise((resolve,reject)=>{
        setTimeout(()=>{
            reject("出错啦")
        },1000)
    })
    /*p.then(function (value) {
        console.log(value);
    },function (reason) {
        console.log(reason);
    })*/
    p.catch(function (reason) {
        console.warn(reason);
    })
</script>

二十二、Set

1、 ES6 提供了新的数据结构 Set(集合)。它类似于数组。但成员的值都是唯一的,集合实现了iterator接口,所以可以使用 扩展运算符 和 for…of… 进行遍历.
2、集合的属性和方法:
(1)size 返回集合得元素个数
(2)add 增加一个新元素,返回当前集合
(3)delete 删除元素,返回boolean值
(4)has 检测集合中是否包含某个元素,返回boolean值

<script>
    let s = new Set();
    let s2 = new Set(['111','222','333','444','111']); //自动去重
    //元素个数
    console.log(s2.size); //4
    //添加新元素
    console.log(s2.add('555'));
    //删除元素
    console.log(s2.delete('222')); //true
    //是否包含某个元素
    console.log(s2.has('123')); //false
    //清空集合
    //console.log(s2.clear());
    console.log(s2);
    for (let v of s2){
        console.log(v);
    }
</script>
<script>
    let arr = [1,2,3,4,5,4,3,2,1];
    1、数组去重
    let result = [...new Set(arr)];
    console.log(result);

    2、交集
    let arr2 = [4,5,6,5,6];
    let result1 = [...new Set(arr)].filter(item=>{
        let s2 = new Set(arr2); //4,5,6
        if (s2.has(item)){
            return true;
        }else{}
        return false;
    })
    console.log(result1);

    3、并集
    let union = [...new Set([...arr, ...arr2])];
    console.log(union);

    4、差集
    let result2 = [...new Set(arr)].filter(item=>{
        let s2 = new Set(arr2); //4,5,6
        if (s2.has(item)){
            return false;
        }else{}
        return true;
    })
    console.log(result2);
</script>

二十三、Map

1、ES6提供了Map数据结构。它类似于对象,也是键值对的集合。
2、各种类型的值(包括对象)都可以当做键.
3、Map也实现了iterator接口,所以可以使用(扩展运算符)和(for…of)进行遍历
4、Map的属性和方法:
(1) size 返回Map的元素个数
(2) set 增加一个新的元素,返回当前Map
(3)get 返回键名对象的赋值
(4) has 检测Map中是否包含某个元素,返回boolean值
(5) clear 清空集合 ,返回undefined

<script>
    let m = new Map();
    m.set("name","张三");
    console.log(m);
</script>

二十四、Class类

1、ES6提供了更接近传统语言的写法,引入了class类这个概念,作为对象的模板。
2、通过class关键字,可以定义类。
3、新的class写法只是让对象原型的写法更加清晰,更像想想对象变成的语法而已。
4、 知识点:
(1)class声明类
(2)constructor定义构造函数初始化
(3)extends继承父类
(4)super调用父级构造方法
(5)static定义静态方法和属性
(6)父类方法可以重写

class静态成员
<script>
    class Phone{
        static 标识的方法属于类而不属于实例对象
        静态属性
        static name = "手机";
        static change(){
            console.log("我可以改变世界");
        }
    }
    let nokia = new Phone();
    console.log(nokia.name);  //undefined
    console.log(Phone.name);  //手机
</script>
构造函数继承
<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("锤子",2111,"pink","14");
    console.log(chuizi);
</script>
class的类继承
<script>
    class Phone{
        构造方法
        constructor(brank,price) {
            this.brand = brank;
            this.price = price;
        }
        父类的成员属性
        call(){
            console.log("我可以打电话");
        }
    }
    class SmartPhone extends Phone{
        构造方法
        constructor(brand,price,color,size) {
            super(brand,price); //Phone.call(this,brand,price)
            this.color = color;
            this.size = size;
        }
        子类可以重写父类的构造方法,但是不可以直接调用
        call() {
            console.log("我可以视频通话");
        }
        photo(){
            console.log("我可以拍照");
        }
        playGame(){
            console.log("我可以打游戏");
        }
    }
    const xiaomi = new SmartPhone("小米",1223,"pink","2.1");
    xiaomi.playGame();
</script>
class中getter和setter设置
<script>
    class Phone{
        get price(){
            console.log("价格属性被读取了");
        }
        set price(val){
            console.log("价格属性被修改了");
        }
    }
    实例化对象
    let s = new Phone();
    //console.log(s.price);
    s.price = "free";
</script>

二十五、ES6的数值扩展

1、Number.EPSILON 是 JavaScript 表示的最小精度。EPSILON 属性的值接近于 2.22044…
2、二进制和八进制
3、Number.isFinite 检测一个数值是否为有限数
4、Number.isNaN 检测一个数值是否为NaN
5、Number.parseInt Number.parseFloat 字符串转整数
6、Number.isInteger 判断一个数是否为整数
7、Math.trunc 将数字的小数部分抹掉
8、Math.sign 判断一个是到底为正数、负数、还是零

二十六、ES6的对象方法扩展

1、Object.is 判断两个值是否完全相等
2、Object.assign 对象的合并
3、Object.setPrototypeOf设置原型对象 Object.getPrototypeOf

<script>
    1、Object.is  判断两个值是否完全相等
    console.log(Object.is(12,12));   //true
    console.log(Object.is(NaN,NaN));   //true
    console.log(Object.is(NaN===NaN));  //false

    2、Object.assign  对象的合并
    const config1 = {
        name:'zhangsan',
        age:'11'
    }
    const  config2 ={
        name: 'lisi',
        age:'1122'
    }
    console.log(Object.assign(config1,config2));  //{name: 'lisi', age: '1122'}

    3、Object.setPrototypeOf设置原型对象  Object.getPrototypeOf
</script>

二十七、模块化

1、模块化: 模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。

2、模块化的好处:
(1)防止命名冲突
(2)代码复用
(3)高维护性

3、模块化规范产品:
(1)CommonJS => NodeJS、Browserify
(2)AMD => requireJS
(3)CMD => seaJS

4、ES6模块化语法:
(1)export 命令用于规定模块的对外接口
(2)import 命令用于输入其他模块提供的功能

5、浏览器使用ES6模块化引入模块方式一:这里是引用
6、浏览器使用ES6模块化引入模块方式二:
在这里插入图片描述
7、babel对ES6模块化代码转换
安装工具 babel-cli babel-preset-env browserify
企业一般使用:webpack

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卡卡_西

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值