JavaScript ES6

目录

变量声明

弱类型

在JS中变量类型由所引用的值决定

	var web = "web";
	console.log(typeof web); //string
	web = 99;
	console.log(typeof web); //number
	web = true;
	console.log(typeof web); //boolean
	web = {
   };
	console.log(typeof web); //object

使用分号表示一段指令的结束,当没有输入分号时如果有换行符JS会自动添加分号,减少错误的发生。
但推荐每个指令都以分号结束
在使用构建工具时,不使用分号结束可能会造成异常

变量提升

变量提升示例
下面是 if(false) 中定义的var也会发生变量提升,注释掉if 结果会不同

var web = "js";
function hd() {
   
  if (false) {
   
    var web = "javascript";
  }
  console.log(web);
}
hd();

解析器会先解析代码,然后把声明的变量的声明提升到最前,这就叫做变量提升。

下面代码在解析过程中发现while不能做为变量名,没有到执行环节就出错了。

var web = 'houdunren';
console.log(web);
let while = 'hdcms'; //Uncaught SyntaxError: Unexpected token 'while'

使用 var 声明代码会被提升到前面,赋值还在原位置

console.log(a); //undefined
var a = 1;
console.log(a);  //1

//以上代码解析器执行过程如下
var a;
console.log(a); //1
a = 1;
console.log(a); //1

变量作用域

var

使用 var 声明的变量存在于最近的函数或全局作用域中,没有块级作用域的机制。

没有块作用域很容易污染全局,下面函数中的变量污染了全局环境

function run() {
   
  web = "web";
}
run();
console.log(web); //web

没有块作用作用域时var也会污染全局

for (var i = 0; i < 10; i++) {
   
  console.log(i);
}
console.log(i);

下例中体验到 var 没有块作用域概念, do/while 定义的变量可以在块外部访问到

var num = 0;

function show() {
   
  var step = 10;
  do {
   
    var res = 0;
    console.log(num = step++);
    res = num;
  } while (step < 20);
  console.log(`结果是${
     res}`);
}
show();

var 全局声明的变量也存在于 window对象中

var hd = "houdunren";
console.log(window.hd); //houdunren

以往没有块任用时使用立即执行函数模拟块作用域

(function() {
   
  var $ = this.$ = {
   };
  $.web = "web";
}.bind(window)());
console.log($.web);

有了块作用域后实现就变得简单多了

{
   
  let $ = (window.$ = {
   });
  $.web = "web";
}
console.log($.web);
let

与 var 声明的区别是 let/const 拥有块作用域,下面代码演示了块外部是无法访问到let声明的变量。

建议将let在代码块前声明
用逗号分隔定义多个
let存在块作用域特性,变量只在块域中有效

if (true) {
   
    let web = 'whs',url = 'icebound.com';
    console.log(web); //whs
}
console.log(web); //web is not defined

块内部是可以访问到上层作用域的变量

if (true) {
   
  let user = "whs";
  (function() {
   
    if (true) {
   
      console.log(`这是块内访问:${
     user}`);
    }
  })();
}
console.log(user);

每一层都是独立作用域,里层作用域可以声明外层作用域同名变量,但不会改变外层变量

function run() {
   
  hd = "icebound";
  if (true) {
   
    let hd = "whs";
    console.log(hd); //whs
  }
  console.log(hd); //icebound
}
run();
const

使用 const 用来声明常量,这与其他语言差别不大,比如可以用来声明后台接口的URI地址。

  • 常量名建议全部大写
  • 只能声明一次变量
  • 声明时必须同时赋值
  • 不允许再次全新赋值
  • 可以修改引用类型变量的值
  • 拥有块、函数、全局作用域
  • 常量不允许全新赋值举例
	try {
   
	  const URL = "https://www.baidu.com";
	  URL = "https://www.icebound.com"; //产生错误
	} catch (error) {
   
	  throw new Error(error);
	}

改变常量的引用类型值,可以使用Object的冻结方法冻结

	const INFO = {
   
      url: "https://www.icebound.com",
      port: "8080",
    };
    INFO.port = "443";
    console.log(INFO);//{url: "https://www.icebound.com", port: "443"}



    const HOST = {
   
      url: "https://www.icebound.com",
      port: "8080",
    };
    Object.freeze(HOST)
    HOST.port = "443";
    console.log(HOST);//{url: "https://www.icebound.com", port: "8080"}

下面演示了在不同作用域中可以重名定义常量

	const NAME = '后盾人';
	
	function show() {
   
	  const NAME = '向军大叔';
	  return NAME;
	}
	console.log(show());
	console.log(NAME);
重复定义

使用 var 可能造成不小心定义了同名变量

//优惠价
var price = 90;
//商品价格
var price = 100;
console.log(`商品优惠价格是:${
     price}`);

使用let 可以避免上面的问题,因为let声明后的变量不允许在同一作用域中重新声明

let web = 'houdunren.com';
let web = '后盾人'; //Identifier 'web' has already been declared

不同作用域可以重新声明

let web = 'houdunren.com';
if (true) {
   
	let web = '后盾人'; //Identifier 'web' has already been declared
}

严格模式

严格模式可以让我们及早发现错误,使代码更安全规范,推荐在代码中一直保持严格模式运行。

主流框架都采用严格模式,严格模式也是未来JS标准,所以建议代码使用严格模式开发

#基本差异
变量必须使用关键词声明,未声明的变量不允许赋值

"use strict";
url = 'icebound.com'; //url is not defined

强制声明防止污染全局

"use strict";
function run() {
   
  web = "icebound";
}
run();
console.log(web); //houdunren

关键词不允许做变量使用

"use strict";
var public = 'icebound.com';

变量参数不允许重复定义

"use strict";
//不允许参数重名
function hd(name, name) {
   } 

单独为函数设置严格模式

function strict(){
     
  "use strict";  
  return "严格模式";  
}  
function notStrict() {
     
  return "正常模式";  
}  

为了在多文件合并时,防止全局设置严格模式对其他没使用严格模式文件的影响,将脚本放在一个执行函数中。

(function () {
   
  "use strict";
  url = 'houdunren.com';
})();

比较运算符

赋值运算符

使用 = 进行变量赋值

let url = 'icebuond.com';
算术运算符

包括以下几种算术运算符。

运算符 说明

示例 符号
* 乘法
/ 除法
+ 加法
- 减法
% 取余数
let a = 5,b = 3;
console.log(a * b); //15
console.log(a % b); //2
复合运算符

可以使用 =、/=、+=、-=、%= 简写算术运算。即 n=2 等同于 n=n*2。

let n = 2;
n *= 2;
console.log(n);

对变量加减相应数值。

let n = 2;
n += 3;
console.log(n); //0
n -= 5;
console.log(n); //5

n+=3 是 n=n+3 的简写形式
一元运算符

前置操作
前置操作会在表达式最先执行。

let n = 1;
++n
console.log(n);
--n
console.log(n);

++n 就是 n=n+1 的简写形式。

使用后置操作符,++n 会在最先执行,所以f的结果是33。

let n = 2;
let f = 30 + ++n;
console.log(f);

后置操作
后置操作会在表达式最后执行。

let n = 1;
n++
console.log(n);

使用后置操作符,n++ 会在最后执行,所以f的结果是32。

let n = 2;
let f = 30 + n++;
console.log(f);

参与数学计算

let a = 1;
b = a++ + 2;
console.log(b); //3
比较运算符
运算符 说明
> 大于
< 小于
>= 大于或等于
<= 小于等于
== 强制类型转换比较
=== 不强制类型转换比较

下面来体验不同类型的比较结果

let a = 1,b = 2,c = '1';

console.log(a < b); //true
console.log(a == b); //false
console.log(a == c); //true
console.log(a === c); //false
console.log(a == true); //true
console.log(a === true); //false

==的类型装换规则

value1 value2 转换后统一类型 结果
boolean number number 仅成立true==1,false ==0
boolean string number 仅成立true==“1”,false ==“0”
boolean object string 永为假
number string number ---------
number object string 永为假
string object string 等同于 string==object.toString()仅且string="[object Object]"时成立

这样会导致一种 字符串“3”不等于真且不等于假的结果,所以不建议使用==和boolean之间做比较

逻辑运算符

逻辑与
使用 && 符号表示逻辑与,指符号两端都为 true 时表达式结果为true。

let a = true,b = true;
if (a && b) {
   
    console.log('表达式成立');
}

逻辑或
使用 || 符号表示逻辑或,指符号左右两端有一方为true,表达式即成立。

let a = true,b = false;
if (a || b) {
   
    console.log('表达式成立');
}

逻辑非
使用 ! 符号表示逻辑非,即原来是true转变为false,反之亦然。

let a = true,b = false;
if (a && !b) {
   
    console.log('表达式成立');
}

优先级
下列中因为 && 的优先级高所以结果是 true。

console.log(true || false && false);

可以使用 () 来提高优先级

console.log((true || false) && false);

流程控制

if

当条件为真时执行表达式代码块。

let state = true;
if (true) {
   
    console.log('表达式成立');
}

如果只有一条代码块,可以不用写 {}

let state = true;
if (true)
    console.log('表达式成立');
console.log('一直都显示的内容');

if(value)中参数value会自动调用Boolean的构造方法,js允许对象都放在if判断中并给出结果,但Boolean构造方法和value==true是有区别的

 function test(a) {
   
      if (a) {
   
        console.log("if(a) yse");
      } else {
   
        console.log("if(a) no");
      }
      console.log(Boolean(a));
      if (a == true) {
   
        console.log("if(a==true) yes");
      } else {
   
        console.log("if(a==true) no");
      }
      if (a == false) {
   
        console.log("if(a==false) yes");
      } else {
   
        console.log("if(a==false) no");
      }
    }
    test(2);
    // if(a) yse
    // true
    // if(a==true) no
    // if(a==false) yes

    test("abcd");
    // if(a) yse
    // true
    // if(a==true) no
    // if(a==false) no
if/else

下面是使用多条件判断密码强度的示例

<body>
  <input type="password" name="title" />
  <span></span>
</body>
<script>
  let input = document.querySelector("[name='title']");
  input.addEventListener("keyup", function() {
   
    let length = this.value.length;
    let msg;
    if (length > 10) {
   
      msg = "密码已经无敌了";
    } else if (length > 6) {
   
      msg = "密码安全性中级";
    } else {
   
      msg = "这密码,要完的节奏";
    }
    document.querySelector("span").innerHTML = msg;
  });
</script>
三元表达式

是针对 if 判断的简写形式。

let n = true ?'yes' : 'no';
console.log(n); //yes

let f = true ? (1 == true ? 'yes' : 'no') : 3;
console.log(f); // yes
switch

可以将 switch 理解为 if 的另一种结构清晰的写法。

如果表达式等于 case 中的值,将执行此 case 代码段
break 关键字会终止 switch 的执行
没有任何 case匹配时将执行default 代码块
如果case执行后缺少break则接着执行后面的语句

let name = '视频';
switch (name) {
   
    case '产品':
        console.log('hdcms.com');
        break;
    case '视频':
        console.log('houdunren.com');
        break;
    default:
        console.log('houdunwang.com')
}

case 合用示例

let error = 'warning';
switch (error) {
   
  case 'notice':
  case 'warning':
      console.log('警告或提示信息');
      break;
  case 'error':
      console.log('错误信息');
}switchcase 都可以使用表达式

function message(age) {
   
  switch (true) {
   
    case age < 15:
      console.log("儿童");
      break;
    case age < 25:
      console.log("青少年");
      break;
    case age < 40:
      console.log("青年");
      break;
    case age < 60:
      console.log("中年");
      break;
    case age < 100:
      console.log("老年");
      break;
    default:
      console.log("年龄输出错误");
  }
}
message(10);

下面例子缺少break 后,会接着执行后面的switch代码。

switch (1) {
   
  case 1:
    console.log(1);
  case 2:
    console.log(2);
  default:
    console.log("default");
}
while

循环执行语句,需要设置跳出循环的条件否则会陷入死循环状态。下面是循环输出表格的示例。

let row = 5;
document.write(`<table border="1" width="100">`);
while (row-- != 0) {
   
  document.write(`<tr><td>${
     row}</td></tr>`);
}
document.write(`</table>`);
do/while
function hd(row = 5) {
   
  let start = 0;
  do {
   
    let n = 0;
    do {
   
      document.write("*");
    } while (++n <= start);
    document.write("<br/>");
  } while (++start <= row);
}
hd();
for

可以在循环前初始化初始计算变量。下面是使用for 打印倒三角的示例

for (let i = 10; i > 0; i--) {
   
    for (let n = 0; n < i; n++) {
   
        document.write('*');
    }
    document.write("<br/>");
}

for的三个参数可以都省略或取几个

let i = 1;
for (; i < 10; ) {
   
  console.log(i++);
}
break/continue

break用于退出当前循环,continue用于退出当前循环返回循环起始继续执行。

获取所有偶数,所有奇数使用 continue 跳过

for (let i = 1; i <= 10; i++) {
   
  if (i % 2) continue;
  console.log(i);
}

获取三个奇数,超过时使用 break退出循环

let count = 0,num = 3;
for (let i = 1; i <= 10; i++) {
   
  if (i % 2) {
   
    console.log(i);
    if (++count == num) break;
  }
}
label

标签(label) 为程序定义位置,可以使用continue/break跳到该位置。

下面取i+n 大于15时退出循环

houdunren: for (let i = 1; i <= 10; i++) {
   
  hdcms: for (let n = 1; n <= 10; n++) {
   
    if (n % 2 != 0) {
   
      continue hdcms;
    }
    console.log(i, n);
    if (i + n > 15) {
   
      break houdunren;
    }
  }
}
for/in

用于遍历对象的所有属性,for/in主要用于遍历对象,不建议用来遍历数组。

遍历数组操作

let hd = [
  {
    title: "第一章 走进JAVASCRIPT黑洞", lesson: 3 },
  {
    title: "ubuntu19.10 配置好用的编程工作站", lesson: 5 },
  {
    title: "媒体查询响应式布局", lesson: 8 }
];
document.write(`
  <table border="1" width="100%">
  <thead><tr><th>标题</th><th>课程数</th></thead>
`);
for (let key in hd) {
   
  document.write(`
  
  <tr>
  <td>${
     hd[key].title}</td>
  <td>${
     hd[key].lesson}</td>
  </tr>
  `);
}
document.write("</table>");

遍历对象操作

let info = {
   
  name: "后盾人",
  url: "houdunren.com"
};
for (const key in info) {
   
  if (info.hasOwnProperty(key)) {
   
    console.log(info[key]);
  }
}

遍历window对象的所有属性

for (name in window) {
   
  console.log(window[name]);
}
for/of

用来遍历 Arrays(数组), Strings(字符串), Maps(映射), Sets(集合)等可迭代的数据结构。

与 for/in 不同的是 for/of 每次循环取其中的值而不是索引。

后面在讲到遍历器 章节后大家会对for/of有更深的体会

let arr = [1, 2, 3];
for (const iterator of arr) {
   
    console.log(iterator);
}

遍历字符串

let str = 'icebound';
for (const iterator of str) {
   
    console.log(iterator);
}

使用迭代特性遍历数组

const hd = ["whs", "icebound"];

for (const [key, value] of hd.entries()) {
   
  console.log(key, value); //这样就可以遍历了
}

使用for/of 也可以用来遍历DOM元素

<body>
  <ul>
    <li></li>
    <li></li>
  </ul>
</body>
<script>
  let lis = document.querySelectorAll("li");
  for (const li of lis) {
   
    li.addEventListener("click", function() {
   
      this.style.backgroundColor = "red";
    });
  }
</script>

基本类型

类型检测

JS提供了非常丰富的数据类型,开发者要学会使用最适合的数据类型处理业务 。

typeof
typeof 用于返回以下原始类型

  • 基本类型:number/string/boolean
  • function
  • object
  • undefined
    可以使用typeof用于判断数据的类型
let a = 1;
console.log(typeof a); //number

let b = "1";
console.log(typeof b); //string

//未赋值或不存在的变量返回undefined
var hd;
console.log(typeof hd);

function run() {
   }
console.log(typeof run); //function

let c = [1, 2, 3];
console.log(typeof c); //object

let d = {
    name: "icebound.com" };
console.log(typeof d); //object

instanceof
instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。

也可以理解为是否为某个对象的实例,typeof不能区分数组,但instanceof则可以。

后面章节会详细介绍原型链

let whs = [];
let icebound = {
   };
console.log(whs instanceof Array); //true
console.log(icebound instanceof Array); //false

let c = [1, 2, 3];
console.log(c instanceof Array); //true

let d = {
    name: "icebound.com" };
console.log(d instanceof Object); //true

function User() {
   }
let user = new User();
console.log(user  instanceof User); //true

值类型与对象
下面是使用字面量与对象方法创建字符串,返回的是不同类型。

let hd = "icebound";
let cms = new String("whs"); 
console.log(typeof hd, typeof cms); //string object

只有对象才有方法使用,但在JS中也可以使用值类型调用方法,因为它会在执行时将值类型转为对象。

let hd = "icebound";
let cms = new String("whs");
console.log(hd.length); 
console.log(cms.length); 

String

字符串类型是使用非常多的数据类型,也是相对简单的数据类型。

声明定义
使用对象形式创建字符串

let hd = new String('icebound');
// 获取字符串
console.log(hd.toString());

字符串使用单、双引号包裹,单、双引号使用结果没有区别。

let content = whs";
console.log(content);
转义符号

有些字符有双层含义,需要使用 \ 转义符号进行含义转换。下例中引号为字符串边界符,如果输出引号时需要使用转义符号。

let content = '后盾人 \'houduren.com\'';
console.log(content);

常用转义符号列表如下

符号 说明
\t 制表符
\n 换行
\ 斜杠符号
单引号
" 双引号R

连接运算符
使用 + 可以连接多个内容组合成字符串,经常用于组合输出内容使用。

模板字面量
使用 ` 符号包裹的字符串中可以写入引入变量与表达式

let url = 'whs';
console.log(`作者是是${
     url}`); //后盾人网址是houdunren.com

支持换行操作不会产生错误

let url = 'houdunren.com';
document.write(`后盾人网址是${
     url}
大家可以在网站上学习到很多技术知识`);

使用表达式

function show(title) {
   
	return `ES6`;
}
console.log(`JavaScript可使用模板字面量的版本是${
     show()}`)

模板字面量支持嵌套使用

let lessons = [
	{
   title: '媒体查询响应式布局'},{
   title: 'FLEX 弹性盒模型'},{
   title: 'GRID 栅格系统'}
];

function template() {
   
  return `<ul>
      ${
     lessons.map((item)=>`
          <li>${
     item.title}</li>
      `).join('')}
  </ul>`;
}
document.body.innerHTML = template();

标签模板
标签模板是提取出普通字符串与变量,交由标签函数处理

let lesson = 'css';
let web = '后盾人';
tag `访问${
     web}学习${
     lesson}前端知识`;

function tag(strings, ...values) {
   
    console.log(strings); //["访问", "学习", "前端知识"]
    console.log(values); // ["后盾人", "css"]
}

下面例子将标题中有后盾人的使用标签模板加上链接

let lessons = [
  {
    title: "后盾人媒体查询响应式布局", author: "后盾人向军" },
  {
    title: "FLEX 弹性盒模型", author: "后盾人" },
  {
    title: "GRID 栅格系统后盾人教程", author: "古老师" }
];

function links(strings, ...vars) {
   
  return strings
    .map((str, key) => {
   
      return (
        str +
        (vars[key]
          ? vars[key].replace(
              "后盾人",
              `<a href="https://www.houdunren.com">后盾人</a>`
            )
          : "")
      ); 
    })
    .join("");
}

function template() {
   
  return `<ul>
    ${
     lessons
      .map(item => links`<li>${
     item.author}:${
     item.title}</li>`)
      .join("")}
</ul>`;
}
document.body.innerHTML += template();

获取长度
使用length属性可以获取字符串长度

console.log("icebound".length)

大小写转换
将字符转换成大写格式

console.log('icebound'.toUpperCase()); //ICEBOUND

转字符为小写格式

console.log('ICEBOUND'.toLowerCase()); //icebound

移除空白
使用trim删除字符串左右的空白字符

let str = '   icebound  ';
console.log(str.length);
console.log(str.trim().length);

使用trimLeft删除左边空白,使用trimRight删除右边空白

let name = " whs ";
console.log(name);
console.log(name.trimLeft());
console.log(name.trimRight()); 

trim方法不会改变原字符串

let name = " whs ";
console.log("|"+name+"|");//| whs |
console.log("|"+name.trim()+"|");//|whs|
console.log("|"+name+"|"); //| whs |

获取单字符
根据从0开始的位置获取字符

console.log('houdunren'.charAt(3))

使用数字索引获取字符串

console.log('houdunren'[3])

截取字符串
使用 slice、substr、substring 函数都可以截取字符串。
slice、substring 第二个参数为截取的结束位置
substr 第二个参数指定获取字符数量

let hd = 'icebound';
console.log(hd.slice(3)); //bound
console.log(hd.substr(3)); //bound
console.log(hd.substring(3)); //bound

console.log(hd.slice(3, 6)); //bou
console.log(hd.substring(3, 6)); //bou
console.log(hd.substring(3, 0)); //ice 较小的做为起始位置
console.log(hd.substr(3, 6)); //bound

console.log(hd.slice(3, -1)); //boun 第二个为负数表示从后面算的字符
console.log(hd.slice(-2));//nd 从末尾取
console.log(hd.substring(3, -9)); //ice 负数转为0
console.log(hd.substr(-3, 2)); //un 从后面第三个开始取两个

查找字符串
从开始获取字符串位置,检测不到时返回 -1

console.log('icebound'.indexOf('c')); //1
console.log('icebound'.indexOf('d', 3)); //7 从第3个字符向后搜索

从结尾来搜索字符串位置

console.log('icebound.com'.lastIndexOf('o')); //10
console.log('icebound.com'.lastIndexOf('o', 7)); //4 从第7个字符向前搜索

search() 方法用于检索字符串中指定的子字符串,也可以使用正则表达式搜索

let str = "icebound.com";
console.log(str.search("com"));
console.log(str.search(/\.com/i));

includes 字符串中是否包含指定的值,第二个参数指查找开始位置

console.log('icebound.com'.includes('o')); //true
console.log('icebound.com'.includes('0', 7)); //true

startsWith 是否是指定位置开始,第二个参数为查找的开始位置。

console.log('icebound.com'.startsWith('o')); //true
console.log('icebound.com'.startsWith('o', 1)); //true

endsWith 是否是指定位置结束,第二个参数为查找的结束位置。

console.log('icebound.com'.endsWith('com')); //true
console.log('icebound.com'.endsWith('o', 2)); //true

下面是查找关键词的示例

const words = ["js", "css"];
const title = "js es6";
const status = words.some(word => {
   
  return title.includes(word);
});
console.log(status);

替换字符串
replace 方法用于字符串的替换操作

let name = "icebound";
web = name.replace("ice", "whs");
console.log(web);

默认只替换一次,如果全局替换需要使用正则

let str = "2023/02/12";
console.log(str.replace(/\//g, "-"));

使用字符串替换来生成关键词链接

const word = ["js", "css"];
const string = "学习js与css知识";
const title = word.reduce((pre, word) => {
   
  return pre.replace(word, `<a href="?w=${
     word}">${
     word}</a>`);
}, string);
document.body.innerHTML += title;

使用正则表达式完成替换

let res = "icebound.com".replace(/u/g, str => {
   
  return "@";
});
console.log(res);

重复生成
下例是根据参数重复生成星号

function star(num = 3) {
   
	return '*'.repeat(num);
}
console.log(star());

下面是模糊后三位电话号码

let phone = "98765432101";
console.log(phone.slice(0, -3) + "*".repeat(3));
类型转换

将字符串转换为数组

console.log("1,2,3".split(",")); //[1,2,3]

隐式类型转换会根据类型自动转换类型

let age = 99 + '';
console.log(typeof age ); //string

使用 String 构造函数可以显示转换字符串类型

let age = 99;
console.log(typeof String(age));

js中大部分类型都是对象,可以使用类方法 toString转化为字符串

let age =</
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值