【前端】【JavaScript】基础知识

文章目录

JavaScript 基础

一. 初识 JavaScript

🔰JavaScript是一种运行在客户端的脚本语言;
🔰脚本语言:不需要编译,运行过程中由js解释器逐行来进行解释并执行;

(一) HTML/CSS/JS 的关系

🔰HTML决定网页结构和内容,相当于看到什么
🔰CSS决定网页呈现给用户的模样,相当于给人穿衣服
🔰JS 实现业务逻辑和页面控制,相当于人的各种动作


(二) 浏览器执行 JS 简介

🔰浏览器分成两部分:渲染引擎和 JS 引擎
🔰渲染引擎:用来解析HTML 与CSS,俗称内核;
🔰JS 引擎:也称之为JS解释器。用来读取网页中的JavaScript 代码,对其处理后运行;
🔰JS引擎执行代码时逐行解释每一句源码,然后由计算机去执行;


(四) JS 的组成

🔰JavaScript由ECMAScript(JavaScript 语法),DOM(页面文档对象类型),BOM(浏览器对象类型)等三部分组成;
🔰ECMAScript:规定了JS的编程语法和基础核心知识,是所有浏览器厂商共同遵守的一套JS语法工业标准。
🔰DOM:通过DOM提供的接口可以对页面上的各种元素进行操作(大小,位置,颜色等)
🔰BOM:是指浏览器对象模型,它提供了独立于内容的可以与浏览器窗口进行互动的对象结构。通过BOM可以操作浏览器窗口,比如弹出框,控制浏览器跳转,获取分辨率等。


(五) JS 书写位置

🔰有3中书写位置,分别为行内,内嵌和外内部;

	<!-- 2.内嵌式的JS -->
    <script>
        alert('沙漠骆驼')
    </script>
    <!-- 3. 外部js ,外部写js,然后引入 -->
    <script src="my.js"></script>
    <!--my.js内代码:alert('我是个学生')-->
</head>
<body>
    <!-- 1.行内式的js  直接写到元素的内部 -->
    <input type="button" value="唐伯虎" onclick="alert('秋香姐')">
</body>


二. JavaScript 常规函数

🔰为了方便信息的输入输出,JS中提供了一些输入输出语句,其常用的语句如下:

方法 说明
alert(msg) 浏览器弹出警示框
confirm(msg) 浏览器弹出确认框
console.log(msg) 浏览器控制台打印输出信息
prompt(into) 浏览器弹出输入框,用户可以输入
document.write() 向 HTML 文档中写入 HTML 或者 JavaScript 代码
prompt('请输入你的年龄')
alert('计算结果是')
console.log('我是程序员')

// 打印我们返回的元素对象,更好的查看里面的属性和方法
console.dir(time); 
函数 解析
eval(2 * 11 + 3 / 4) 对括号内的表达式进行计算,并返回结果
isNaN(a) 对变量进行测试其是否为数字,是数字返回false,不是返回true
parseFloat(“4 number”) 将字符串内的数字转换成浮点数字,若遇到非数字字符,将停止转换
parseInt(“A12”, 16) 将字符串内的数字转换成整数数字,可设置转换成几进制数字


三. JavaScript的注释

单行注释

<script>
    // 这是注释内容
    console.log("Hello,World!");
</script>

多行注释

<script>
    /**
     * 这是注释内容
     */
    console.log("Hello,World!");
</script>


三. 变量

🔰本质:变量是程序在内存中申请的一块用来存放数据的空间。

(一) 变量的使用

🔰变量在使用时分两步:1)声明变量;2)赋值

  1. 声明变量
    var age; // 声明一个名称为age的变量
    📌var 是一个JS关键字,用来声明变量。使用该关键字声明变量后,计算机会自动为变量分配内存空间,不需要程序员管。
    📌age是程序员定义的变量名,我们要通过变量名来访问内存中分配的空间。

  2. 赋值
    age = 18; // 给age 这个变量赋值为10

🔰变量初始化
var age = 18; // 声明变量的同时赋值为18


(二) 变量语法扩展

🔰同时声明多个变量时,只需要写一个var,多个变量名之间使用英文逗号隔开;
var age = 10, name = 'aili', sex = 2;


(三) 变量命名规范

🔰有字母,数字,下划线,美元符号组成;
🔰严格区分大小写;
🔰不能以数字开头;
🔰不能时关键字,保留字;
🔰变量名必须有意义;
🔰遵守驼峰命名法,首字母小写,后面的单词的首字母需要大写;



四. 数据类型

🔰JavaScript 是-种弱类型或者说动态语言。这意味着不用提前声明变量的类型,在程序运行过程中,类型会被自动确定。
var age = 10; // 这是一个数字型
var areYourk = '是的'; // 这是一个字符串
🔰在代码运行时,变量的数据类型是由JS引擎根据=右边变量值的数据类型来判断的,运行完毕之后.变量就确定了数据类型型。


🔰JS把数据类型分为两类:

  1. 简单数据类型(Number, String, Boolean, Undefined, Null);
  2. 复杂数据类型(object);

(一) 简单数据类型

简单数据类型 说明 默认值
Number 数字,包含整型,浮点型值,如21,0.21 0
Boolean 布尔值类,如true,false,等价于1和0 false
String 字符串,如“张三”,注意在JS里面,字符串都带引号 “”
Undefined 未定义的值,var a:声明了变量a,但是没有给值,此时 a = undefined undefined
Null 空值,var a = null; 声明了变量a, 为空值 null

1. Number

其他进制

🔰在JS中八进制前面加0, 十六进制前面加0x;
var num1 = 07; // 对应十进制的7
var num2 = 0xA; // 对应十进制的10

特殊的数字:

  • Infinity:正无穷
  • -Infinity:负无穷
  • NaN:非法数字(Not A Number)

isNaN()

🔰用来判断一个变量是否为非数字的类型;是数字返回false;
var ss = isNaN('age');

2. String

🔰字符串型可以是引号中的任意文本,其语法为双引号""单引号''


🔰通过字符串的length属性可以获取整个字符串的长度。
var number = '123456789';
alter(number.length); // 显示 11


🔰多个字符串之间用 + 进行拼接,字符串 + 任何类型 = 拼接后的新字符串数字相加,字符相连
alert('老师今年' + age + '岁');

3. 获取检测变量的数据类型

🔰typeof 可用来获取检测变量的数据类型;
alert(typeof 12); // number

转义符 含义 转义符 含义
\n 换行 \\ 斜杠
\t 制表 \’ 单引号
\b 空格 \" 双引号
\r 回车

4. 数据类型转换

转换为字符串

方式 说明 案例
toString() 转成字符串 var num = 1;
alert(num.toString());
String()强制转换 转成字符串 var num = 1;
alert(String(num));
加号拼接字符串 和字符串拼接的结果都是字符串 var num = 1;
alert(num + "我是字符串");

转换为数字型

方式 说明 案例
parseInt(string) 函数 将 string 类型转换成整数数值型 parseInt('78')
parseFloat(string) 函数 将 string 类型转换成浮点数数值型 parseFloat('78.3')
Number() 强制转换函数 将 stirng 类型转换为数值型 Number('12')
js 隐式转换(- * /) 利用算数运算,隐式转换为数值型 '12'-0

转换为布尔型

方式 说明 案例
Boolean() 函数 其他类型转换成布尔值 Boolean('true')

🔰代表空、否定的值会被转换为false , 如"、0、 NaN、null. undefined

console. log (Boolean('')); // false
console. log (Boolean(0)); // false
console. log (Boolean(NaN)); // false
console. log (Boolean (null)); // false
console. log (Boolean (unde fined)); // false
conso1e. log (Boolean('小白)); // true
console. log (Boolean(12)); // true

5. 算术运算符

运算符 描述 运算符 描述
+ 加法 - 减法
* 乘法 / 除法
% 取模(求余数)
++ 自增 - - 自减

6. 逻辑运算符

运算符 描述
&& and (与)
|| or (或)
not (非)

7. 比较运算符

  • 使用 == 来做相等运算
    • 当使用==来比较两个值时,如果值的类型不同,则会自动进行类型转换,将其转换为相同的类型,然后在比较
  • 使用 != 来做不相等运算
    • 不相等用来判断两个值是否不相等,如果不相等返回true,否则返回false,不相等也会对变量进行自动的类型转换,如果转换后相等它也会返回false
  • 使用 === 来做全等运算
    • 用来判断两个值是否全等,它和相等类似,不同的是它不会做自动的类型转换,如果两个值的类型不同,直接返回false
  • 使用 !== 来做不全等运算
    • 用来判断两个值是否不全等,它和不等类似,不同的是它不会做自动的类型转换,如果两个值的类型不同,直接返回true

(二) 引用数据类型

Object(对象)、Array(数组)、Function(函数)



五. 流程控制

🔰流程控制主要有三种结构,分别是顺序结构分支结构循环结构,这三种结构代表三种代码执行的顺序。
🔰顺序结构程序会按照代码的先后顺序,依次执行,程序中大多数的代码都是这样执行的。
🔰分支结构执行代码的过程中,根据不同的条件,执行不同的路径代码(执行代码多选一的过程) , 从而得到不同的结果。

(一) 分支结构

1. if 语句

if(条件表达式1) {
   
	语句1} else if(条件表达式2) {
   
	语句2}else {
   
	// 上述条件都不成立,执行此处代码
} 

2. 三元表达式

🔰条件表达式 ? 表达式1 : 表达式2
🔰如果条件表达式结果为真,则返回表达式1的值;如果条件表达式结果为假,则返回表达式2的值;

3. switch 语句

switch(表达式) {
   
	case value1:
		// 表达式 等于 value1 时要执行的代码
		break;\
	case value2:
		// 表达式 等于 value2 时要执行的代码
		break;
	default:
		// 表达式 不等于任何一个 value 时要执行
}

(二) 循环结构

1. for 循环

for(初始化变量; 条件表达式; 操作表达式) {
   
	// 循环体
}

🔰初始化变量就是用var声明的一个普通变量,通常用于 作为计数器使用
🔰条件表达式就是用来决定每一次循环是 否继续执行就是终止的条件
🔰操作表达式是每次循环最后执行的代码经常用于我们计数器变量进行更新(递增或者递减)

2. while 循环

while(条件表达式) {
   
	// 循环体代码
}

🔰执行思路:

  1. 先执行条件表达式,如果为true,则执行循环体代码;如果为false,则退出循环,执行后面的代码;
  2. 执行循环体代码;
  3. 循环体代码执行完毕后,程序会继续判断执行条件表达式,如果条件仍为true,则会继续执行循环体,直到循环条件为false时,整个循环过程才会结束。

3. do while 循环

do {
   
	// 循环体代码
} while(条件表达式);

🔰执行思路:

  1. 先执行一次循环体代码;
  2. 再执行条件表达式,如果结果为true ,则继续执行循环体代码;如果为false,则退出循环,继续执行后面代码。
    🔰注意:先再执行循环体,再判断,我们会发现d…while循环语句至少会执行一次循环体代码。

4. continue break

🔰continue关键字用于立即跳出本次循环,继续下一次循环(本次循环体中continue之后的代码就会少执行一次)
🔰break关键字用于立即跳出整个循环(循环结束)。



六. 函数

🔰函数在使用时分为两步:声明函数,调用函数;

(一) 声明函数

// 1. 利用函数关键字自定义函数(命名函数)
function 函数名(形参1, 形参2) {
   
	// 函数体代码
	return 需要返回的结果;
}

function cook(aru) {
   
	console.log(aru);
	return 666;
}

// 2. 函数表达式(匿名函数)
// var 变量名 = function() {}
var fun  = function(aru) {
   
	console.log(aru);
}
fun('pink老师');
// fun 是变量名,不是函数名

🔰function是声明函数的关键字,必须小写;


(二) 调用函数

// 调用函数
函数名(实参1, 实参2); // 通过调用函数名来执行函数体代码

cook('酸辣土豆丝');
var ss = cook('酸辣土豆丝'); // 获取返回值结果

🔰我们的函数如果有return,则返回的是return 后面的值;如果函数没有return ,则返回undef ined。


(三) arguments 的使用

🔰当我们不确定有多少个参数传递的时候,可以使用 arguments 来获取实参的值;
🔰只有函数才有 arguments 对象,而且每个函数都内置好了arguments 对象,arguments 对象中存储了传递的所有实参

function cook() {
   
	console.log(arguments); // 里面存储了所有传递过来的实参 arguments = [1, 2, 3]
	console.log(arguments.length); // 3
	console.log(arguments[1]); // 2

	// 我们可以按照数组的方式遍历 arguments
	for (let i = 0; i < arguments.length; i++) {
   
		console.log(arguments[i]);
	}
}
cook(1, 2, 3);

🔰伪数组,并不是真正意义上的数组;

  1. 具有数组的 length 属性
  2. 按照索引的方式进行存储的;
  3. 他没有真正数组的一些方法,pop() push() 等;


七. 作用域

🔰JS作用域:就是代码名字(变量) 在某个范围内起作用和效果;
🔰目的是为了提高程序的可靠性,更重要的是减少命名冲突;
🔰全局作用域:整个 script标签或者是一个单独的js文件。
🔰局部作用域:在函数内部就是局部作用域,这个代码的名字只是在函数内部起到效 果和作用。

(一) 全局变量

🔰在全局作用域下声明的变量叫做全局变量 (在函数外部定义的变量);

  1. 全局变量在代码的任何位置都可以使用;
  2. 在全局作用域下 var 声明的变量,是全局变量;
  3. 特殊情况下,在函数内不适用 var 声明的变量也是全局变量 (不建议使用) ;

(二) 局部变量

🔰在局部作用域下声明的变量叫做局部变量 (在函数内部定义的变量);

  1. 局部变量只能在该函数内部使用;
  2. 在函数内部 var 声明的变量,是局部变量;
  3. 函数的形参实际上就是局部变量;


八. JS 预解析

🔰JS引擎运行 js 分两步:预解析 代码运行

  1. 预解析:JS引擎会把 js 里面所有的 var ,还有 function 提升到当前作用域的最前面;
  2. 代码执行:按照代码书写顺序从上往下执行
    🔰预解析分为:变量解析(变量提升) 和 函数预解析(函数提升);
  3. 变量提升:就是把所有的变量声明提升到当前的作用域最前面,不提升赋值操作;
  4. 函数提升:就是把所有的函数声明提升到当前作用域最前面,不调用函数;


九. JS对象

(一) 创建对象

1. 利用对象字面量创建对象

// var obj = {} // 创建了一个空对象
var obj = {
    
	uname:'张三丰',
	age: 18,
	sex: '男',
	seyHi:function() {
    
		console.log('hi~');
	}
}

🔰里面的属性或者方法我们采取键值对的形式 键 属性名:值 属性值;
🔰多个属性或者方法中间用逗号隔开的;
🔰方法冒号后面跟的是一个匿名函数;
🔰使用对象:

// 调用对象属性
// 1.  对象.属性名
console.log(obj.uname);
// 2. 对象名['属性名']
console.log(obj['age']);

// 调用对象方法
// 对象名.方法名()
obj.sayHi();

2. 利用 new Object 创建对象

var obj = new Object(); // 创建了一个空对象
obj.uname = '张三丰';
obj.age = 18;
obj.sex = '男';
obj.sayHi = function() {
   
	console.log('hi~');
}
// 调用对象
console.log(obj.uname);
console.log(obj['age']);
obj.sayHi();

3. 利用构造函数创建对象

// 声明构造函数
function 构造函数名() {
   
	this.属性 =;
	this.方法 = function() {
   }
}
function Star(uname, age, sex) {
   
	this.name = uname;
	this.age = age;
	this.sex = sex;
}

// 使用构造函数
new 构造函数名();
var ldh = new Star('刘德华', 19, '男');
console.log(ldh.name);

(二) 遍历对象

// for in 遍历对象
// for(变量 in 对象) {}
for(var k in obj) {
   
	console.log(k); // 属性名
	console.log(obj[k]); // 属性值
}


十. 内置对象

(一) 查文档

🔰学习一个内置对象的使用,只要学会其常用成员的使用即可,我们可以通过查文档学习,可以通过MDN来查询。
🔰MDN:https://developer.mozilla.org/zh-CN/

如何学习对象中的方法

  1. 查询该方法的功能
  2. 查看里面参数的意义和类型
  3. 查看返回值的意义和类型
  4. 通过demo进行测试

(二) Math 对象

🔰Math 数学对象:不是构造函数,所以不需要new 来调用,直接使用里面的属性和方法即可;

方法/属性 说明
Math.PI 圆周率值
Math.max(i, j) 取最大值
Math.max(12, 23) // 23
Math.min(i, j) 取最小值
Math.min(12, 23) // 12
Math.abs(i) 绝对值
Math.abs(-12) // 12
Math.round(i) 四舍五入, 就近取值
Math.round(1.5) // 2
Math.floor(i) 向下取整
Math.floor(3.4) // 3
Math.ceil(i) 向上取整
Math.ceil(3.4) // 4
Math.random() 随机数
Math.floor(Math.random()*10 // 取0~9内的一个随机数
Math.trunc() 将数字的小数部分抹掉
Math.sign() 判断一个数到底为正数、负数、还是零
// 随机获取学生姓名
function getRandom(min, max) {
   
	return Math.floor(Math.random() * (max-min+1))+min;
}
var arr = ['张三', '艾莉', '艾琳', '古丽'];
alert(arr[getRandom(0, arr.length-1)]);
/*固定值*/
console.log("PI = " + Math.PI);
console.log("E  = " + Math.E);
console.log("===============");
/*正数*/
console.log(Math.abs(1));        //可以用来计算一个数的绝对值
console.log(Math.ceil(1.1));     //可以对一个数进行向上取整,小数位只有有值就自动进1
console.log(Math.floor(1.99));   //可以对一个数进行向下取整,小数部分会被舍掉
console.log(Math.round(1.4));    //可以对一个数进行四舍五入取整
console.log("===============");
/*负数*/
console.log(Math.abs(-1));       //可以用来计算一个数的绝对值
console.log(Math.ceil(-1.1));    //可以对一个数进行向上取整,小数部分会被舍掉
console.log(Math.floor(-1.99));  //可以对一个数进行向下取整,小数位只有有值就自动进1
console.log(Math.round(-1.4));   //可以对一个数进行四舍五入取整
console.log("===============");
/*随机数*/
//Math.random():可以用来生成一个0-1之间的随机数
//生成一个0-x之间的随机数:Math.round(Math.random()*x)
//生成一个x-y之间的随机数:Math.round(Math.random()*(y-x)+x)
console.log(Math.round(Math.random() * 10));            //生成一个0-10之间的随机数
console.log(Math.round(Math.random() * (10 - 1) + 1));  //生成一个1-10之间的随机数
console.log("===============");
/*数学运算*/
console.log(Math.pow(12, 3));   //Math.pow(x,y):返回x的y次幂
console.log(Math.sqrt(4));      //Math.sqrt(x) :返回x的平方根

(三) 日期对象

🔰Date 对象是一个构造函数,所以需要实例化后才能使用;
🔰Date 实例用来处理日期和时间;

1. Date() 方法

1)获取当前时间必须实例化

var now = new Date();
alert(now); // Tue Nov 22 2022 16:49:21 GMT+0800 (中国标准时间)

2)Date() 构造函数的参数

🔰如果构造函数括号里面有时间,就返回参数里面的时间。
var now = new Date('2022-11-12 / 2022/11/12');
// Sat Nov 12 2022 08:00:00 GMT+0800 (中国标准时间)

var date = new Date();
console.log(date);

console.log(date.getFullYear());//获取当前日期对象的年份(四位数字年份)
console.log(date.getMonth());//获取当前日期对象的月份(0 ~ 11)
console.log(date.getDate());//获取当前日期对象的日数(1 ~ 31)
console.log(date.getHours());//获取当前日期对象的小时(0 ~ 23)
console.log(date.getMinutes());//获取当前日期对象的分钟(0 ~ 59)
console.log(date.getSeconds());//获取当前日期对象的秒钟(0 ~ 59)
console.log(date.getMilliseconds());//获取当前日期对象的毫秒(0 ~ 999)

2. 日期格式化

🔰对象.方法

方法 说明
obj.getFullYear() 获取当年
obj.getMonth() 获取当月(0~11)
实际应用时,加一
obj.getDate() 获取当天日期
obj.getDay() 获取星期几(周日:0 ~ 周六:6)
obj.getHours() 获取当前小时
obj.getMinutes() 获取当前分钟
obj.getSeconds() 获取当前秒钟

🔰获取总的毫秒数:Date.now();

3. 倒计时案例实现

在这里插入图片描述

function conutDown(time) {
   
	var nowTIme = +new Date(); // 返回的时当前时间总的毫秒数
	var inputTime = +new Date(time); // 返回的是用户输入时间总的毫秒数
	var times = (inputTime - nowTIme) / 1000; // time 是剩余时间总的毫秒数
	var d = parseInt(times / 60 / 60 / 24); // 天
	d = d < 10 ? '0' + d : d;
	var h = parseInt(times / 60 / 60 % 24); // 时
	h = h < 10 ? '0' + h : h;
	var m = parseInt(times / 60 % 60); // 分
	m = m < 10 ? '0' + m : m;
	var s = parseInt(times % 60); // 当前的秒
	s = s < 10 ? '0' + s : s;
	return d + '天' + h + '时' + m + '分' + s + '秒';
}
alert(conutDown('2022-11-22 18:47:00'));

(四) 数组对象

利用 new 创建数组

var 数组名 = new Array();
var arr = new Array();

利用数组字面量创建数组

// 1. 使用数组字面方式创建空的数组
var 数组名 = [];
var arr = [];
// 2. 使用数组字面量方式创建带初始值的数组
var 数组名 = ['小白''小黑', '大黄'];
var arr = [1, 2, 3, 4];

🔰数组中可以存放任意类型的数据,例如字符串,数字,布尔值等;
🔰 arr.length动态检测数组元素的个数;
🔰可以通过修改数组索引追加数组元素。

// 利用 new Array() 创建数组
// var arr1 = new Array(); // 创建了一个空的数组
// var arr1 = new Array(2); // 这个2 表示:里面有2个空的数组元素
var arr1 = new Array(2, 3); // 等价于[2, 3] 这样写表示:里面有两个数组元素,是2和3

1. 添加和删除数组元素

方法 说明
Array.isArray(arr) 判断是否是一个数组
arr.push(i) 数组末尾添加元素
arr.unshift(i) 数组开头添加元素
arr.pop() 删除数组最后一个元素
arr.shift() 删除数组第一个元素
var arr = new Array();
Array.isArray(arr); // 判断是否为数组
arr.push(2, 1, 'pink'); // 在数组末尾,添加一个或多个数组元素
arr.unshift(3, 'lov'); // 在数组开头,添加一个或多个数组元素
arr.pop(); // 删除数组的最后一个元素,并返回删除的元素值
arr.shift(); // 删除数组的第一个元素,并返回删除的元素值

2. 数组排序

方法 说明
arr.reverse() 颠倒数组中元素的顺序
arr.sort() 对数组中元素进行排序
var arr = new Array(2, 16, 4, 7, 1);
arr.reverse(); // [1,7,4,6,2] 颠倒数组中元素的顺序
arr.sort(); // [1,2,4,6,7]  对数组中元素进行排序(0~9比较好使)
arr.sort(function(a, b) {
    // 对所有的数字都好使
   return a - b; // 升序排序
   // return b - a; // 降序排序
});

3. 数组索引方法

方法 说明
arr.indexOf(i) 查找指定素第一个索引号
arr.lastIndexOf(i) 查找指定 元素最后一个索引号
var arr = new Array(2, 16, 4, 4, 7, 1);
var ss = arr.indexOf(4); // 数组中查找给定元素的第一个索引,返回索引号,不存在返回-1
var s = arr.lastIndexOf(4); // 数组中的最后一个索引,返回索引号,不存在返回-1

4. 数组转换为字符串

方法 说明
arr.toString() 数组转换成字符串,用逗号分割
arr.join(‘/’) 数组转换成字符串,用户自定义分割字符
var arr = new Array(2, 16, 4, 4, 7, 1);
var ss = arr.toString(); // 把数组转换成字符串,逗号分隔每一项
       var s = arr.join(' '); // 方法用于把数组中的所有元素转换为一个字符串

(五) 字符串对象

1. 根据字符返回位置

方法 说明
indexOf(‘要查找的字符’, 开始的位置) 从前往后找,找不到返回-1
lastIndexOf(‘要查找的字符’, 开始的位置) 从后往前找,找不到返回-1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

码字小萌新♡

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

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

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

打赏作者

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

抵扣说明:

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

余额充值