ES6刷一波

1、let和const

共同点都是块级作用域,前者可以更改,后者是常量,不能更改,有个特殊情况,object由于是引用,但是改变obj是可以的,只是那个指针没有改变:
function testConst(){
    const obj={
        a:1
    }
    obj.b = 2;
}
testConst();
console.log(obj)
//obj:{a:1, b:2}

let and const

 for(var i = 1; i < 6; i++) {
     document.getElementById('my-element' + i)
       .addEventListener('click', function() { alert(i) })
   }



   'use strict';

  for(let i = 1; i < 6; i++) {
     document.getElementById('my-element' + i)
       .addEventListener('click', function() { alert(i) })
   }
 for循环顺序 for(a;b;c){d}  a =>b =>d =>c 

ES6自带ES5的’use strict’ 不能在全局声明两次同一个变量,且报错方式 多了一个Reference,ES5只会打印’undefined’

2、解构与赋值

Destructuring in MDN


{
    let a, b, rest;
    [a, b, ...rest] = [1,2,3,4,5,6];
    console.log(a, b, rest)
}

{
    function f(){
      return [1,2]
    }
    let a,b;
    [a,b]=f();
    console.log(a,b);
  }

{
    let a=1;
    let b=2;
    [a,b]=[b,a];
    console.log(a,b);
  }

// 对象解构赋值

{
    let a, b, c, rest;
    ({a, b, c=60, ...rest} = {a: 10, b: 20, c: 30, d: 40});
    console.log(a, b, c, rest)
}



// 字符串解构赋值

// 布尔值解构赋值

// 函数参数解构赋值
{

    function userId({id}) {
        return id;
      }

      function whois({displayName, fullName: {firstName: name}}) {
        console.log(displayName + ' is ' + firstName);
      }

      var user = { 
        id: 42, 
        displayName: 'jdoe',
        fullName: { 
            firstName: 'John',
            lastName: 'Doe'
        }
      };

      console.log('userId: ' + userId(user)); // "userId: 42"
      whois(user); // "jdoe is John"
}


// 数值解构赋值


{
    let metaData={
      title:'abc',
      test:[{
        title:'test',
        desc:'description'
      }]
    }
    let {title:titleVal, test:[{desc:descVal}]} = metaData;
    console.log(titleVal, descVal)
  }


  {
    function f() {
        return [1, 2, 3];
      }

      var a, b; 
      [a, , b] = f(); 
      console.log(a); 
      console.log(b); 
  }

  {
    let people = [
        {
          name: 'Mike Smith',
          family: {
            mother: 'Jane Smith',
            father: 'Harry Smith',
            sister: 'Samantha Smith'
          },
          age: 35
        },
        {
          name: 'Tom Jones',
          family: {
            mother: 'Norah Jones',
            father: 'Richard Jones',
            brother: 'Howard Jones'
          },
          age: 25
        }
      ];

        for(let {name:nameVal, family:{father:faVal}}of people){
            console.log(nameVal, faVal)
        }

  }



//   其它

{
    let z = 'fuck';

    let { [z]:foo} = {fuck:'fuck'}

    console.log(foo)
}

// 对象解构赋值 一般等号的右边大多为 真正的对象 等号左边,是笔者需要赋值的变量较多。

3.Number扩展

{console.log('B',0B111110111);
console.log(0o767);}

{
    console.log('15',Number.isFinite(15));
    console.log('NaN',Number.isFinite(NaN));
    console.log('true',Number.isFinite('true'));
    console.log('1/0',Number.isFinite('true'/0));
    console.log('0',Number.isFinite(0));
    console.log('0',Number.isFinite('0'));
    console.log('NaN',Number.isNaN(NaN));
    // only values of the type number, that are also NaN, return true.
    console.log('0',Number.isNaN(0));

  }
  {
    console.log('25',Number.isInteger(25));
    console.log('25.0',Number.isInteger(25.0));
    console.log('25.1',Number.isInteger(25.1));
    console.log('25.1',Number.isInteger('25'));
  }
  {
    console.log(Number.MAX_SAFE_INTEGER,Number.MIN_SAFE_INTEGER);
    console.log('10',Number.isSafeInteger(10));
    console.log('a',Number.isSafeInteger('a'));
  }

  {
    console.log(4.1,Math.trunc(4.1));
    console.log(4.9,Math.trunc(4.9));
  }

  {
    console.log('-5',Math.sign(-5));
    console.log('0',Math.sign(0));
    console.log('5',Math.sign(5));
    console.log('50',Math.sign('50'));
    console.log('foo',Math.sign('foo'));
  }


  {
    console.log('-1',Math.cbrt(-1));
    console.log('8',Math.cbrt(8));
  }

4.String
String in MDN

{
    console.log('a',`\u0061`);
    console.log('s',`\u20BB7`);  
    console.log('s',`\u{20BB7}`);
  }
  {

    {
        let s='��';
        console.log('length',s.length);
        console.log('0',s.charAt(0));
        console.log('1',s.charAt(1));
        console.log('at0',s.charCodeAt(0));
        console.log('at1',s.charCodeAt(1));

        let s1='��a';
        console.log('length',s1.length);
        console.log('code0',s1.codePointAt(0));
        console.log('code0',s1.codePointAt(0).toString(16));
        console.log('code1',s1.codePointAt(1));
        console.log('code2',s1.codePointAt(2));
      }

  }
  {
    console.log(String.fromCharCode("0x20bb7"));
    console.log(String.fromCodePoint("0x20bb7"));
  }
  {
    let str='\u{20bb7}abc';
    for(let i=0;i<str.length;i++){
      console.log('es5',str[i]);
    }
    for(let code of str){
      console.log('es6',code);
    }
  }
  {
    let user={
      name:'list',
      info:'hello world'
    };
    console.log(abc`i am ${user.name},${user.info}`);
    function abc(s,v1,v2){
      console.log(s,v1,v2);
      return s+v1+v2
    }
  }

5.数组扩展

copyWithin find findIndex includes apply call slice fill

{
Array.of(7);       // [7] 
Array.of(1, 2, 3); // [1, 2, 3]
Array(7);          // [ , , , , , , ]
Array(1, 2, 3);    // [1, 2, 3]
Array.of();    // []
Array.of(undefined); // [undefined]
}
// Polify
{
    if (!Array.of) {
    Array.of = function() {
      return Array.prototype.slice.call(arguments);
    };
  }
}

{
    if(!Array.of){
        Array.of = function(){
            return A
        }
    }
}


// Array.from 
// array-like objects (objects with a length property and indexed elements) or
// iterable objects (objects where you can get its elements, such as Map and Set).

{
    let arr = document.querySelectorAll('p');
    let arrEle = Array.from(arr);
    arrEle.forEach( item=> {
        console.log(item.textContent)
    })
}
{
    Array.from([1, 3, 5], (item, index) => {
        console.log(item, val)
    })
}

{
    // Array.fill()slice的用法差不多
    // Array.slice(val)
    // Array.slice(val, start)
    // Array.slice(val, start, end)

    [].fill.call({ length: 3 }, 4);  // {0: 4, 1: 4, 2: 4, length: 3}
    // https://segmentfault.com/q/1010000005847475
    // https://segmentfault.com/a/1190000004450221

}
{
// arr.includes(searchElement)
         // arr.includes(searchElement, fromIndex)
        console.log('number',[1,2,NaN].includes(1));
        console.log('number',[1,2,NaN].includes(NaN));
}
{

    for(let index of ['1','c','ks'].keys()){
        console.log('keys',index);
    }
    for(let value of ['1','c','ks'].values()){
        console.log('values',value);
    }
    for(let [index,value] of ['1','c','ks'].entries()){
        console.log('values',index,value);
    }

}

6.对象扩展

Object

{
  let a = 1,
    b = 2;
  let es6 = {
    a,
    b
  };
  console.log(es6);
}

{
  let es6_method = {
    hello() {
      console.log("hello");
    }
  };
}

{
  let a = "b";
  let es6_obj = {
    [a]: "fuck"
  };
  console.log(es6_obj);
}

{
  console.log("字符串", Object.is("abc", "abc"), "abc" === "abc");
  console.log("数组", Object.is([], []), [] === []);
}

{
  var arr = ["a", "b", "c"];
  console.log(Object.keys(arr)); // console: ['0', '1', '2']

  // array like object
  var obj = { 0: "a", 1: "b", 2: "c" };
  console.log(Object.keys(obj)); // console: ['0', '1', '2']

  // array like object with random key ordering
  var anObj = { 100: "a", 2: "b", 7: "c" };
  console.log(Object.keys(anObj)); // ['2', '7', '100']

  // array like object with random key ordering
  var an_obj = { 100: "a", 2: "b", 7: "c" };
  console.log(Object.values(an_obj)); // ['b', 'c', 'a']
}

{       
  // getFoo is property which isn't enumerable
  var myObj = Object.create(
    {},
    {
      getFoo: {
        value: function() {
          return this.foo;
        }
      }
    }
  );
         myObj.foo = 1;
         console.log(Object.keys(myObj)); // console: ['foo']
}


{
    // non-object argument will be coerced to an object
    console.log(Object.values('foo')); // ['f', 'o', 'o']
}

entries

{
    let arr = {a:1,b:2};
    for(let [key, value] of Object.entries(arr)){
            console.log(key, value)
    }

    Object.entries(arr).forEach( ([key, val]) =>{
        console.log(key + ' ' + val)
    }

    );    
}

7.Function扩展
Rest parameters

{
function multiply(multiplier, ...theArgs){
    return theArgs.map( item => {
        return multiplier * item
    })

}
console.log(multiply(3,1,2,3))
}
{
    function test(x, y = 'world'){
      console.log('默认值',x,y);
    }
    test('hello');
    test('hello','kill');
  }

  {
    let x='test';
    function test2(x,y=x){
      console.log('作用域',x,y);
    }
    test2('kill');
  }

  {
    function test3(...arg){
      for(let v of arg){
        console.log('rest',v);
      }
    }
    test3(1,2,3,4,'a');
  }

  {
    console.log(...[1,2,4]);
    console.log('a',...[1,2,4]);
  }

  {
    let arrow = v => v*2;
    let arrow2 = () => 5;
    console.log('arrow',arrow(3));
    console.log(arrow2());

  }

  {
    function tail(x){
      console.log('tail',x);
    }
    function fx(x){
      return tail(x)
    }
    fx(123)
  }

8.Symbol

Symbol

// var _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(e) {
//     return typeof e
// } : function(e) {
//     return e && "function" == typeof Symbol && e.constructor === Symbol ? "symbol" : typeof e
// };

{
let a1 = Symbol();
let a2 = Symbol();
console.log(a1===a2);


let a3 = Symbol.for('a3');
let a4 = Symbol.for('a3');
console.log(a3===a4)
// 两者的区别for会先检查是否在全局注册过,如果注册过就调用,没注册再for a3是key值

}

{
    let a1=Symbol.for('abc');
    let obj={
      [a1]:'123',
      'abc':345,
      'c':456
    };
    console.log('obj',obj);

    for(let [key,value] of Object.entries(obj)){
        console.log('let of',key,value);
      }
      Object.getOwnPropertySymbols(obj).forEach(function(item){
        console.log(obj[item]);
      })
      Reflect.ownKeys(obj).forEach(function(item){
        console.log('ownkeys',item,obj[item]);
      })

}

10.Promise
阮一峰的Promise
我对Promise的理解
Promise很酷
打开Promise的正确姿势
Promise in MDN

{
    var p = new Promise((resolve, reject) => {
           if(true){
               console.log('1');
               resolve('true')
               console.log('2');
           }else{
               reject('failed')
           }   
           console.log('3');           
    });
    p.then(
        val =>{
            console.log('success');
        },
        err =>{
            console.log('error');
        }
    )
}
{
    console.log('this block end')
    function test(second){
        return new Promise((resolve, reject) => {
            setTimeout(resolve('good'), second,'parama1');
        });
    }
    test(100).then(
        val =>{
            console.log('success');
        }
    )

}
{
// then方法指定的回掉函数,会在当前脚本同步全部执行完毕再执行

let promise = new Promise((resolve, reject) => {
        console.log('1');
        resolve('2')
});
promise.then(val=>{
    console.log('4');
    console.log('block end');
})
console.log('3');

}
{
    // 如果resolve的参数是另一个promise 那么当前promise取决于 参数了
    //  resolvedPromise 是在本轮事件循环的末尾执行,总是晚于本轮循环的同步任务。
    let p1 = new Promise((resolve, reject) => {
            setTimeout(function() {
                console.log('p1');
                reject('fuck') 
                console.log('p3'); 
            }, 3000);
    });
    let p2 = new Promise((resolve, reject) => {
            setTimeout(function() {
                console.log('p2');
                  resolve(p1)  
            }, 1000);
    });
    p2.then(val=>{
        console.log('success');
    }).catch(err=>{
        console.log(err);
    })

}
{
    // 调用resolvereject以后,Promise 的使命就完成了,加return 会阻止后续执行
     new Promise((resolve, reject) => {
       return resolve(1);
       console.log('i will not be excuted'); 
    });
}

{
    // then 有可能返回的还是一个Promise对象
    // 一般来说,不要在then方法里面定义Reject状态的回调函数(即then的第二个参数),总是使用catch方法。

    var someAsyncThing = function() {
        return new Promise(function(resolve, reject) {
          // 下面一行会报错,因为x没有声明
          resolve(x + 2);
        });
      };

      someAsyncThing().then(function() {
        console.log('everything is great');
      });
}
{
      // catch方法返回的还是一个 Promise 对象,因此后面还可以接着调用then方法。
      var someAsyncThing = function() {
        return new Promise(function(resolve, reject) {
          // 下面一行会报错,因为x没有声明
          resolve(x + 2);
        });
      };

      someAsyncThing().then(function() {
        console.log('everything is great');
      }).catch(err=>{
          console.log(err);
      }).then(()=>{
          console.log('catch then carry on');
      });
}

{
    // 如果p2报错,但是已经有catch方法了,就会返回新的promise实例,状态是resolve的,那么Pomise.all就都是resolvelet p1 =  new Promise((resolve, reject) => {
        resolve('hello')
    });
    let p2 =  new Promise((resolve, reject) => {
        reject('err')
    }).catch(err=>
    {
        console.log(err); 
    });

    Promise.all([p1, p2]).then( val=>{
        console.log(val);
    }).catch(err=>{
        console.log(err);
    })
}
{
    // Promise.resolve()
    let thenable = {
        then:(resolve, reject)=>{
            resolve('ok')
        }
    }
    Promise.resolve(thenable).then(val=>{
        console.log('ok');
    })

}
{
    setTimeout(function() {
        console.log(3);
    }, 0);
    Promise.resolve().then(val=>{
        console.log(2);
    })
    console.log(1);
}

11.Proxy and Reflect
Proxy
Reflect


{
let obj = {
    name:'John Snow',
    age:20,
    _skill:'sword',
    girlFriend:'The Mother Of Dragon'
}
let ctl = new Proxy(obj, {
    get(target, key){
           return key =='name'? target[key]:'you can only get Johns name'
    },
    set(obj, prop, value){
        if(prop=='age'){
            if(!Number.isInteger(value)){
                throw new TypeError('age is not a integer')
            }
            if(value > 30){
                throw new TypeError('snow cant 30+')
            }
        }
        obj[prop] = value;
        return true;

    },
    ownKeys(target) {
        return Object.keys(target).filter( item => item!='_skill')
      },
      deleteProperty(target, property) {
          if(property!=='girlFriend'){
              delete target[property]
              return true
          }else{
              throw TypeError('you cant split dragon and snow up')
          }
    }


})
obj.name='fuck'
console.log(ctl.age)
console.log(ctl.name)
ctl.age =28;
console.log(obj)
console.log(Object.keys(ctl))
delete ctl._skill;
console.log(ctl);
delete ctl.girlFriend;
}

{
    let obj = {
        name:'John Snow',
        age:20,
        _skill:'sword',
        girlFriend:'The Mother Of Dragon'
    }



}
{
    // example
     function monitorSnow(target, validator){
        return new Proxy(target,{
            _validator:validator,
            set(obj, prop, value){
                if(target.hasOwnProperty[prop]){
                    let va =this._validator[prop]; 
                    if(!!va(value)){
                        return Reflect.set(obj, prop, value)
                    }else{
                        throw TypeError(`不能设置${prop}到${value}`)
                    }
                }else{
                    throw TypeError('不存在')
                }
            }
        }

        )
     }
     const validator ={
         name(val){
            return typeof val === 'string'
         },
         age(val){
            return typeof val === 'number' && val>18
         }
     }

     class Snow{
         constructor(name, age){
            this.name=name;
            this.age=age;
            return monitorSnow(this, validator)
         }
     }


const snow = new Snow('john snow',28);
     snow.name=23;
     console.log(snow)

}

12.Set and Map

// set and map
// set不会添加重复的值。

{
    let list = new Set();
    list.add(5);
    list.add(7);

    // console.log('size',list.size);
  }
  {
    let arr = [1,2,3,4,5];
    let list = new Set(arr);

    console.log('size',list.size);
  }
  {
    let list = new Set();
    list.add(1);
    list.add(2);
    list.add(1);

    console.log('list',list);

    let arr=[1,2,3,1,'2'];
    let list2=new Set(arr);

    console.log('unique',list2);
  }
  {
    let arr=['add','delete','clear','has'];
    let list=new Set(arr);

    console.log('has',list.has('add'));
    console.log('delete',list.delete('add'),list);
    list.clear();
    console.log('list',list);
  }
  {
    let arr=['add','delete','clear','has'];
    let list=new Set(arr);

    for(let key of list.keys()){
      console.log('keys',key);
    }
    for(let value of list.values()){
      console.log('value',value);
    }
    for(let [key,value] of list.entries()){
      console.log('entries',key,value);
    }

    list.forEach(function(item){console.log(item);})
  }

  {
    let map = new Map();
    let arr=['123'];

    map.set(arr,456);

    console.log('map',map,map.get(arr));
  }
  {
    let map = new Map([['a',123],['b',456]]);
    console.log('map args',map);
    console.log('size',map.size);
    console.log('delete',map.delete('a'),map);
    console.log('clear',map.clear(),map);
  }
  {
    let weakmap=new WeakMap();

    let o={};
    weakmap.set(o,123);
    console.log(weakmap.get(o));
  }

13.Set and Map VS Array and Object

{
    // map vs array
    let map = new Map()
    let arr = [];
    // 增
    map.set('add',1);
    arr.push({add:1 })
    console.log(map, arr)
    // 查    
    console.log(map.has('add'))
    console.log(arr.find( item => item.add))    
    // 改
    map.set('add',2);
    arr.forEach( item =>item.add?item.add=2 :'');
    console.log(map, arr)
    // 刪
    map.delete('add');
    let index = arr.findIndex( item => item.add);
    arr.splice(index, 1);
    console.log(map, arr)

}
{
    // set vs arr

     console.log('// map vs array')
     let set = new Set()
     let arr = [];
    // 增
     set.add({add:1});
     arr.push({add:1})
     console.log(set, arr)
     // 查    
     console.log(set.has({add:1}))
     console.log(arr.find( item => item.add))  
     // 改
     set.forEach( item => item.add?item.add=2:'')
     arr.forEach( item => item.add?item.add=2 :'');
     console.log(set, arr)
     // 刪
     set.forEach(item => item.add? set.delete(item):'');
     console.log(set, arr)
}


{
    // map, set ,vs obj

    let item = {add:'1'}
    let map = new Map();
    let set = new Set();
    let obj = {};

    map.set('add','1');
    set.add(item);
    obj['add']=1;

    console.log(map, set, obj);

    console.info({
        a:map.has('add'),
        b:set.has(item),
        c:'add' in obj

    })
    // 改
    obj['add']=2;
    map.set('add','2');
    item.add=2;
    set.add(item);    
    console.log(map, set, obj);


    // 删除
    map.delete('add');
    set.delete(item);
    delete obj['add']
    console.log(map, set, obj);
}

14.类
老牌类继承
老牌类封装
原型链讲解
前端进阶系列
阮一峰Class

{
    // An important difference between function declarations and class declarations is that function declarations are hoisted and class declarations are not. You first need to declare your class and then access it, otherwise code like the following will throw a ReferenceError:
    // var p = new Rectangle(); // ReferenceError

    // class Rectangle {}
}

{
    class Rectangle{
        constructor(height, width) {
            this.height=height;
            this.width=width;
        }
        get area(){
        return this.calcArea() 
        }
        calcArea(){
            return this.height*this.width
        }

    }
    const square = new Rectangle(10, 10);
    console.log(square.area);

}

{
    class Point{
        constructor(x, y) {
            this.x= x;
            this.y= y;
        }

        static calcuDis(a, b){
            const dx = a.x -b.x;
            const dy = a.y -b.y;
            return Math.hypot(dx, dy)
        }

    }

    const p1 = new Point(5,5);
    const p2 = new Point(6,5);
    console.log(Point.calcuDis(p1, p2));
}
{
    class Animal{
        constructor(species) {
            this.species = species;    
        }
        speak(){
            console.log(this.species);
        }


    }
    class Dog extends Animal {
           speak(){
               console.log(this.species);
           } 
    };

    var d = new Dog('animal')
    d.speak();

}

15.修饰器

{
    let readonly=function(target,name,descriptor){
      descriptor.writable=false;
      return descriptor
    };

    class Test{
      @readonly
      time(){
        return '2017-03-11'
      }
    }

    let test=new Test();

    // test.time=function(){
    //   console.log('reset time');
    // };

    console.log(test.time());
  }


  {
    let typename=function(target,name,descriptor){
      target.myname='hello';
    }

    @typename
    class Test{

    }

    console.log('类修饰符',Test.myname);
    // 第三方库修饰器的js库:core-decorators; npm install core-decorators
  }

16.迭代

{
    let arr = ['hello','world'];
    let map = arr[Symbol.iterator]();

    console.log(map.next());
    console.log(map.next());
    console.log(map.next());

}
{


let obj ={
    start:[1,2,3,4,5],
    end:[7,8,9],
    [Symbol.iterator](){
        let self = this;
        let index = 0;
        let arr = self.start.concat(self.end);
        let len = arr.length;
    return{
        next(){
            if(index < len){
                return{
                    value:arr[index++],
                    done:false
                }
            }else{
                return{
                    value:arr[index++],
                    done:true
                }
            }
        }

    }
}
}
for(let key of obj){
    console.log(key);
}
}

{
    let arr=['hello','world'];
    for(let value of arr){
      console.log('value',value);
    }
  }

17.Generator

{
    let gen = function* (){
        yield 'a';
        yield 'b';
        return 'c'
    };
    let gene = gen();
    console.log(gene.next());
    console.log(gene.next());
    console.log(gene.next());
    console.log(gene.next());
}


{
    let obj ={};
    obj[Symbol.iterator] = function* (){
        yield 1;
        yield 2;
        yield 3;
    }
    for(let val of obj){
        console.log(val);
    }


}
{
    let state = function* (){
        while(1){
            yield 'A';
            yield 'B';
            yield 'C';
        }
    }
    let status = state();

    console.log(status.next());
    console.log(status.next());
    console.log(status.next());
    console.log(status.next());
    console.log(status.next());



}

{
     let state = async function(){
         while(1){
             await 'A';
             await 'B';
             await 'C';
             await 'D';
         }
     }
     let status = state();
     console.log(status.next());
     console.log(status.next());
     console.log(status.next());
     console.log(status.next());

}
{
    let ajaxXhr = function* (){
        yield new Promise((resolve, reject) => {
               setTimeout(function() {
                    resolve('ok')
               }, 200); 
        });
    }

    let pull = function(){
        let ajaxFunc = ajaxXhr()
        let gen = ajaxFunc.next();
        gen.value.then(val=>{
            if(val=='ok'){
                setTimeout(function() {
                    console.log('i am pulling');
                    pull();  
                }, 1000);
            }else{
                console.log('ok');
            }
        })
    }
    pull()
}

18.模块化

import defaultMember from "module-name";
import * as name from "module-name";
import { member } from "module-name";
import { member as alias } from "module-name";
import { member1 , member2 } from "module-name";
import { member1 , member2 as alias2 , [...] } from "module-name";
import defaultMember, { member [ , [...] ] } from "module-name";
import defaultMember, * as name from "module-name";
import "module-name";
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值