前端面试题promise、ajax

 1、说说你对作用域链的理解

- 作用域链的作用是保证执行环境里有权访问的变量和函数是有序的,作用域链的变量只能向上访问,变量访问到`window`对象即被终止,作用域链向下访问变量是不被允许的

- 简单的说,作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。

2、JavaScript原型,原型链 ? 有什么特点?

- 每个对象都会在其内部初始化一个属性,就是`__proto__`,当我们访问一个对象的属性时

- 如果这个对象内部不存在这个属性,那么他就会去`__proto__`里找这个属性,这个`__proto__`又会有自己的`__proto__`,于是就这样一直找下去,也就是我们平时所说的原型链的概念。按照标准,`__proto__` 是不对外公开的,也就是说是个私有属性

- 关系:`instance.constructor.prototype == instance.__proto__`

js

var a = {}

a.constructor.prototype == a.__proto__    

- 特点:

  - `JavaScript`对象是通过引用来传递的,我们创建的每个新对象实体中并没有一份属于自己的原型副本。当我们修改原型时,与之相关的对象也会继承这一改变

- 当我们需要一个属性的时,`Javascript`引擎会先看当前对象中是否有这个属性, 如果没有的

- 就会查找他的`Prototype`对象是否有这个属性,如此递推下去,一直检索到 `Object` 内建对象

原型:

  - `JavaScript`的所有对象中都包含了一个 `[__proto__]` 内部属性,这个属性所对应的就是该对象的原型

  - JavaScript的函数对象,除了原型 `[__proto__]` 之外,还预置了 `prototype` 属性

  - 当函数对象作为构造函数创建实例时,该 prototype 属性值将被作为实例对象的原型 `[__proto__]`。

- **原型链:**

  - 当一个对象调用的属性/方法自身不存在时,就会去自己 `[__proto__]` 关联的前辈 `prototype` 对象上去找

  - 如果没找到,就会去该 `prototype` 原型 `[__proto__]` 关联的前辈 `prototype` 去找。依次类推,直到找到属性/方法或 `undefined` 为止。从而形成了所谓的“原型链”

- **原型特点:**

  - `JavaScript`对象是通过引用来传递的,当修改原型时,与之相关的对象也会继承这一改变

3、谈谈This对象的理解

- `this`总是指向函数的直接调用者(而非间接调用者)

- 如果有`new`关键字,`this`指向`new`出来的那个对象

- 在事件中,`this`指向触发这个事件的对象(dom),特殊的是,`IE`中的`attachEvent`中的`this`总是指向全局对象`Window`

4、new操作符具体干了什么呢?

- 创建一个空对象,并且 `this` 变量引用该对象,同时还继承了该函数的原型

- 属性和方法被加入到 `this` 引用的对象中

- 新创建的对象由 `this` 所引用,并且最后隐式的返回 `this`

5、Ajax原理

- `Ajax`的原理简单来说是在用户和服务器之间加了—个中间层(`AJAX`引擎),通过`XmlHttpRequest`对象来向服务器发异步请求,从服务器获得数据,然后用`javascrip`t来操作`DOM`而更新页面。使用户操作与服务器响应异步化。这其中最关键的一步就是从服务器获得请求数据

- `Ajax`的过程只涉及`JavaScript`、`XMLHttpRequest`和`DOM`。`XMLHttpRequest`是`aja`x的核心机制

```javascript

/** 1. 创建连接 **/

var xhr = null;

xhr = new XMLHttpRequest()

/** 2. 连接服务器 **/

xhr.open('get', url, true)

/** 3. 发送请求 **/

xhr.send(null);

/** 4. 接受请求 **/

xhr.onreadystatechange = function(){

  if(xhr.readyState == 4){

    if(xhr.status == 200){

      success(xhr.responseText);

    } else {

      /** false **/

      fail && fail(xhr.status);

    }

  }

}

```

**ajax 有那些优缺点?**

- 优点:

  - 通过异步模式,提升了用户体验.

  - 优化了浏览器和服务器之间的传输,减少不必要的数据往返,减少了带宽占用.

  - `Ajax`在客户端运行,承担了一部分本来由服务器承担的工作,减少了大用户量下的服务器负载。

  - `Ajax`可以实现动态不刷新(局部刷新)

- 缺点:

  - 安全问题 `AJAX`暴露了与服务器交互的细节。

  - 对搜索引擎的支持比较弱。

  - 不容易调试。

6、为什么要有同源限制?

- 同源策略指的是:协议,域名,端口相同,同源策略是一种安全协议

- 举例说明:比如一个黑客程序,他利用`Iframe`把真正的银行登录页面嵌到他的页面上,当你使用真实的用户名,密码登录时,他的页面就可以通过`Javascript`读取到你的表单中`input`中的内容,这样用户名,密码就轻松到手了。

7、javascript有哪些方法定义对象

- 对象字面量: `var obj = {};`

- 构造函数: `var obj = new Object();`

- Object.create(): `var obj = Object.create(Object.prototype);`

8、说说你对promise的了解

- 依照 `Promise/A+` 的定义,`Promise` 有四种状态:

  - `pending:` 初始状态, 非 `fulfilled` 或 `rejected.`

  - `fulfilled:` 成功的操作.

  - `rejected:` 失败的操作.

  - `settled: Promise`已被`fulfilled`或`rejected`,且不是`pending`

- 另外, `fulfilled`与 `rejected`一起合称 `settled`

- `Promise` 对象用来进行延迟(`deferred`) 和异步(`asynchronous`) 计算

**Promise 的构造函数**

- 构造一个 `Promise`,最基本的用法如下:

```javascript

var promise = new Promise(function(resolve, reject) {

        if (...) {  // succeed

            resolve(result);

        } else {   // fails

            reject(Error(errMessage));

        }

    });

```

- `Promise` 实例拥有 `then` 方法(具有 `then` 方法的对象,通常被称为`thenable`)。它的使用方法如下:

```text

promise.then(onFulfilled, onRejected)

```

- 接收两个函数作为参数,一个在 `fulfilled` 的时候被调用,一个在`rejected`的时候被调用,接收参数就是 `future`,`onFulfilled` 对应`resolve`, `onRejected`对应 `reject`

9、 vue、react、angular

- `Vue.js` 一个用于创建 `web` 交互界面的库,是一个精简的 `MVVM`。它通过双向数据绑定把 `View` 层和 `Model` 层连接了起来。实际的 `DOM` 封装和输出格式都被抽象为了`Directives` 和 `Filters`

- `AngularJS` 是一个比较完善的前端`MVVM`框架,包含模板,数据双向绑定,路由,模块化,服务,依赖注入等所有功能,模板功能强大丰富,自带了丰富的 `Angular`指令

- `react` `React` 仅仅是 `VIEW` 层是`facebook`公司。推出的一个用于构建`UI`的一个库,能够实现服务器端的渲染。用了`virtual dom`,所以性能很好。

10、JS的基本数据类型和引用数据类型

- 基本数据类型:`undefined`、`null`、`boolean`、`number`、`string`、`symbol`

- 引用数据类型:`object`、`array`、`function`

11、介绍js有哪些内置对象

- `Object` 是 `JavaScript` 中所有对象的父对象

- 数据封装类对象:`Object`、`Array`、`Boolean`、`Number` 和 `String`

- 其他对象:`Function`、`Arguments`、`Math`、`Date`、`RegExp`、`Error`

12、说几条写JavaScript的基本规范

- 不要在同一行声明多个变量

- 请使用`===/!==`来比较`true/false`或者数值

- 使用对象字面量替代`new Array`这种形式

- 不要使用全局函数

- `Switch`语句必须带有`default`分支

- `If`语句必须使用大括号

- `for-in`循环中的变量 应该使用`var`关键字明确限定作用域,从而避免作用域污染



 

 13、javascript创建对象的几种方式

> `javascript`创建对象简单的说,无非就是使用内置对象或各种自定义对象,当然还可以用`JSON`;但写法有很多种,也能混合使用

- 对象字面量的方式

```javascript

person={firstname:"Mark",lastname:"Yun",age:25,eyecolor:"black"};

```

- 用`function`来模拟无参的构造函数

```javascript

function Person(){}

  var person=new Person();//定义一个function,如果使用new"实例化",该function可以看作是一个Class

        person.name="Mark";

        person.age="25";

        person.work=function(){

        alert(person.name+" hello...");

}

person.work();

```

- 用`function`来模拟参构造函数来实现(用`this`关键字定义构造的上下文属性)

```javascript

function Pet(name,age,hobby){

       this.name=name;//this作用域:当前对象

       this.age=age;

       this.hobby=hobby;

       this.eat=function(){

           alert("我叫"+this.name+",我喜欢"+this.hobby+",是个程序员");

       }

}

var maidou =new Pet("麦兜",25,"coding");//实例化、创建对象

maidou.eat();//调用eat方法

```

- 用工厂方式来创建(内置对象)

javascript

var wcDog =new Object();

     wcDog.name="旺财";

     wcDog.age=3;

     wcDog.work=function(){

       alert("我是"+wcDog.name+",汪汪汪......");

     }

     wcDog.work();

```

- 用原型方式来创建

```javascript

function Dog(){}

Dog.prototype.name="旺财";

Dog.prototype.eat=function(){

  alert(this.name+"是个吃货");

}

var wangcai =new Dog();

wangcai.eat();

```

- 用混合方式来创建

```javascript

 function Car(name,price){

  this.name=name;

  this.price=price;

}

Car.prototype.sell=function(){

  alert("我是"+this.name+",我现在卖"+this.price+"万元");

}

var camry =new Car("凯美瑞",27);

camry.sell();

```

14、null,undefined 的区别

- `undefined` 表示不存在这个值。

- `undefined` :是一个表示"无"的原始值或者说表示"缺少值",就是此处应该有一个值,但是还没有定义。当尝试读取时会返回 `undefined`

- 例如变量被声明了,但没有赋值时,就等于`undefined`

- `null` 表示一个对象被定义了,值为“空值”

- `null` : 是一个对象(空对象, 没有任何属性和方法)

- 例如作为函数的参数,表示该函数的参数不是对象;

- 在验证`null`时,一定要使用 `===` ,因为 `==`无法分别`null` 和 `undefined`

15、javascript 代码中的"use strict";是什么意思

- `use strict`是一种`ECMAscript 5` 添加的(严格)运行模式,这种模式使得 Javascript 在更严格的条件下运行,使`JS`编码更加规范化的模式,消除`Javascript`语法的一些不合理、不严谨之处,减少一些怪异行为

 16、JSON 的了解

- `JSON(JavaScript Object Notation)` 是一种轻量级的数据交换格式

- 它是基于`JavaScript`的一个子集。数据格式简单, 易于读写, 占用带宽小

- `JSON`字符串转换为JSON对象:

```javascript

var obj =eval('('+ str +')');

var obj = str.parseJSON();

var obj = JSON.parse(str);

```

- `JSON`对象转换为JSON字符串:

```text

var last=obj.toJSONString();

var last=JSON.stringify(obj);

```

17、同步和异步的区别

- 同步:浏览器访问服务器请求,用户看得到页面刷新,重新发请求,等请求完,页面刷新,新内容出现,用户看到新内容,进行下一步操作

- 异步:浏览器访问服务器请求,用户正常操作,浏览器后端进行请求。等请求完,页面不刷新,新内容也会出现,用户看到新内容

18、谈谈你对ES6的理解

- 新增模板字符串(为`JavaScript`提供了简单的字符串插值功能)

- 箭头函数

- `for-of`(用来遍历数据—例如数组中的值。)

- `arguments`对象可被不定参数和默认参数完美代替。

- `ES6`将`promise`对象纳入规范,提供了原生的`Promise`对象。

- 增加了`let`和`const`命令,用来声明变量。

- 增加了块级作用域。

- `let`命令实际上就增加了块级作用域。

- 还有就是引入`module`模块的概念



 

19、ECMAScript6 怎么写class么

- 这个语法糖可以让有`OOP`基础的人更快上手`js`,至少是一个官方的实现了

- 但对熟悉`js`的人来说,这个东西没啥大影响;一个`Object.creat()`搞定继承,比`class`简洁清晰的多

20、什么是面向对象编程及面向过程编程,它们的异同和优缺点

- 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了

- 面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为

- 面向对象是以功能来划分问题,而不是步骤

21、面向对象编程思想

- 基本思想是使用对象,类,继承,封装等基本概念来进行程序设计

- 优点

  - 易维护

    - 采用面向对象思想设计的结构,可读性高,由于继承的存在,即使改变需求,那么维护也只是在局部模块,所以维护起来是非常方便和较低成本的

  - 易扩展

  - 开发工作的重用性、继承性高,降低重复工作量。

  - 缩短了开发周期

 22、如何通过JS判断一个数组

- instanceof方法

  - `instanceof` 运算符是用来测试一个对象是否在其原型链原型构造函数的属性

```javascript

var arr = [];

arr instanceof Array; // true

```

- constructor方法

  - `constructor`属性返回对创建此对象的数组函数的引用,就是返回对象相对应的构造函数

```javascript

var arr = [];

arr.constructor == Array; //true

```

- 最简单的方法

  - 这种写法,是 `jQuery` 正在使用的

```javascript

Object.prototype.toString.call(value) == '[object Array]'

// 利用这个方法,可以写一个返回数据类型的方法

var isType = function (obj) {

     return Object.prototype.toString.call(obj).slice(8,-1);

}

```

- `ES5`新增方法`isArray()`

```javascript

var a = new Array(123);

var b = new Date();

console.log(Array.isArray(a)); //true

console.log(Array.isArray(b)); //false

```

 23、谈一谈let与var的区别

- `let`命令不存在变量提升,如果在`let`前使用,会导致报错

- 如果块区中存在`let`和`const`命令,就会形成封闭作用域

- 不允许重复声明,因此,不能在函数内部重新声明参数

  24、map与forEach的区别

- `forEach`方法,是最基本的方法,就是遍历与循环,默认有3个传参:分别是遍历的数组内容`item`、数组索引`index`、和当前遍历数组`Array`

- `map`方法,基本用法与`forEach`一致,但是不同的,它会返回一个新的数组,所以在callback需要有`return`值,如果没有,会返回`undefined`



 

25、谈一谈箭头函数与普通函数的区别?

- 函数体内的`this`对象,就是定义时所在的对象,而不是使用时所在的对象

- 不可以当作构造函数,也就是说,不可以使用`new`命令,否则会抛出一个错误

- 不可以使用`arguments`对象,该对象在函数体内不存在。如果要用,可以用`Rest`参数代替

- 不可以使用`yield`命令,因此箭头函数不能用作`Generator`函数

26、JS 数组和对象的遍历方式,以及几种方式的比较

- `for in`循环

- `for`循环

- `forEach`

  - 这里的 `forEach`回调中两个参数分别为 `value`,`index`

  - `forEach` 无法遍历对象

  - IE不支持该方法;`Firefox` 和 `chrome` 支持

  - `forEach` 无法使用 `break`,`continue` 跳出循环,且使用 `return` 是跳过本次循环

- 这两种方法应该非常常见且使用很频繁。但实际上,这两种方法都存在性能问题

- 在方式一中,`for-in`需要分析出`array`的每个属性,这个操作性能开销很大。用在 `key` 已知的数组上是非常不划算的。所以尽量不要用`for-in`,除非你不清楚要处理哪些属性,例如 `JSON`对象这样的情况

- 在方式2中,循环每进行一次,就要检查一下数组长度。读取属性(数组长度)要比读局部变量慢,尤其是当 `array` 里存放的都是 `DOM` 元素,因为每次读取都会扫描一遍页面上的选择器相关元素,速度会大大降低

27、说一下Vue的双向绑定数据的原理

- `vue.js` 则是采用数据劫持结合发布者-订阅者模式的方式,通过`Object.defineProperty()`来劫持各个属性的`setter`,`getter`,在数据变动时发布消息给订阅者,触发相应的监听回调

28、let var const

**let**

- 允许你声明一个作用域被限制在块级中的变量、语句或者表达式

- let绑定不受变量提升的约束,这意味着let声明不会被提升到当前

- 该变量处于从块开始到初始化处理的“暂存死区”

**var**

- 声明变量的作用域限制在其声明位置的上下文中,而非声明变量总是全局的

- 由于变量声明(以及其他声明)总是在任意代码执行之前处理的,所以在代码中的任意位置声明变量总是等效于在代码开头声明

**const**

- 声明创建一个值的只读引用 (即指针)

- 基本数据当值发生改变时,那么其对应的指针也将发生改变,故造成 `const`申明基本数据类型时

- 再将其值改变时,将会造成报错, 例如 `const a = 3` ; `a = 5`时 将会报错

- 但是如果是复合类型时,如果只改变复合类型的其中某个`Value`项时, 将还是正常使用

 29、JavaScript的组成

- JavaScript由以下三部分组成:

  - `ECMAScript(核心):`JavaScript` 语言基础

  - `DOM`(文档对象模型):规定了访问`HTML`和`XML`的接口

  - `BOM`(浏览器对象模型):提供了浏览器窗口之间进行交互的对象和方法

30、介绍JS有哪些内置对象

- 数据封装类对象:`Object`、`Array`、`Boolean`、`Number`、`String`

- 其他对象:`Function`、`Arguments`、`Math`、`Date`、`RegExp`、`Error`

- ES6新增对象:`Symbol`、`Map`、`Set`、`Promises`、`Proxy`、`Reflect`

 31、说几条写JavaScript的基本规范

- 代码缩进,建议使用“四个空格”缩进

- 代码段使用花括号`{}`包裹

- 语句结束使用分号;

- 变量和函数在使用前进行声明

- 以大写字母开头命名构造函数,全大写命名常量

- 规范定义`JSON`对象,补全双引号

- 用`{}`和`[]`声明对象和数组

32、解释JavaScript中的作用域与变量声明提升

- `JavaScript`作用域:

  - 在`Java`、`C`等语言中,作用域为for语句、`if`语句或`{}`内的一块区域,称为作用域;

  - 而在 `JavaScript` 中,作用域为`function(){}`内的区域,称为函数作用域。

- `JavaScript`变量声明提升:

  - 在`JavaScript`中,函数声明与变量声明经常被`JavaScript`引擎隐式地提升到当前作用域的顶部。

  - 声明语句中的赋值部分并不会被提升,只有名称被提升

  - 函数声明的优先级高于变量,如果变量名跟函数名相同且未赋值,则函数声明会覆盖变量声明

  - 如果函数有多个同名参数,那么最后一个参数(即使没有定义)会覆盖前面的同名参数

33、列举一下JavaScript数组和对象有哪些原生方法?

**数组:**

- `arr.concat(arr1, arr2, arrn);`

- `arr.join(",");`

- `arr.sort(func);`

- `arr.pop();`

- `arr.push(e1, e2, en);`

- `arr.shift();`

- `unshift(e1, e2, en);`

- `arr.reverse();`

- `arr.slice(start, end);`

- `arr.splice(index, count, e1, e2, en);`

- `arr.indexOf(el);`

- `arr.includes(el);` // ES6

**对象:**

- `object.hasOwnProperty(prop);`

- `object.propertyIsEnumerable(prop);`

- `object.valueOf();`

- `object.toString();`

- `object.toLocaleString();`

- `Class.prototype.isPropertyOf(object);`

34、Array.slice() 与 Array.splice() 的区别?

**`slice`**

> “读取”数组指定的元素,不会对原数组进行修改

- 语法:`arr.slice(start, end)`

- `start` 指定选取开始位置(含)

- `end` 指定选取结束位置(不含)

**splice**

- “操作”数组指定的元素,会修改原数组,返回被删除的元素

- 语法:`arr.splice(index, count, [insert Elements])`

- `index` 是操作的起始位置

- `count = 0` 插入元素,`count > 0` 删除元素

- `[insert Elements]` 向数组新插入的元素

 35、MVVM

**MVVM 由以下三个内容组成**

- `View`:界面

- `Model`:数据模型

- `ViewModel`:作为桥梁负责沟通 `View` 和 `Model`



 

36、this指向

**1、this 指向有哪几种**

- 默认绑定:全局环境中,`this`默认绑定到`window`

- 隐式绑定:一般地,被直接对象所包含的函数调用时,也称为方法调用,`this`隐式绑定到该直接对象

- 隐式丢失:隐式丢失是指被隐式绑定的函数丢失绑定对象,从而默认绑定到`window`。显式绑定:通过`call()`、`apply()`、`bind()`方法把对象绑定到`this`上,叫做显式绑定

- new绑定:如果函数或者方法调用之前带有关键字new,它就构成构造函数调用。对于this绑定来说,称为new绑定

  - 构造函数通常不使用`return`关键字,它们通常初始化新对象,当构造函数的函数体执行完毕时,它会显式返回。在这种情况下,构造函数调用表达式的计算结果就是这个新对象的值

  - 如果构造函数使用`return`语句但没有指定返回值,或者返回一个原始值,那么这时将忽略返回值,同时使用这个新对象作为调用结果

  - 如果构造函数显式地使用`return`语句返回一个对象,那么调用表达式的值就是这个对象

**2. 改变函数内部 this 指针的指向函数(bind,apply,call的区别)**

- `apply`:调用一个对象的一个方法,用另一个对象替换当前对象。例如:`B.apply(A, arguments)`;即A对象应用B对象的方法

- `call`:调用一个对象的一个方法,用另一个对象替换当前对象。例如:`B.call(A, args1,args2)`;即A对象调用B对象的方法

- `bind`除了返回是函数以外,它的参数和`call`一样

**3. 箭头函数**

- 箭头函数没有`this`,`this`绑定的就是最近一层非箭头函数的`this`,

- 箭头函数没有自己的`arguments`对象,但是可以访问外围函数的`arguments`对象

- 不能通过`new`关键字调用,同样也没有`new.target`值和原型

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Promise是JavaScript中的一种异步编程解决方案。它有三种状态:pending(初始状态)、fulfilled(实现状态)和rejected(失败状态)。在面试中,可能会问到与Promise相关的问题,例如如何创建一个Promise对象、如何处理Promise的异常等。下面是一个关于Promise的示例代码: ```javascript // 创建一个Promise对象 const promise = new Promise((resolve, reject) => { // 异步操作,例如发送网络请求或读取文件 // 如果操作成功,调用resolve函数传递结果 // 如果操作失败,调用reject函数传递错误信息 // resolve('success'); reject(new Error('error!!!')); }); // 处理Promise对象的结果 promise .then(result => { console.log(result); }) .catch(error => { console.error(error); }); ``` 在上面的代码中,我们创建了一个Promise对象,并在构造函数中执行了一个异步操作。如果操作成功,我们调用resolve函数传递操作的结果;如果操作失败,我们调用reject函数传递错误信息。然后,我们使用.then方法处理Promise对象的结果,如果操作成功,我们打印结果;如果操作失败,我们使用.catch方法捕获错误并打印错误信息。 希望以上回答对您有所帮助。如果您有任何其他问题,请随时提问。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [端面试 | 必知必会的10道Promise题](https://blog.csdn.net/IT_studied/article/details/124758936)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [端面试题Promise](https://blog.csdn.net/weixin_49014702/article/details/122938017)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值