js中的数据类型

update time 2023年2月15日22:00:52

一、数据类型的定义

  • JS是一种弱类型语(动态语言)。
  • 在程序运行过程中,类型会被自动确定(根据等号右边的值)
        // int num = 10; // java
        var num; // 这里的num我们不确定属于哪种数据类型
        var num = 10; // num数据数字型

二、数据类型分类

  1. 原始类型也叫简单数据类型或者基本数据类型。因为其占据空间固定,是简单的数据段,为了便于提升变量查询速度,将其存储在栈(stack)中(按值访问)。
  2. 引用类型(复杂数据类型或者Object)由于其值的大小会改变,所以不能将其存放在栈中,否则会降低变量查询速度,因此其存储在堆(heap)中,存储在变量处的值是一个指针,指向存储对象的内存处(按址访问)
    在这里插入图片描述

三、typeof操作符(数据类型检测)

  1. 主要是用来检测基本数据类型(对于复杂数据类型效果不大)
    • 语法:typeof 待检测的变量
    • 返回的值为数据类型
        // typeof操作符 (数据类型检测)
        // (1) 数字型返回number
        var num = 1;
        console.log('num: ', typeof num); // number 


        // (2) 字符串型返回string
        var str = '' + 1;
        console.log('str: ', typeof str); // string 


        // (3) 布尔型返回boolean
        console.log('flag: ', typeof true); // boolean 


        // (4) undefined返回undefined
        var age;
        console.log('age: ', typeof age); // undefined 


        // (5) null返回object 表示值为对象(空对象的引用)
        var space = null;
        console.log('space: ', typeof space); // object 
        var obj = new Object();
        console.dir(obj.__proto__.__proto__); // null Object的最顶层就是用null表示


        // (6) symbol返回symbol
        let sym = Symbol();
        console.log('sym: ', typeof sym);


        // (7) 函数返回function
        // 严格来说,在ECMAscript中,函数也被认为是对象,并不代表一种数据类型,但是函数也有自己特殊的属性。为此,就有必要通过typeof操作符来区分函数还是其他对象
        var fun = function() {}
        console.log('fun: ', typeof fun); // function 表示值为函数


        // (8) 对象返回object
        var ob = {};
        console.log('ob: ', typeof ob);


        // (9) 数组返回object 因为数组也是对象
        var arr = [];
        console.log('arr: ', typeof arr);

null表示空对象引用

常用数据类型返回值参考

  1. Number return number
  2. String return string
  3. Boolean return boolean
  4. Undefined return undefined
  5. Null return object
  6. Symbol return symbol
  7. object return object
  8. Function return function
  9. Array return object

四、instanceof 操作符

  1. 主要是用来检测复杂数据类型
    • 语法:待检测的变量 instanceof 某种数据类型
    • 返回的值为boolean
  2. 判断方式
  • 判断所有基本数据类型是否属于对应的数据类型都返回false
      let num = 1;
      console.log(num instanceof Number); // false
  • 判断所有复杂数据类型是否属于对应的数据类型都返回 true
      // (3)判断某些值是否属于引用类型
      let arr = [];
      let reg = /''/;
      let date = new Date();
      let obj = {};
      console.log(arr instanceof Array); // true
      console.log(reg instanceof RegExp); // true
      console.log(date instanceof Date); // true
      console.log(obj instanceof Object); // true
  • 判断所有复杂数据类型是否属于 object 都会返回 true(因为object是所有引用类型的基类)
      // (2) 因为object是所有引用类型的基类,所以判断所有引用类型是否是object,都会返回true
      console.log(Array instanceof Object); // true
      console.log(String instanceof Object); // true
      console.log(Number instanceof Object); // true
      console.log(RegExp instanceof Object); // true
      console.log(Date instanceof Object); // true

动态属性

复制值

作用域链查找

解构赋值

Undefined

  • undefined类型只有一个值,就是特殊值undefined
        // 1.undefined类型只有一个值,就是特殊值undefined
        let variable;
        console.log(variable); // undefined
        console.log(variable === undefined); // true
        let variable1 = undefined; // 此写法是没有任何意义的,只是为了演示
  • undefined的出现场景?
    • 未初始化的变量默认为undefined
    • 获取对象不存在的属性
    • 无返回值的函数的执行结果
    • 函数的参数没有传入
    • void(expression)
  • undefined和未定义变量的区别?
    • undefined和未定义变量使用typeof操作符检测都返回undefined
    • 建议定义变量必须初始化。当typeof返回undefined就是我们没有定义该变量。而不是未初始化
        // 2.包含undefined的值和未定义变量的区别?
        let message;
        // 未定义 age
        console.log(message); // undefined
        // console.log(age); // 报错 因为没有声明此变量
        // 使用typeof检测
        console.log(typeof message); // undefined
        console.log(typeof age); // undefined
        // 结论:建议我们在使用变量时最好都进行初始化,这样当typeof返回“undefined”时,我们知道变量从未声明而不是声明未初始化
  • undefined和null的区别和联系?
    • undefined值是由null派生而来的,所以在表面上他们是相等的
        // undefined继承自null,所以undefined == null,但是undefined又不是null,所以肯定不全等
        console.log(undefined == null); // true
        console.log(undefined === null); // false

Boolean

  1. Boolean有两个字面值,true(真)和false(假)
        //1. Boolean有两个字面值,true(真)和false(假)
        let flag = true;
        let flag1 = false;
        console.log(flag); // true
        console.log(flag1); // false
  1. Boolean参与运算时,true表示1,false表示0
        //2. 布尔值参与运算时,true为1,false为0
        console.log(true + 1); // 2
        console.log(false + 1); // 1
  1. 转换为Boolean类型
  • 调用Boolean()转型函数
        // (1) 调用Boolean转型函数
        // 注意:0,'',null,undefined,NaN 转换为boolean值都为flase,其余的都为true
        console.log(Boolean(0)); //fasle
        console.log(Boolean("")); // false
        console.log(Boolean(null)); // false
        console.log(Boolean(undefined)); // false
        console.log(Boolean(NaN)); // false


        console.log(Boolean(1)); // true
        console.log(Boolean('message')); // true
        console.log(Boolean({})); // true
  • 使用双重取反"!!"转换
      // (2) 使用双重取反转换
      console.log(!!1); // true
      console.log(!!"message"); // true


      console.log(!!null); // false
  1. Boolean类型转换注意事项
数据类型转换为false的值转换为true的值
Booleanfalsetrue
string’ ’非空字符串
number0,NaN非零数值(包括无穷值)
objectnull任意对象
undefinedundefined

由于存在这种自动转换,理解流程控制语句中使用什么变量就非常重要。错误的使用对象而不是布尔值会明显改变应用程序的执行流。

Null

  1. Null类型同样只有一个值,即特殊值null。逻辑上讲,null表示一个空对象指针,这也是给typeof传一个null会返回“Object”的原因
        // 1.Null类型同样只有一个值,即特殊值null。逻辑上讲,null表示一个空对象指针,这也是给typeof传一个null会返回“Object”的原因
        var space = null;
        console.log(typeof space); // Object
  1. 在定义将来要保存对象值的变量时,建议使用null来初始化,不要使用其他值。这样,只要检查这个变量的值是不是null就可以知道这个变量是否在后来被重新赋予了一个对象的引用
        if (car != null) {
            // car是一个对象的引用
        }
  1. 任何时候,只要变量要保存对象,而当时又没有那个对象可以保存,就要使用null来填充该变量。这样就可以保持null是空对象指针的语义,并进步一讲其与undefined区分开来
        var car = null; //使用nul来填充空对象

Number

1. 整数和浮点数

在JS中number表示整数和浮点数。最基本的数值为十进制,直接书写即可。

  • 整数
    • 八进制(以0开头,范围0~7)
    • 十六进制(以ox开头,0~ 9,A~F)
    • 注意:八进制的数值范围超过了0~7,会忽略前面的0,并以十进制展示
    • 使用科学计数法表示较大的数和较小的数值
        // 在JS中number表示整数和浮点数。最基本的数值为十进制,直接书写即可,整数可以是八进制(以0开头,范围0~7),可以是十六进制(以ox开头,0~9,A~F)。
        // 注意:八进制的数值范围超过了0~7,会忽略前面的0,并以十进制展示
        let intNum = 10; // 10 十进制
        let octNum1 = 070; // 56 八进制
        let octNum2 = 097; // 97 无效的八进制
        let hexNum1 = 0xA; // 10 十六进制
        let hexNum2 = 0xF; // 15 十六进制
        // 使用科学计数法表示较大的数和较小的数值
        let maxNum = 3.125e7; // 31 250 000 相当于3.125乘以10的7次幂
        let minNum = 3e-7; // 0.000 000 3
  • 浮点数
    • 浮点数计算会丢失精度,所以尽量避免浮点数的计算
        // 浮点数
        let floatNum1 = 0.1; // 0.1 浮点数
        let floatNum2 = 1.1; // 1.1 浮点数
        let floatNum3 = .1; // 0.1 有效,但不推荐
        let floatNum4 = 1.0; // 1 小数后面是零是当成整数来处理
        let floatNum5 = 1.; // 1 小数点后面没有数字的会当成整数来处理
        // 浮点数计算会丢失精度,尽量避免浮点数的计算
        const result = 0.1 + 0.2; // 0.30000000000000004 不等于0.3
        const result1 = 0.05 + 0.25; // 0.3
        const result2 = 0.5 + 0.15; // 0.65

2.数值的范围

  • 最大取值范围:Number.MAX_VALUE
  • 最小取值范围:Number.MIN_VALUE
  • 正无穷大:Infinity
  • 负无穷大:-INfinity
        // Number中值的范围
        // (1) 最大值
        console.log(Number.MAX_VALUE); // 1.7976931348623157e+308 最大取值范围
        // (2) 最小值
        console.log(Number.MIN_VALUE); // 5e-324 最小取值范围
        // (3) 无穷大
        console.log('result: ', result); // Infinity 表示正无穷大
        console.log(-result); // 表示负无穷大

判断值是不是有限大可以使用isFinite(),return false表示超出了范围,true表示未超出

  • 虽然超出数值范围的值并不常见,但计算非常大的值或者非常小的值时,有必要监测一下计算的结果是否超出了取值范围
       const result = Number.MAX_VALUE + Number.MAX_VALUE;
        // (5)如果要判断一个值是不是有限大(即JS的最大值和最小值之间),可以使用isFinite()
        // 虽然超出数值范围的值并不常见,但计算非常大的值或者非常小的值时,有必要监测一下计算的结果是否超出了取值范围
        console.log(isFinite(result)); // false 表示超出了范围
        const result3 = 100 + 100;
        console.log(isFinite(result3)); // true 表示没有超出范围

注意:当计算结果返回 Infinity 或者 -Infinity时该值不会在参与任何运算。

3.NaN

NaN 意思是"不是数值"(Not a Number)。用于表示本来要返回整数值的操作失败 (而不是抛出错误)。

        // (1)NaN 意思是“不是数值”(Not a Number)。用于表示本来要返回整数值的操作失败 (而不是抛出错误)。
        console.log(0 / 0); // NaN
        console.log(-0 / +0); // NaN
        console.log('数字' - 1); //NaN
  1. NaN有几个独特的的属性。
    • 任何涉及NaN的操作始终返回NaN,如(NaN/10)
    • NaN不包括NaN在内的任何值
        // NaN不包括NaN在内的任何值
        console.log(NaN == NaN); // false
  1. ECMAscript提供了isNaN()函数。
    • 该函数接收一个参数,可以是任意类型,然后判断这个参数"是否不是数值"。
    • 该函数会尝试把传入的参数转换为数值格式, 如果是数值格式或者能转换为数值格式就返回false, 反之就返回true。
        // ECMAscript提供了isNaN()函数。该函数接收一个参数,可以是任意类型,然后判断这个参数"是否不是数值"。
        // 该函数会尝试把传入的参数转换为数值格式, 如果是数值格式或者能转换为数值格式就返回false, 反之就返回true。
        console.log(isNaN(NaN)); // true
        console.log(isNaN(10)); // fasle 10是数值
        console.log(isNaN('10')); // fasle 可以转换为数值 10
        console.log(isNaN('张三')); // true 不能转换为数值
        console.log(isNaN(true)); // false 可以转换为数值1

4. 其他类型转换为number类型

  1. Number() (强制转换)
  • Number()是转型函数,可以用于任何数据类型。由于Number()函数转换字符时复杂且反常规,所以优先使用parseInt()
        // (1) Number()函数 (强制转换)
        let num3 = Number('hello world'); // NaN
        let num4 = Number(''); // 0
        let num5 = Number(00001); // 1
        let num6 = Number(true); // 1
  1. parseInt()
  • parseInt()将字符串转换为整数
        // (2) parseInt() 函数, 字符串转换为整数
        let num7 = parseInt('1234blue'); // 1234
        let num8 = parseInt(''); // NaN
        let num9 = parseInt('0xA'); // 10 将十六进制转换为十进制
        let num10 = parseInt('22.5'); // 22 取整
        let num11 = parseInt('70'); // 70 转换为十进制
        let num12 = parseInt('0xF'); // 15 将十六进制转换为十进制
        let num13 = parseInt('blue123'); // NaN
  • 不同格式容易混淆,所以parseInt()也可传入第二个参数,用于指定进制数
        // 不同格式容易混淆,所以parseInt()也可传入第二个参数,用于指定进制数
        let num14 = parseInt('0xAF', 16); // 175 使用十六进制数的完整写法,并且指定进制
        let num15 = parseInt('AF', 16); // 175 如果指定了进制数,那么十六进制前面的0x可以省略
        let num16 = parseInt('AF'); // NaN 省略了0x,还没有传入第二个参数


        let num17 = parseInt('10', 2); // 2 按二进制解析
        let num18 = parseInt('10', 8); // 8 按八进制解析
        let num19 = parseInt('10', 10); // 10 按十进制解析
        let num20 = parseInt('10', 16); // 16 按十六进制解析
        //注意: 如果不传进制数,让parseInt()自己决定如何去解析,为了避免出错,建议传入第二个参数

注意: 如果不传进制数,让parseInt()自己决定如何去解析,为了避免出错,建议传入第二个参数

  1. parseFloat()
  • parseFloat()函数,此函数和parseInt()类似
        // (2) parseInt() 函数, 字符串转换为整数
        let num7 = parseInt('1234blue'); // 1234
        let num8 = parseInt(''); // NaN
        let num9 = parseInt('0xA'); // 10 转换为十六进制
        let num10 = parseInt('22.5'); // 22 取整
        let num11 = parseInt('70'); // 70 转换为十进制
        let num12 = parseInt('0xF'); // 15 转换为十六进制
        let num13 = parseInt('blue123'); // NaN
  • parseFloat()和parseInt()的区别在于,它只能解析十进制,因此不能传入第二个参数,并且会忽略十进制前面的0,十六进制数值始终返回0。
        // (3) parseFloat()函数,此函数和parseInt()类似
        // parseFloat()和parseInt()的区别在于,它只能解析十进制,因此不能传入第二个参数,并且会忽略十进制前面的0,十六进制数值始终返回0。
        let num21 = parseFloat('1234blue'); // 1234
        let num22 = parseFloat('0xA'); //0
        let num23 = parseFloat('22.5'); // 22.5
        let num24 = parseFloat('22.34.5'); // 22.34
        let num25 = parseFloat('0908.5'); // 908.5
        let num26 = parseFloat('3.123e7'); // 31230000
  1. 使用算数运算符(隐式转换)
  • 我们也可以使用算数运算符(-、/、*)等转换
        // (4) 使用算数运算符隐式转换
        console.log('10' - 0); // 10
        console.log('10' * 1); // 10
        console.log('10' / 1); // 10

String

1. String表示字符串数据类型,表示0或多个16位Unicode字符序列。

  1. 字符串可以使用双引号(" ")、单引号(’ ')或反引号( `` )表示

注意:以某种符号开头,必须以某种符号结尾

  1. 字符串嵌套:外单内双,内单外双
        // String表示字符串数据类型,表示0或多个16位Unicode字符序列。字符串可以使用双引号(" ")、单引号(' ')或反引号(` `)表示
        // 注意:以某种符号开头,必须以某种符号结尾
        let firstName = "张三";
        let lastName = '李四';
        let lastName1 = `王五`;


        // 字符串嵌套
        // 外单内双,内单外双
        let dou = '我是"中国"人';
        console.log(dou); // 字符串 '我是"中国"人'
  1. 字符串转义符
转义符解释说明
\n换行符
\ \斜杠
\ ’单引号
\ "双引号
\ttab缩进(空格)
\b空格
        // 字符串转义符
        let text = '床前明月光,疑是地上霜。\n举头望明月,低头思故乡。';
        let xiGeMa = '\u03a3'; // 西格玛符号

2. 字符串的特点

  1. ECMAscript中规定字符串中的值是不可变的。
    意思就是: 值一旦创建就不能改变, 如果需要修改变量中字符串的值, 必须先销毁原始字符串, 然后将包含新值的另一字符串保存在该变量
  2. 所以,如果大量使用拼接字符串时,效率会降低
  3. 在早期的浏览器中,拼接字符串时会非常慢,后来浏览器也针对性的解决了此问题
        // ECMAscript中规定字符串中的值是不可变得, 意思就是: 值一旦创建就不能改变, 如果需要修改变量中字符串的值, 必须先销毁原始字符串, 然后将包含新值的另一字符串保存在该变量
        let lang = 'java';
        lang = lang + 'script';
        console.log(lang); // 'javascript'
        // 解释说明:
        // (1) 首先, 变量lang只包含字符串 'java', 紧接着lang被重新定义为包含 'java'和 'script'的组合。
        // (2) 整个过程先会分配一个包含10个字符的空间,然后填充上'java'和'script'。
        // (3) 最后销毁原有的字符串'java'和'script',因为这两个字符串都没有用了。所有处理都是在后台发生


        // 所以,如果大量使用拼接字符串时,效率会降低
        // 在早期的浏览器中,拼接字符串时会非常慢,后来浏览器也针对性的解决了此问题

3. 其他类型转换为String

  1. toString()方法
  • toString() 方法可用于 数值、 布尔值、 对象 和字符串值( 字符串值只是返回自身的一个副本)。
  • toString()方法在接收数值的时候可以传入一个参数,传入的参数为进制数,如果传入的进制数是2,则将值转换为2进制后转换为字符串结果,以此类推。默认情况下以十进制展示
  • null和undefined没有toString()方法
        // (1) toString() 方法可用于 数值、 布尔值、 对象 和字符串值( 字符串值只是返回自身的一个副本)。
        // 注意:null和undefined没有toString() 方法
        let age2 = 11;
        let ageAsString = age2.toString(); // '11'


        let found = true;
        let foundAsString = found.toString(); // 'true'
        // toString()方法在接收数值的时候可以传入一个参数,传入的参数为进制数,如果传入的进制数是2,则将值转换为2进制后转换为字符串结果,以此类推。默认情况下以十进制展示
        let num = 10;
        console.log(num.toString()); // '10' 默认十进制
        console.log(num.toString(2)); // '1010' 二进制
        console.log(num.toString(8)); // '12' 八进制
        console.log(num.toString(10)); // '10' 十进制
        console.log(num.toString(16)); // 'a' 十六进制
  1. String()函数 (强制转换)
  • 如果不确定一个值是null还是undefined的话可以使用String()转型函数,它始终会返回相应类型值的字符串。
  • 数值和布尔值与调用toString()结果相同。
        // (2)(强制转换) 如果不确定一个值是null还是undefined的话可以使用String()转型函数,它始终会返回相应类型值的字符串,数值和布尔值于调用toString()结果相同
        var obj = null;
        var str;
        console.log(String(obj)); // 'null'
        console.log(String(str)); // 'undefined'
  1. 字符串拼接 (隐式转换)
  • 字符串+任何类型 = 字符串 (数值相加,字符相连)
        // (3)字符串拼接 (隐式转换)
        // 字符串+任何类型 = 字符串  数值相加,字符相连
        console.log('你好' + '张三'); // '你好张三'
        console.log('现在是' + 21 + '点'); // '现在是21点'
        console.log('你好' + true); // '你好true'
        console.log(20 + 20); // 数值 40
        console.log(20 + '21'); // '2021'
        let age1 = 18;
        console.log('我今年' + age1 + '岁了'); // '我几年18岁了'
        console.log(undefined + '张三'); // 'undefined张三'

4. 模板字面量

  • 模板字面量保留换行字符,可以跨行定义字符串
  • 模板字面量会保持反括号里面的所有空格
        //模板字面量,模板字面量保留换行字符,可以跨行定义字符串
        let tem = 'my first\npage';
        let tem1 = `my first
page`;
        let tem2 = `my first
                page`;
        console.log(tem === tem1); // true tem和tem的确一样,包括空格,换行,等等。
        console.log(tem1 === tem2); // false 因为模板字面量会保持反括号里面的所有空格,当然也包括我们的代码缩进

5. 字符串插值

  • 技术上讲,模板字符串不是字符串,而是一种特殊的表达式,只不过求值后得到的是字符串
        // 字符串插值
        // 技术上讲,模板字符串不是字符串,而是一种特殊的表达式,只不过求值后得到的是字符串
        let myName = '张三';
        let age = 22;
        // (1) 传统的字符串插值
        let person = '我是' + myName + '\n我今年' + age + '岁了';
        // (2)使用字符串插值
        let jack = `我是${myName},我今年${age}岁了`

6. 模板字面量标签函数

        // 模板字面量标签函数:标签函数可以自定义插值行为
        // 模板字面量函数和定义普通函数方式一致
        let a = 6;
        let b = 9;


        function simpleTag(strings, aVal, bVal, sum) {
            console.log(strings);
            console.log(aVal); // 6
            console.log(bVal); // 9
            console.log(sum); // 15
            let foobar = `strings[0]`;
            return 'foobar'
        }


        let untaggedResult = `${a}+${b}=${a + b}`;
        console.log('untaggedResult: ', untaggedResult);
        let taggedResult = simpleTag `${a}+${b}=${a + b}`;
        console.log('taggedResult: ', taggedResult);

7. 原始字符串

  • 使用String.raw标签函数可以直接获取原始模板字面量内容(换行符或Unicode字符),而不是转换后的字符
        // 原始字符串
        // 使用String.raw标签函数可以直接获取原始模板字面量内容(换行符或Unicode字符),而不是转换后的字符


        //(1) Unicode示例 \u00A9b表示版权号
        console.log(`\u00A9`); // ©
        console.log(String.raw `\u00A9`); // \u00A9


        //(2)换行符示例
        console.log(`first line\nsecond line`);
        /*  运行结果:
         first line
         econd line */
        console.log(String.raw `first line\nsecond line`);
        /*  运行结果:
         first line\necond line */


        // (3)注意:对于真是存在的换行,String.raw()并不会将其转换“\n”
        console.log(`first line
        second line`);
        /*  运行结果:
         first line
         econd line */
        console.log(String.raw `first line
        second line`);
        /*  运行结果:
           first line
           econd line */

注意:对于真是存在的换行,String.raw()并不会将其转换“\n”

Symbol

1. 解释说明:

  • Symbol(符号)是ES6新增的数据类型。符号是原始数据类型,且符号实例是唯一,不可变的。
  • 符号的用途是确保对象属性使用唯一标识符,不会发生属性冲突的危险
  • 符号就是用来创建唯一记号,进而用作非字符串形式的对象属性

2. 符号的基本用法

  • 符号需要使用Symbol()函数来初始化
  • 调用Symbol()函数时,可以传入一个字符串参数用作对符号的描述,将来可以通过这个字符串来调试代码,这个字符串参数与符号定义或标识完全无关。
  • 符号没有字面量语法。你只需要创建Symbol()实例并将其用作对象的新属性,就可以保证它不会覆盖已有的对象属性,无论是符号属性还是字符串属性。
  • Symbol()函数不能与new关键字一起作为构造函数使用。
    • 为了避免创建符号包装对象
    • 真的想用符号包装对象,可以借用Object()函数

3.使用全局符号注册表

- 需要使用Symbol.for()方法

4. 使用符号作为属性

5. 常用内置符号

6. Symbol.asyncIterator

7. Symbol.hasInstance

8. Symbol.isConcatSpreadable

9. Symbol.iterator

10.Symbol.match

11. Symbol.replace

12. Symbol.search

13. Symbol.species

14. Symbol.split

15. Symbol.toPrimitive

16. Symbol.toStringTag

17. Symbol.unscopables

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值