Web | JavaScript之ECMAScript规范与BOM

1.JavaScript介绍

JavaScript web 开发人员必须学习的 3 门语言中的一门:

  1. HTML 定义了网页的内容
  2. CSS 描述了网页的布局
  3. JavaScript 网页的行为

JavaScript发展史:

  • 1992年,nombas公司发明了C–,最早的客户端脚本语言。专门用于表单验证。 后更名为 scriptEarth
  • 网景 scriptlive,后来找到sun公司合作,共同开发出 JavaScript
  • 微软根据JavaScript 定义了 JScript
  • ECMA(欧洲计算机制造商协会)定义了一套客户端脚本语言的规范 ECMAScript规范

为什么要学习JavaScript

  • 表单验证-减轻服务器端压力
  • 页面的动态交互
  • 页面动态效果

什么是JavaScript

  • JavaScript是一种基于对象和事件驱动的,并具有安全性能和脚本语言

JavaScript的特点

  • 向HTML页面中添加交互行为
  • 脚本语言,语法和Java类似
  • 解析型语言,边执行边解释

JavaScript组成

  • ECMAScript:描述了该语言的语法和基本语法
  • DOM:文档对象模型,描述处理网页内容的方法和接口
  • BOM:浏览器对象模型,描述与浏览器进行交互的方法和接口

2.网页中引入JS的方式

  • 方式1:内部js
    定义< script >标签,标签体书写js代码
    注意:< script >标签定义的位置,会影响执行顺序
<script type="text/javascript">
	<!--
		JavaScript语句;
	-->
</script>
  • 方式2:外部js
    定义< script >标签,通过src属性导入外部js文件
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<!-- 引入一个外部js文件 -->
		<script src="js/myjs.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
	</body>
</html>

在这里插入图片描述

3.ECMAScript规范

3.1 语法

  1. 常量

Java中的基本数据类型:

  • 整型:byte short int long
  • 浮点型:float double
  • 布尔型:boolean
  • 字符型:char

js原始数据类型:

  • number:数字类型,包含整数和小数和 NaN(not a number)
  • string: 字符串和字符类型 “” ‘’
  • boolean: true 和 false
  • null: 空类型。对象的占位符
  • undefined:未定义,如果一个变量没有初始化值,默认为undefined
  • ES6里可以定义常量 const
    运算符typeof可以查询原始数据类型
<script type="text/javascript">
			var num=3.2;
			alert(typeof num);
			const a=100;
			//a=500   常量不能被再次赋值
			alert(a);
</script>
  1. 变量
  • 使用 var定义变量 var i = “abc”
  • js是一门弱类型语言:定义变量时,不需要规定其数据类型。
  • typeof运算符:获取变量的数据类型
  • var关键字如果不书写,该变量则为全局变量
    示例
			var aa=100;
			function show1(){
				alert(aa);
				bb=10;//局部变量,前面不写var,就变成了全局变量
			}
			show1();
			
			function show2()
			{
				alert(bb);
			}
			show2();
//输出:100 10
  1. 语句
    if
    switch
    while
    do…while
    for
<script type="text/javascript">
			//for 语句
			for(var i=1;i<10;i++){
				document.write("<div style='color:red;font-size: 30px;'>"+i+"</div>");
				//函数里面写style,双引号变成单引号
			}
</script>

<body>
		<div style="color: yellow;font-size: 50px;">hello</div>
</body>

输出:
在这里插入图片描述
注意:方法里写http代码,要加双引号;
           http代码中如果有双引号,方法里要改写成单引号。

示例:九九乘法表

		<script type="text/javascript">
			for(var i=1;i<10;i++){
				for(var j=i;j<10;j++){
					//document.write(i+"*"+j+"="+(i*j));
					document.write(i+"*"+j+"="+(i*j)+"&nbsp;&nbsp")//&nbsp表示空格
				}
				document.write("<br />")//方法里写http代码,要加双引号
			}
		</script>
  1. 运算符
  • 一元运算符 ++ – +(正) -(负)
    在js中,如果传递给运算符的值,和 运算符想要接受的 值 的类型不匹配,则会自动类型转换

  • 比较运算符:> < >= <=
    1.NaN参与的运算,结果都为fasle,除了(!=)
    2.字符串比较小大:如果长度一致按照字典顺序比较 长度不一致 那谁的长度长那就谁大
    3.===(全等于):全等于比较时,先比较类型,如果类型不一致,直接返回false

//===与==的比较
		var aa="2";
		var bb=2;
		var flag1=(aa==bb);
		var flag2=(aa===bb);
		alert(flag1);
		alert(flag2);
//输出:true
//	   false

字符串的比较:用"=="比较,这和java是不同的

			//字符串的比较:用"=="比较
			var str1="abc";
			var str2="abc";
			if(str1==str2){
				document.write("两个字符串相同");
			}
//输出:两个字符串相同		
  • 逻辑运算符 && || !

  • 算术运算符:+ - * / %
    NaN 参与数学运算 结果都为NaN

  • 赋值运算符 = +=

  • 三元运算符:表达式 ? 值1 : 值2;


自动类型转换

当运算符运算的值,与期望值不一致时,就会发生自动类型转换

  • 其他类型转为number
    string:将字符串的字面值,转为number,如果字面值不是数字,则 转为NaN
    boolean: true为1 false 为0
//字符串转数字,字面能转数字,就转成数字;转不了的,转NaN
		var a="a2";
		var b=3;
		var c=a*b;
		alert(c);
		
//输出:NaN
		var num1="2";
		var num2=3;
		var num3=num1*num2;
		alert(num3);
		
//输出:6			
		//布尔类转数字 true 转1  false转成0
		var flag=true;
		var num4=flag+1;
		alert(num4);
//输出:2			
  • 其他类型转boolean
    number:非0为true,0和NaN为false
    string: 除了空字符串转为false,其他都是true
    null 和 undefined:转为false
		str3="";
		str4="a";
		if(str3){
			document.write("str3转为true");
		}else{
			document.write("str3转为flase");
			}
			document.write("<br />")
		if(str4){
			document.write("str4转为true");
		}else{
			document.write("str4转为flase");
			}
//输出:	str3转为flase
//      str4转为true		

3.2 函数

js是一门基于对象的语言。基于对象指的是,不能由原生的对象派生出新的对象。换句话说,不存在继承关系
基于对象的语言,最重要的一个概念就是函数

3.2.1 函数的创建

1.function fun( ){ }
2.var fun = function(){ }

		<script type="text/javascript">
			/* 方式1 */
			function show(){
				alert(10);
			}
			show();
	
			// 方法2
			var show2=function(){
				alert(20);
			}
			show2();
		</script>

3.2.2 函数的length属性

length:形参的个数
注:通过函数名.length调用该属性

			function show(a,b){
				alert(a+b);
			}
			show(1,2);
			var num= show.length;
			alert(num);
	        //输出:3,2

3.2.3 函数的参数与返回值

  1. JS里,函数的形参,不需要写数据类型
  2. JS里,调用函数时,可以不传,少传或者多传参数。
//函数的形参,不需要写数据类型
		function show1(a,b){
			return a+b;
		}
		var num1=show1(2,3);
		alert(num1);
//输出:5	
	    //调用函数时,可以不传,少传或者多传参数。
		var num2=show1(4,5,6);
		alert(num2);
//输出:9

上述两条可以理解为:函数的调用,只与函数名称有关,与实参列表无关

  1. 函数内部有内置对象 arguments 封装实参数组,可以把所有传递过来的参数,放到arguments数组中。
//函数内部有内置对象 arguments 封装实参数组,可以把所有传递过来的参数,放到arguments数组中。	
		function show2(a,b,c){
			alert(arguments[0]);
			alert(arguments[1]);
			alert(arguments[2]);
			alert(arguments[3]);
			alert(arguments[4]);
		}	
		show2(2,3,4,5);
// 输出: 2
// 	    3
// 	    4
// 	    5
//		undefined

3.2.4 void运算符

void运算符:拦截返回值,一般结合a标签一起使用,使a标签完成以下功能:注销a标签跳转功能,保留可被点击的功能

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script type="text/javascript">
			function judge()
			{
				var v=window.confirm("您确定要跳转吗?");
				if(v){
					location.href="http://www.baidu.com";
					}
			}
			
		</script>
	</head>
	<body>
		<a href="javascript:void(judge())">百度一下</a>
	</body>
</html>

在这里插入图片描述
在这里插入图片描述
点击ok,跳转百度;点击cancel,返回当前页面

3.2.5 闭包

资料来源:https://www.runoob.com/js/js-tutorial.html
预备知识1:自调用函数

  • 函数表达式可以 “自调用”。
  • 自调用表达式会自动调用。
  • 如果表达式后面紧跟 () ,则会自动调用。
  • 不能自调用声明的函数,通过添加括号,来说明它是一个函数表达式。
	(function(){document.write("hello");})();
//输出:hello

说明1:
对于函数自调用,必须通过把函数表达式外面添加括号(来说明它是一个函数表达式)再调用,否则会报错。

function() {document.write("hello");}();
// 报错:Uncaught SyntaxError: Unexpected token (

说明2:
现在我们知道函数表达式后面紧跟 () 会自动调用,但是如果把函数表达式赋给一个变量则不需要添加括号也可以直接调用。下方的代码中,函数表达式的主体部分会执行,并且会返回一个字符串给 x:

			var x=function() {
				document.write("hello");
				return "world";
			}();
			document.write(x);
//输出:helloworld	

预备知识2:匿名函数
JavaScript 函数可以通过一个表达式定义。
函数表达式可以存储在变量中:

var x = function (a, b) {return a * b};

在函数表达式存储在变量后,变量也可作为一个函数使用:

var x = function (a, b) {return a * b};
var z = x(4, 3);

以上函数实际上是一个 匿名函数 (函数没有名称)。
函数存储在变量中,不需要函数名称,通常通过变量名来调用。


闭包
闭包是一种保护私有变量的机制,在函数执行时形成私有的作用域,保护里面的私有变量不受外界干扰。直观的说就是形成一个不销毁的栈环境。

通过计数器困境来引入闭包。
设想下如果你想统计一些数值,且该计数器在所有函数中都是可用的。
你可以使用全局变量,函数设置计数器递增:

var counter = 0;
 
function add() {
   return counter += 1;
}
 
add();
add();
add();

// 计数器现在为 3

计数器数值在执行 add() 函数时发生变化。

但问题来了,页面上的任何脚本都能改变计数器,即便没有调用 add() 函数。

如果我在函数内声明计数器,如果没有调用函数将无法修改计数器的值:

function add() {
    var counter = 0;
    return counter += 1;
}
 
add();
add();
add();
 
// 本意是想输出 3, 但事与愿违,输出的都是 1 !

以上代码将无法正确输出,每次我调用 add() 函数,计数器都会设置为 1。


JavaScript 内嵌函数可以解决该问题。

所有函数都能访问全局变量。

实际上,在 JavaScript 中,所有函数都能访问它们上一层的作用域。

JavaScript 支持嵌套函数。嵌套函数可以访问上一层的函数变量。

该实例中,内嵌函数 plus() 可以访问父函数的 counter 变量:

function add() {
    var counter = 0;
    function plus() {counter += 1;}
    plus();    
    return counter; 
}

如果我们能在外部访问 plus() 函数,这样就能解决计数器的困境。

我们同样需要确保 counter = 0 只执行一次。


我们需要闭包。

var add = (function () {
    var counter = 0;
    return function () {return counter += 1;}
})();
//外层function是自调用的匿名函数;内层function函数是每次被调用的匿名函数。
 
add();
add();
add();
 
// 计数器为 3

注意: 为什么上面这段代码没有直接写的 function add (){…} 而是把function赋值给了变量add呢?

我们通常会想当然的认为每次调用 add() 都会重走一遍add()中的代码块, 但其实不然。

注意add方法中的return, 它return的并不是1,2,3这样的数值,而是return了一个方法,并且把这个方法赋值给了add变量。

那么在这个function自运行一遍之后,其实最后赋值给add的是return counter += 1 这段代码。

所以后面每次调用add() 其实都是在调用return counter += 1。

再结合文章之前所说的, 闭包会持有父方法的局部变量并且不会随父方法销毁而销毁, 所以这个counter其实就是来自于第一次function执行时创建的变量。

yr注:本人的理解就是,外层function是自调用的匿名函数;内层function函数是每次被调用的匿名函数。


另一种理解方式,可以将以上代码分解如下:

function outerFunction() {
    var counter = 0;
    function innerFunction(){
        return counter += 1;
    }
    return innerFunction;
    /*
     注意 typeof innerFunction 是:function;而typeof innerFunction()是number;
    */
}
var add = outerFunction();

/* 
调用 outerFunction()返回的是内部函数innerFucntion,那么调用几次add()将调用几次
内部函数inner Function,内部函数公用了counter,所以能够计数,所以说闭包就是将内部嵌套函数变成外部可调用的。
*/

add();
add();
add();

3.3 JS中的内置对象

3.3.1 String对象

String 对象用于处理文本(字符串)。

String 对象属性

  • length 字符串的长度

String 对象方法

  • charAt() 返回在指定位置的字符。
  • concat() 连接字符串。
  • indexOf() 根据字符检索此符在字符串中的索引。
  • lastIndexOf() 从后向前搜索字符串。
  • substring() 提取字符串中两个指定的索引号之间的字符
  • toLowerCase() 把字符串转换为小写。
  • toUpperCase() 把字符串转换为大写。
  • replace() 替换字符串。
  • split() 把字符串分割为字符串数组。
  • trim():去除字符串两端的空格
3.3.2 Number 对象

Number 对象是原始数值的包装对象。

创建 Number 对象的语法:

  • var myNum=new Number(value);
  • var myNum=Number(value);

Number 对象属性

  • MAX_VALUE 可表示的最大的数。
  • MIN_VALUE 可表示的最小的数。

Number 对象方法

  • toString 把数字转换为字符串,使用指定的基数。
  • toFixed 把数字转换为字符串,可把 Number 四舍五入为指定小数位数的数字。
  • toPrecision 把数字格式化为指定的长度。
3.3.3 Date 对象

Date 对象用于处理日期和时间。
创建 Date 对象的语法:

  • var myDate=new Date()

Date 对象方法
在这里插入图片描述

3.3.4 Math 对象

Math 对象用于执行数学任务。

该对象不需要创建 直接对象名点上方法

Math 对象属性

  • E 返回算术常量 e,即自然对数的底数(约等于2.718)。
  • PI 返回圆周率(约等于3.14159)。

Math 对象方法

  • Math.random();随机产生0----1 之间的随机数
  • Math.round(2.36); 对小数进行四舍五入 得到一个整数
  • Math.ceil(3.82);向上取整
  • Math.floor(2.6);向下取整
  • Math.min(15,25); 取最小值
  • Math.min(15,25); 取最小值
  • Math. abs(-2) 返回数的绝对值。

示例:生成四位随机验证码

			var str="abcdfghijklmnopqrtuvwxyz123456798";
			for(var i=1;i<=4;i++){
				var num=Math.floor(Math.random()*str.length);
				var s=str.charAt(num);
				document.write(s);
			}
3.3.5 Array 对象

Array 对象用于在单个的变量中存储多个值。
注意:JS中的数组长度是可变的;JS中的数组元素可以是任意类型

创建 Array 对象的语法:

  • new Array();
  • new Array(size);
  • new Array(element0, element1, …, elementn);

Array 对象属性

  • length 设置或返回数组中元素的数目。

Array 对象方法

  • concat() 连接两个或更多的数组,并返回结果。
  • join() 把数组的所有元素放入一个字符串。元素通过指定的分隔符进行分隔。
  • pop() 删除并返回数组的最后一个元素
  • push() 向数组的末尾添加一个或更多元素,并返回新的数组长度。
  • reverse() 颠倒数组中元素的顺序。
  • shift() 删除并返回数组的第一个元素
  • slice() 从某个已有的数组返回选定的元素
  • sort() 对数组的元素进行排序 从小到大
    默认排序方式:字典顺序
    要想实现自己的比较方式,需要传入比较器方法对象
			var arr=new Array();
			arr=[10,51,68,7,6,21,75];
			var arr1=arr.sort();//字典顺序
			document.write(arr1);
			document.write("<br />")
			var arr2=arr.sort((a,b)=>a-b);//从小到大排序
			document.write(arr2);
//输出: 10,21,51,6,68,7,75 
//       6,7,10,21,51,68,75	
3.3.6 RegExp 对象

RegExp 对象表示正则表达式,它是对字符串执行模式匹配的强大工具。

创建 RegExp 对象的语法:

  • new RegExp(pattern, attributes);

    参数 pattern 是一个字符串,指定了正则表达式的模式或其他正则表达式。

    参数 attributes 是一个可选的字符串,包含属性 “g”、“i” 和 “m”,分别用于指定全局匹配、区分大小写的匹配和多行匹配。ECMAScript 标准化之前,不支持 m 属性。如果 pattern 是正则表达式,而不是字符串,则必须省略该参数。

			//创建正则对象
	    	var regx=/[a-z]{6,16}/i;
			//i 模式 不区分大小写的匹配
			var str="abfhdfds";
			var flag=regx.test(str);
			document.write(flag);
//输出:true	

修饰符:

  • i 执行对大小写不敏感的匹配。
  • g 执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。
  • m 执行多行匹配。

g 执行全局匹配的示例:

			//以string对象中的replace方法为例:
			//如果 regexp 具有全局标志 g,那么 replace() 方法将替换所有匹配的子串。
			//否则,它只替换第一个匹配子串
			var str="aaa=bbb=ccc=ddd=eee"; //aaabbbccc
			
			var s1=str.replace(/=/g,'');
			var s2=str.replace(/=/,'');
			document.write(s1+"<br />");
			document.write(s2+"<br />");
//输出:			
//aaabbbcccdddeee
//aaabbb=ccc=ddd=eee

RegExp 对象方法

  • exec 检索字符串中指定的值。返回找到的值,并确定其位置。
  • test 检索字符串中指定的值。返回 true 或 false。

支持正则表达式的 String 对象的方法

  • search 检索与正则表达式相匹配的值。
  • match 找到一个或多个正则表达式的匹配。
  • replace 替换与正则表达式匹配的子串。
  • split 把字符串分割为字符串数组。
//查找出三个字符组成的单词。
			var str  ="da jia hao hao xue xi a";
			var regx=/\b[a-z]{3}\b/g;
			var v=regx.exec(str);
			while(v!=null){
				document.write(v);
				document.write("<br />");
				v=regx.exec(str);
			}
//输出:			
// jia
// hao
// hao
// xue			
3.3.7 Global 对象

全局属性和函数可用于所有内建的 JavaScript 对象。

特点
该对象中的方法调用,不需要对象的引用,可直接使用。

顶层函数(全局函数)

  • isNaN() 检查某个值是否是数字。
    == 无法判断两个NaN是否相等,需要专门用一个函数来比较
		var v=NaN;
		var f=isNaN(v);
		alert(f);
//输出:true		
  • parseInt() 解析一个字符串并返回一个整数。
		var s1="123abc"	;
		var num1=parseInt(s1);
		document.write(num1);
//输出:	123
  • parseFloat() 解析一个字符串并返回一个浮点数。
  • decodeURI() 解码某个编码的 URI。
  • encodeURI() 把字符串编码为 URI。
		var s=decodeURI("%E5%BC%A0%E4%B8%89");
		document.write(s);
//张三
		var s2=encodeURI("李四");
		document.write(s2);
//%E6%9D%8E%E5%9B%9B
3.3.8 ES6中数组新增方法
  • filter() 检测数值元素,并返回符合条件所有元素的数组。
  • forEach() 数组每个元素都执行一次回调函数。
  • isArray() 判断对象是否为数组。
  • indexOf() 搜索数组中的元素,并返回它所在的位置。
  • reduce() 将数组元素计算为一个值(从左到右)。
  • map() 通过指定函数处理数组的每个元素,并返回处理后的数组。

4 BOM

浏览器对象模型(Browser Object Model):提供了独立于内容的,可以与浏览器窗口进行互动的对象结构,结构图如下:
在这里插入图片描述
可实现功能:

  • 弹出新的浏览器窗口
  • 移动、关闭浏览器窗口以及调整窗口的大小
  • 页面的前进,后退

特点:
BOM对象不能自己创建,当文档加载进内存,浏览器自动创建。

组成:
1.Window:窗口对象
2.Location:地址栏对象
3.History:历史记录(当前窗口)对象
4.Navigator :浏览器对象
5.Screen:显示器屏幕

			//window 对象中的属性
			var doc=window.document  //获取html 文档对象
			var l=window.location;//获取地址栏对象
			var h=window.history;//获取历史记录对象
			var s=window.screen;//获取屏幕屏幕对象
			var n=window.navigator;//获取整个浏览器对象

4.1 Window:窗口对象

使用方式
window.方法名();
注意:window 可以省略

4.1.1 与弹出有关的方法

  • alert() 显示带有一段消息和一个确认按钮的警告框。
  • confirm() 显示带有一段消息以及确认按钮和取消按钮的对话框。
  • prompt(参数1,参数2) 显示可提示用户输入的对话框。 //参数2:默认文字
			//window 对象可以省略不写
			window.alert("警告框");
			//确认取消框
			var r=window.confirm("你确定吗?")
			document.write(r);
			//弹出一个输入框
			//prompt() 显示可提示用户输入的对话框。 
			var text=window.prompt("请输入你的收获地址",".com");
			document.write(text);

4.1.2 与定时器有关的方法

  • setInterval() 按照指定的周期(以毫秒计)来调用函数或计算表达式。 循环执行

  • clearInterval() 取消由 setInterval() 设置的 timeout。

  • setTimeout() 在指定的毫秒数后调用函数或计算表达式。 只执行一次
    参数1:字符串(js语句)或者 函数对象
    参数2:毫秒值。

  • clearTimeout() 取消由 setTimeout() 方法设置的 timeout。

   	var timeID=window.setTimeout(function () {
   		alert("执行了");
   	}, 3000)

示例:页面时钟

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    测试
    <div id="time"></div>
</body>
<script>
    var myTime;
    setInterval(showTime,1000);
    function showTime(){
        myTime=new Date();
        var time=myTime.toLocaleString();
        document.getElementById("time").innerText=time;
    }
    showTime();

</script>
</html>

4.1.3 与打开关闭有关的方法

  • open():打开新窗口
    参数:打开目标的URL
    返回值:返回新打开窗口的window引用

  • close():关闭窗口
    谁调用,关闭谁。

  var win=null;
    function openURL() {
        if(window.confirm("要进入页面吗?")){
            win=window.open("demo.html");
        }
    }
    function closeWin(){
        if(window.confirm("要关闭页面吗?")){
            win.close();
        }
    }
    
    function closeWinNow(){
        window.close();
    }

4.2 Location:地址栏对象

常用属性:
在这里插入图片描述
常用方法:
在这里插入图片描述

4.3 History:历史记录对象

常用方法:
在这里插入图片描述
go方法的参数:
1:前进
-1:后退

4.4 Document对象

常用属性:
在这里插入图片描述
常用方法:
在这里插入图片描述

作用:

  • 判断页面是否是链接进入
  • 自动跳转到登录页面
  • 动态改变层,标签中的内容
  • 访问相同name的元素

示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div id="a"></div>
    <input type="button" onclick="test()" value="显示" style="height: 50px;width: 50px">
    <input type="button" onclick="test2()" value="隐藏" style="height: 50px;width: 50px">
</body>
<script>
    function test(){
        document.getElementById("a").innerText="彩蛋";
    }
    function test2(){
        document.getElementById("a").innerText="";
    }
</script>
</html>

在这里插入图片描述
点击显示
在这里插入图片描述

4.5 总结

4.5.1 事件

在这里插入图片描述

4.5.2 常用方法

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值