前端学习3——JS

前端学习3——JS

0、JS注释

// 单行注释
/*
多行注释
*/

1、组成部分

  • BOM
  • DOM
  • ECMAScript

2、接入方式

  • 行内式
<a href="javascript:;">我们不一样</a>
  • 内联式
<script>
alert("我的第一个 JavaScript");
</script>
  • 外联式
<script src="myScript.js"></script>

3、输出

  • 使用 window.alert() 写入警告框
<script>
window.alert(5 + 6);
</script>
  • 使用 document.write() 写入 HTML 输出
<script>
document.write(5 + 6);
</script>
  • 使用 console.log() 写入浏览器控制台
<script>
console.log(5 + 6);
</script>

4、变量

变量定义(ES6中常量使用const,变量使用let,var尽量不要用

var x = 7;
var y = 8;
var z = x + y; 
var person = "Bill Gates", carName = "porsche", price = 15000;
var person = "Bill Gates",
carName = "porsche",
price = 15000;
// 不带有值的变量,它的值将是 undefined
var carName;

变量规则

  • 名称可包含字母、数字、下划线和美元符号
  • 名称必须以字母开头
  • 名称也可以 $_ 开头(但是在本教程中我们不会这么做)
  • 名称对大小写敏感(y 和 Y 是不同的变量)
  • 保留字(比如 JavaScript 的关键词)无法用作变量名称

5、运算符

加法运算符(+)加数

var x = 7;
var y = 8;
var z = x + y; 

减法运算符(-)减数

var x = 7;
var y = 8;
var z = x - y; 

乘法运算符(*)乘数

var x = 7;
var y = 8;
var z = x * y; 

除法运算符(/)除数

var x = 7;
var y = 2;
var z = x / y; 

系数运算符(%)返回除法的余数

var x = 7;
var y = 2;
var z = x % y; 

递增运算符(++)对数值进行递增

var x = 7;
x++;
var z = x;

递减运算符(–)对数值进行递减

var x = 7;
x--;
var z = x; 

取幂运算符(**)将第一个操作数提升到第二个操作数的幂

var x = 5;
var z = x ** 2;          // 结果是 25
var x = 5;
var z = Math.pow(x,2);   // 结果是 25

运算符优先级:https://www.w3school.com.cn/js/js_arithmetic.asp

6、数据类型

5 种不同的可以包含值的数据类型:

  • string
  • number
  • boolean
  • object
  • function

6 种类型的对象

  • Object
  • Date
  • Array
  • String
  • Number
  • Boolean

2 种不能包含值的数据类型

  • null
  • undefine
typeof "Bill"                 // 返回 "string"
typeof 3.14                   // 返回 "number"
typeof NaN                    // 返回 "number"
typeof false                  // 返回 "boolean"
typeof [1,2,3,4]              // 返回 "object"
typeof {name:'Bill', age:19}  // 返回 "object"
typeof new Date()             // 返回 "object"
typeof function () {}         // 返回 "function"
typeof myCar                  // 返回 "undefined" *
typeof null                   // 返回 "object"

1、字符串

var carName = "Porsche 911";   // 使用双引号
var carName = 'Porsche 911';   // 使用单引号
var answer = "It's alright";             // 双引号内的单引号
var answer = "He is called 'Bill'";    // 双引号内的单引号
var answer = 'He is called "Bill"';    // 单引号内的双引号

2、数值

var x1 = 34.00;     // 带小数点
var x2 = 34;        // 不带小数点

3、布尔

var x = true;
var y = false;

4、数组

var cars = ["Porsche", "Volvo", "BMW"];

5、对象

var person = {firstName:"Bill", lastName:"Gates", age:62, eyeColor:"blue"};

6、typeof

typeof ""                  // 返回 "string"
typeof "Bill"              // 返回 "string"
typeof "Bill Gates"          // 返回 "string"
typeof 0                   // 返回 "number"
typeof 314                 // 返回 "number"
typeof 3.14                // 返回 "number"
typeof (7)                 // 返回 "number"
typeof (7 + 8)             // 返回 "number"
var person;                  // 值是 undefined,类型是 undefined。
typeof undefined              // undefined
typeof null                   // object
null === undefined            // false
null == undefined             // true
typeof {name:'Bill', age:62} // 返回 "object"
typeof [1,2,3,4]             // 返回 "object" typeof 运算符把数组返回为 "object",因为在 JavaScript 中数组即对象
typeof null                  // 返回 "object"
typeof function myFunc(){}   // 返回 "function"

7、函数

格式(注意函数本事是一种引用数据类型

function name(参数 1, 参数 2, 参数 3) {
    要执行的代码
}

调用方式

  • 当事件发生时(当用户点击按钮时)
  • 当 JavaScript 代码调用时
  • 自动的(自调用)

普通函数

function myFunction(a, b) {
     return a * b;
}

匿名函数

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

自调用函数

(function () {
    var x = "Hello!!";      // 我会调用我自己
})();

函数参数

function myFunction(a, b) {
    return arguments.length;
}

8、对象

对象属性

var car = {type:"porsche", model:"911", color:"white"};

对象方法

var person = {
  firstName: "Bill",
  lastName : "Gates",
  id       : 678,
  fullName : function() {
    return this.firstName + " " + this.lastName;
  }
};

9、事件

事件

事件描述
abort媒体加载中止时发生该事件。
afterprint当页面开始打印时,或者关闭打印对话框时,发生此事件。
animationendCSS 动画完成时发生此事件。
animationiteration重复 CSS 动画时发生此事件。
animationstartCSS 动画开始时发生此事件。
beforeprint即将打印页面时发生此事件。
beforeunload在文档即将被卸载之前发生此事件。
blur当元素失去焦点时发生此事件。
canplay当浏览器可以开始播放媒体时,发生此事件。
canplaythrough当浏览器可以在不停止缓冲的情况下播放媒体时发生此事件。
change当form元素的内容、选择的内容或选中的状态发生改变时,发生此事件
click当用户单击元素时发生此事件。
contextmenu当用户右键单击某个元素以打开上下文菜单时,发生此事件。
copy当用户复制元素的内容时发生此事件。
cut当用户剪切元素的内容时发生此事件。
dblclick当用户双击元素时发生此事件。
drag拖动元素时发生此事件。
dragend当用户完成拖动元素后,发生此事件。
dragenter当拖动的元素进入放置目标时,发生此事件。
dragleave当拖动的元素离开放置目标时,发生此事件。
dragover当拖动的元素位于放置目标之上时,发生此事件。
dragstart当用户开始拖动元素时发生此事件。
drop当将拖动的元素放置在放置目标上时,发生此事件。
durationchange媒体时长改变时发生此事件。
ended在媒体播放到尽头时发生此事件。
error当加载外部文件时发生错误后,发生此事件。
focus在元素获得焦点时发生此事件。
focusin在元素即将获得焦点时发生此事件。
focusout在元素即将失去焦点时发生此事件。
fullscreenchange当元素以全屏模式显示时,发生此事件。
fullscreenerror当元素无法在全屏模式下显示时,发生此事件。
hashchange当 URL 的锚部分发生改变时,发生此事件。
input当元素获得用户输入时,发生此事件。
invalid当元素无效时,发生此事件。
keydown当用户正在按下键时,发生此事件。
keypress当用户按下键时,发生此事件。
keyup当用户松开键时,发生此事件。
load在对象已加载时,发生此事件。
loadeddata媒体数据加载后,发生此事件。
loadedmetadata加载元数据(比如尺寸和持续时间)时,发生此事件。
loadstart当浏览器开始查找指定的媒体时,发生此事件。
message在通过此事件源接收消息时,发生此事件。
mousedown当用户在元素上按下鼠标按钮时,发生此事件。
mouseenter当指针移动到元素上时,发生此事件。
mouseleave当指针从元素上移出时,发生此事件。
mousemove当指针在元素上方移动时,发生此事件。
mouseout当用户将鼠标指针移出元素或其中的子元素时,发生此事件。
mouseover当指针移动到元素或其中的子元素上时,发生此事件。
mouseup当用户在元素上释放鼠标按钮时,发生此事件。
mousewheel不推荐使用。请改用 wheel事件。
offline当浏览器开始脱机工作时,发生此事件。
online当浏览器开始在线工作时,发生此事件。
open当打开与事件源的连接时,发生此事件。
pagehide当用户离开某张网页进行导航时,发生此事件。
pageshow在用户导航到某张网页时,发生此事件。
paste当用户将一些内容粘贴到元素中时,发生此事件。
pause当媒体被用户暂停或以编程方式暂停时,发生此事件。
play当媒体已启动或不再暂停时,发生此事件。
playing在媒体被暂停或停止以缓冲后播放时,发生此事件。
popstate窗口的历史记录改变时,发生此事件。
progress当浏览器正处于获得媒体数据的过程中时,发生此事件。
ratechange媒体播放速度改变时发生此事件。
reset重置表单时发生此事件。
resize调整文档视图的大小时发生此事件。
scroll滚动元素的滚动条时发生此事件。
search当用户在搜索字段中输入内容时,发生此事件。
seeked当用户完成移动/跳到媒体中的新位置时,发生该事件。
seeking当用户开始移动/跳到媒体中的新位置时,发生该事件。
select用户选择文本后(对于和)发生此事件
show 元素显示为上下文菜单时,发生此事件。
stalled当浏览器尝试获取媒体数据但数据不可用时,发生此事件。
storageWeb 存储区域更新时发生此事件。
submit在提交表单时发生此事件。
suspend当浏览器有意不获取媒体数据时,发生此事件。
timeupdate当播放位置更改时发生此事件。
toggle当用户打开或关闭 元素时,发生此事件。
touchcancel在触摸被中断时,发生此事件。
touchend当手指从触摸屏上移开时,发生此事件。
touchmove当手指在屏幕上拖动时,发生此事件。
touchstart当手指放在触摸屏上时,发生此事件。
transitionendCSS 转换完成时,发生此事件。
unload页面卸载后(对于 ),发生此事件。
volumechange当媒体的音量已更改时,发生此事件。
waiting当媒体已暂停但预期会恢复时,发生此事件。
wheel当鼠标滚轮在元素向上或向下滚动时,发生此事件。

事件属性

属性/方法描述
altKey返回触发鼠标事件时是否按下了 “ALT” 键。
altKey返回触发按键事件时是否按下了 “ALT” 键。
animationName返回动画的名称。
bubbles返回特定事件是否为冒泡事件。
button返回触发鼠标事件时按下的鼠标按钮。
buttons返回触发鼠标事件时按下的鼠标按钮。
cancelBubble设置或返回事件是否应该向上层级进行传播。
cancelable返回事件是否可以阻止其默认操作。
changeTouches返回在上一触摸与该触摸之间其状态已更改的所有触摸对象的列表
charCode返回触发 onkeypress 事件的键的 Unicode 字符代码。
clientX返回触发鼠标事件时,鼠标指针相对于当前窗口的水平坐标。
clientY返回触发鼠标事件时,鼠标指针相对于当前窗口的垂直坐标。
clipboardData返回对象,其中包含受剪贴板操作影响的数据。
code返回触发事件的键的代码。
composed指示该事件是否可以从 Shadow DOM 传递到一般的 DOM。
composedPath()返回事件的路径。
createEvent()创建新事件。
ctrlKey返回触发鼠标事件时是否按下了 “CTRL” 键。
ctrlKey返回按键鼠标事件时是否按下了 “CTRL” 键。
currentTarget返回其事件侦听器触发事件的元素。
data返回插入的字符。
dataTransfer返回一个对象,其中包含被拖放或插入/删除的数据。
defaultPrevented返回是否为事件调用 preventDefault() 方法。
deltaX返回鼠标滚轮的水平滚动量(x 轴)。
deltaY返回鼠标滚轮的垂直滚动量(y 轴)。
deltaZ返回鼠标滚轮的 Z 轴滚动量。
deltaMode返回数字,代表增量值(像素、线或页面)的度量单位。
detail返回数字,指示鼠标被单击了多少次。
elapsedTime返回动画已运行的秒数。
elapsedTime返回过渡已运行的秒数。
eventPhase返回当前正在评估事件流处于哪个阶段。
getModifierState()返回包含目标范围的数组,此范围将受到插入/删除的影响。
getTargetRanges()返回包含目标范围的数组,此范围将受到插入/删除的影响。
inputType返回更改的类型(即 “inserting” 或 “deleting”)。
isComposing返回事件的状态是否正在构成。
isTrusted返回事件是否受信任。
key返回事件表示的键的键值。
key返回更改后的存储项的键。
keyCode返回触发 onkeypress、onkeydown 或 onkeyup 事件的键的 Unicode 字符代码。
location返回键盘或设备上按键的位置。
lengthComputable返回进度的长度是否可计算。
loaded返回已加载的工作量。
metaKey返回事件触发时是否按下了 “META” 键。
metaKey返回按键事件触发时是否按下了 “META” 键。
MovementX返回相对于上一 mousemove 事件的位置的鼠标指针的水平坐标
MovementY返回相对于上一 mousemove 事件的位置的鼠标指针的垂直坐标
newURL返回更改 hash 后的文档 URL。
newValue返回更改后的存储项目的新值。
offsetX返回鼠标指针相对于目标元素边缘位置的水平坐标。
offsetY返回鼠标指针相对于目标元素边缘位置的垂直坐标。
oldURL返回更改 hash 前的文档 URL。
oldValue返回更改后的存储项目的旧值。
onemptied当发生不良情况且媒体文件突然不可用时,发生此事件。
pageX返回触发鼠标事件时鼠标指针相对于文档的水平坐标。
pageY返回触发鼠标事件时鼠标指针相对于文档的垂直坐标。
persisted返回网页是否被浏览器缓存。
preventDefault()如果可以取消事件,则将其取消,不执行属于该事件的默认操作。
propertyName返回与动画或过渡相关联的 CSS 属性的名称。
pseudoElement返回动画或过渡的伪元素的名称。
region
relatedTarget返回与触发鼠标事件的元素相关的元素。
relatedTarget返回与触发事件的元素相关的元素。
repeat返回是否重复按住某个键。
screenX返回窗口/鼠标指针相对于屏幕的水平坐标。
screenY返回窗口/鼠标指针相对于屏幕的垂直坐标。
shiftKey返回事件触发时是否按下了 “SHIFT” 键。
shiftKey返回按键事件触发时是否按下了 “SHIFT” 键。
state返回包含历史记录条目副本的对象。
stopImme…()防止同一事件的其他侦听器被调用。
stopPropagation()防止事件在事件流中进一步传播。
storageArea返回代表受影响的存储对象的对象。
target返回触发事件的元素。
targetTouches返回包含仍与触摸面接触的所有触摸点的Touch对象的TouchList列表
timeStamp返回创建事件的时间(相对于纪元的毫秒数)。
total返回将要加载的工作总量。
touches返回当前与表面接触的所有 touch 对象的列表。
type返回事件名称。
url返回已更改项目的所在文档的 URL。
which返回触发鼠标事件时按下的鼠标按钮。
which返回触发 onkeypress 事件的键的 Unicode 字符码,或触发 onkeydown 或 onkeyup 事件的键的 Unicode 键码
view返回对发生事件的 Window 对象的引用。

10、字符串

1、基本

转义字符

代码结果描述
单引号
""双引号
\\反斜杠

字符串可以作为对象

var x = "Bill";
var y = new String("Bill");

// typeof x 将返回 string
// typeof y 将返回 object

2、字符串模板

通过使用模板字面量,可以在字符串中同时使用单引号和双引号

let text = `He's often called "Johnny"`;

字符串插值(string interpolation)

let firstName = "Bill";
let lastName = "Gates";
let text = `Welcome ${firstName}, ${lastName}!`;
let price = 10;
let VAT = 0.25;
let total = `Total: ${(price * (1 + VAT)}`;

3、属性

length属性返回字符串的长度

var txt = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var sln = txt.length;

字符串的字符

var str = "HELLO WORLD";
str[0];                   // 返回 H

4、方法

查找字符串中的字符串

indexOf() 方法返回字符串中指定文本首次出现的索引(位置)

参数:目标字符串,检索开始索引

返回:如果未找到文本, 返回 -1,否则为第一次匹配的索引

var str = "The full name of China is the People's Republic of China.";
var pos = str.indexOf("China");

// 17

lastIndexOf() 方法返回指定文本在字符串中最后一次出现的索引,

参数:目标字符串,检索开始索引

返回:如果未找到文本, 返回 -1,否则为第一次匹配的索引

var str = "The full name of China is the People's Republic of China.";
var pos = str.lastIndexOf("China");

// 51

search() 方法搜索特定值的字符串,并返回匹配的位置

var str = "The full name of China is the People's Republic of China.";
var pos = str.search("locate");

// -1

match() 方法根据正则表达式在字符串中搜索匹配项,并将匹配项作为 Array 对象返回

let text = "The rain in SPAIN stays mainly in the plain";
text.match(/ain/g)    // 返回数组 [ain,ain,ain]

includes() 判断字符串是否包含指定值

let text = "Hello world, welcome to the universe.";
text.includes("world")    // 返回 true

startsWith() 判断字符串是否以指定值开头

let text = "Hello world, welcome to the universe.";
text.startsWith("Hello")   // 返回 true

endsWith() 判断字符串是否以指定值开头

var text = "Bill Gates";
text.endsWith("Gates")    // 返回 true

提取部分字符串

slice() 提取字符串的某个部分并返回被提取的部分

参数:起始索引,终止索引(如果某个参数为负,则从字符串的结尾开始计数)

var str = "Apple, Banana, Mango";
var res = str.slice(7,13);

// Banana
var str = "Apple, Banana, Mango";
var res = str.slice(-13,-7);

// Banana
var str = "Apple, Banana, Mango";
var res = str.slice(-13) 

// Banana, Mango

substring()提取字符串的某个部分并返回被提取的部分,不接受参数为负

参数:起始索引,终止索引

var str = "Apple, Banana, Mango";
var res = str.substr(7,6);

// Banana

substr()提取字符串的某个部分并返回被提取的部分

参数:起始索引,提取长度

var str = "Apple, Banana, Mango";
var res = str.substr(7,6);

// Banana
var str = "Apple, Banana, Mango";
var res = str.substr(-5);

// Mango

替换字符串内容

replace() 方法用另一个值替换在字符串中指定的值,返回的是新字符串,默认只替换第一个

str = "Please visit Microsoft!";
var n = str.replace("Microsoft", "W3School");

忽略大小写匹配

str = "Please visit Microsoft!";
var n = str.replace(/MICROSOFT/i, "W3School");

替换所有

str = "Please visit Microsoft and Microsoft!";
var n = str.replace(/Microsoft/g, "W3School");

大小写转换

toUpperCase() 把字符串转换为大写

var text1 = "Hello World!";       // 字符串
var text2 = text1.toUpperCase();  // text2 是被转换为大写的 text1

toLowerCase() 把字符串转换为小写

var text1 = "Hello World!";       // 字符串
var text2 = text1.toLowerCase();  // text2 是被转换为小写的 text1

字符串连接

其实与+连接相同

var text1 = "Hello";
var text2 = "World";
text3 = text1.concat(" ",text2);

字符串处理

trim() 方法删除字符串两端的空白符

var str = "       Hello World!        ";
alert(str.trim());

提取字符串字符

charAt() 方法返回字符串中指定下标(位置)的字符串

var str = "HELLO WORLD";
str.charAt(0);            // 返回 H

charCodeAt() 方法返回字符串中指定索引的字符 unicode 编码

var str = "HELLO WORLD";
str.charCodeAt(0);         // 返回 72

把字符串转换为数组

split() 将字符串转换为数组

var txt = "a,b,c,d,e";   // 字符串
txt.split(",");          // 用逗号分隔

11、数值

1、基本

JavaScript 数值始终是 64 位的浮点数

2、方法

类型转换

toString() 返回数值的字符串形式

var x = 123;
x.toString();            // 从变量 x 返回 123
(123).toString();        // 从文本 123 返回 123
(100 + 23).toString();   // 从表达式 100 + 23 返回 123

Number() 可用于把 JavaScript 变量转换为数值

x = true;
Number(x);        // 返回 1
x = false;     
Number(x);        // 返回 0
x = new Date();
Number(x);        // 返回 1404568027739
x = "10"
Number(x);        // 返回 10
x = "10 20"
Number(x);        // 返回 NaN

parseInt() 解析一段字符串并返回整数型数值,允许空格,只返回首个数字

parseInt("10");         // 返回 10
parseInt("10.33");      // 返回 10
parseInt("10 20 30");   // 返回 10
parseInt("10 years");   // 返回 10
parseInt("years 10");   // 返回 NaN

parseFloat() 解析一段字符串并返回数值,允许空格,只返回首个数字

parseFloat("10");        // 返回 10
parseFloat("10.33");     // 返回 10.33
parseFloat("10 20 30");  // 返回 10
parseFloat("10 years");  // 返回 10
parseFloat("years 10");  // 返回 NaN

格式处理

toExponential() 返回已被四舍五入并使用指数计数法的数字的字符串值

var x = 9.656;
x.toExponential(2);     // 返回 9.66e+0
x.toExponential(4);     // 返回 9.6560e+0
x.toExponential(6);     // 返回 9.656000e+0

toFixed() 返回包含了指定位数小数的数字的字符串值

var x = 9.656;
x.toFixed(0);           // 返回 10
x.toFixed(2);           // 返回 9.66
x.toFixed(4);           // 返回 9.6560
x.toFixed(6);           // 返回 9.656000

toPrecision() 返回字符串值,它包含了指定长度的数字

var x = 9.656;
x.toPrecision();        // 返回 9.656
x.toPrecision(2);       // 返回 9.7
x.toPrecision(4);       // 返回 9.656
x.toPrecision(6);       // 返回 9.65600

valueOf() 以数值返回数值(将 Number 对象转换为数值)

var x = 123;
x.valueOf();            // 从变量 x 返回 123
(123).valueOf();        // 从文本 123 返回 123
(100 + 23).valueOf();   // 从表达式 100 + 23 返回 123

12、数组

1、基本

var cars = ["Saab", "Volvo", "BMW"];

var cars = [
    "Saab",
    "Volvo",
    "BMW"
];

var cars = new Array("Saab", "Volvo", "BMW");
cars[0] = "Opel";

2、属性

length 属性返回数组的长度(数组元素的数目)

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.length;                       // fruits 的长度是 4

3、方法

数组输出

toString() 把数组转换为数组值(逗号分隔)的字符串

返回:以逗号分割的字符串

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.toString();

// Banana,Orange,Apple,Mango

join() 方法也可将所有数组元素结合为一个字符串

参数:数组值的分隔符

返回:以指定分割符的数组字符串

var fruits = ["Banana", "Orange","Apple", "Mango"];
fruits.join(" * "); 

// Banana * Orange * Apple * Mango

数组增删

pop() 方法从数组中删除最后一个元素

返回:“被弹出”的值

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.pop();              // 从 fruits 删除最后一个元素("Mango")

push() 方法(在数组结尾处)向数组添加一个新的元素

参数:要添加的值

返回:新数组的长度

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.push("Kiwi");       //  向 fruits 添加一个新元素

shift() 方法会删除首个数组元素(直接移除,不是变为undefined

返回:被“位移出”的字符串

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.shift();            // 从 fruits 删除第一个元素 "Banana"

unshift() 方法(在开头)向数组添加新元素,并“反向位移”旧元素

参数:要添加的值

返回:新数组的长度

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.unshift("Lemon");    // 返回 5

利用length添加元素

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits[fruits.length] = "Kiwi";          // 向 fruits 追加 "Kiwi"

数组元素更改

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits[0] = "Kiwi";        // 把 fruits 的第一个元素改为 "Kiwi"

数组元素删除

var fruits = ["Banana", "Orange", "Apple", "Mango"];
delete fruits[0];           // 把 fruits 中的首个元素改为 undefined

数组拼接/裁剪

splice() 方法可用于向数组添加新项

参数:拼接新元素的位置,应删除多少元素,要添加的新元素

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.splice(2, 0, "Lemon", "Kiwi");

concat() 方法通过合并(连接)现有数组来创建一个新数组

参数:要拼接的数组(可以使用任意数量的数组参数

var myGirls = ["Cecilie", "Lone"];
var myBoys = ["Emil", "Tobias", "Linus"];
var myChildren = myGirls.concat(myBoys);   // 连接 myGirls 和 myBoys

slice() 方法用数组的某个片段切出新数组

参数:开始元素,结束元素(如果没有默认数组长度

var fruits = ["Banana", "Orange", "Lemon", "Apple", "Mango"];
var citrus = fruits.slice(1, 3); 

// Orange,Lemon,Apple,Mango

数组排序

sort() 方法以字母顺序对数组进行排序

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.sort();            // 对 fruits 中的元素进行排序

reverse() 方法反转数组中的元素

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.sort();            // 对 fruits 中的元素进行排序
fruits.reverse();         // 反转元素顺序

自定义排序

参数:排序函数(非必须

var points = [40, 100, 1, 5, 25, 10];
points.sort(function(a, b){return a - b}); 

数组遍历

forEach() 方法为每个数组元素调用一次函数(回调函数)

回调函数参数:项目值,项目索引,数组本身

var txt = "";
var numbers = [45, 4, 9, 16, 25];
numbers.forEach(myFunction);

function myFunction(value, index, array) {
  txt = txt + value
}

Array.map() 通过对每个数组元素执行函数来创建新数组

参数:回调函数

回调函数参数:项目值,项目索引,数组本身

var numbers1 = [45, 4, 9, 16, 25];
var numbers2 = numbers1.map(myFunction);

function myFunction(value, index, array) {
  return value * 2;
}

Array.filter() 方法创建一个包含通过测试的数组元素的新数组

参数:回调函数

回调函数参数:项目值,项目索引,数组本身

var numbers = [45, 4, 9, 16, 25];
var over18 = numbers.filter(myFunction);

function myFunction(value, index, array) {
  return value > 18;
}

Array.reduce()方法在每个数组元素上运行函数,以生成(减少它)单个值

参数:回调函数,初始值(total,非必需

回调函数参数:总数(初始值/先前返回的值),项目值,项目索引,数组本身

var numbers1 = [45, 4, 9, 16, 25];
var sum = numbers1.reduce(myFunction);

function myFunction(total, value, index, array) {
  return total + value;
}

Array.reduceRight()方法在每个数组元素上运行函数,以生成(减少它)单个值(从右到左)

参数:回调函数,初始值(total,非必需

回调函数参数:总数(初始值/先前返回的值),项目值,项目索引,数组本身

var numbers1 = [45, 4, 9, 16, 25];
var sum = numbers1.reduceRight(myFunction);

function myFunction(total, value, index, array) {
  return total + value;
}

Array.every()方法检查所有数组值是否通过测试

参数:回调函数

回调函数参数:项目值,项目索引,数组本身

var numbers = [45, 4, 9, 16, 25];
var allOver18 = numbers.every(myFunction);

function myFunction(value, index, array) {
  return value > 18;
}

Array.some()方法检查某些数组值是否通过了测试

参数:回调函数

回调函数参数:项目值,项目索引,数组本身

var numbers = [45, 4, 9, 16, 25];
var someOver18 = numbers.some(myFunction);

function myFunction(value, index, array) {
  return value > 18;
}

数组索引

Array.indexOf() 方法在数组中搜索元素值并返回其位置

var fruits = ["Apple", "Orange", "Apple", "Mango"];
var a = fruits.indexOf("Apple");

Array.lastIndexOf() 方法在数组中搜索元素值并返回其位置(从右到左)

var fruits = ["Apple", "Orange", "Apple", "Mango"];
var a = fruits.lastIndexOf("Apple");

数组搜索

Array.find() 方法返回通过测试函数的第一个数组元素的值

参数:回调函数

回调函数参数:项目值,项目索引,数组本身

var numbers = [4, 9, 16, 25, 29];
var first = numbers.find(myFunction);

function myFunction(value, index, array) {
  return value > 18;
}

Array.findIndex() 方法返回通过测试函数的第一个数组元素的索引

参数:回调函数

回调函数参数:项目值,项目索引,数组本身

var numbers = [4, 9, 16, 25, 29];
var first = numbers.findIndex(myFunction);

function myFunction(value, index, array) {
  return value > 18;
}

13、日期

GMT(格林威治标准时间)

CST(中国标准时间)

1、基本

  • new Date()
  • new Date(year, month, day, hours, minutes, seconds, milliseconds)
  • new Date(milliseconds)
  • new Date(date string)
var d = new Date();
var d = new Date(2018, 11, 24, 10, 33, 30, 0);

// Tue Apr 02 2019 09:01:19 GMT+0800 (中国标准时间)

2、日期格式

类型实例
ISO 日期“2018-02-19” (国际标准)
短日期“02/19/2018” 或者 “2018/02/19”
长日期“Feb 19 2018” 或者 “19 Feb 2019”
完整日期“Monday February 25 2015”

3、日期获取/设置

方法描述
getDate()以数值返回天(1-31)
getDay()以数值获取周名(0-6)
getFullYear()获取四位的年(yyyy)
getHours()获取小时(0-23)
getMilliseconds()获取毫秒(0-999)
getMinutes()获取分(0-59)
getMonth()获取月(0-11)
getSeconds()获取秒(0-59)
getTime()获取时间(从 1970 年 1 月 1 日至今,时间戳格式)
方法描述
setDate()以数值(1-31)设置日
setFullYear()设置年(可选月和日)
setHours()设置小时(0-23)
setMilliseconds()设置毫秒(0-999)
setMinutes()设置分(0-59)
setMonth()设置月(0-11)
setSeconds()设置秒(0-59)
setTime()设置时间(从 1970 年 1 月 1 日至今的毫秒数)

14、数字

1、属性

Math.E          // 返回欧拉指数(Euler's number)
Math.PI         // 返回圆周率(PI)
Math.SQRT2      // 返回 2 的平方根
Math.SQRT1_2    // 返回 1/2 的平方根
Math.LN2        // 返回 2 的自然对数
Math.LN10       // 返回 10 的自然对数
Math.LOG2E      // 返回以 2 为底的 e 的对数(约等于 1.414)
Math.LOG10E     // 返回以 10 为底的 e 的对数(约等于 0.434)

2、方法

Math.round(x) 的返回值是 x 四舍五入为最接近的整数

Math.round(6.8);    // 返回 7
Math.round(2.3);    // 返回 2

Math.pow(x, y) 的返回值是 x 的 y 次幂

Math.pow(8, 2);      // 返回 64

Math.sqrt(x) 返回 x 的平方根

Math.sqrt(64);      // 返回 8

Math.abs(x) 返回 x 的绝对(正)值

Math.abs(-4.7);     // 返回 4.7

Math.ceil(x) 的返回值是 x 上舍入最接近的整数

Math.ceil(6.4);     // 返回 7

Math.floor(x) 的返回值是 x 下舍入最接近的整数

Math.floor(2.7);    // 返回 2

Math.sin(x) 返回角 x(以弧度计)的正弦(介于 -1 与 1 之间的值)

Math.sin(90 * Math.PI / 180);     // 返回 1(90 度的正弦)

Math.cos(x) 返回角 x(以弧度计)的余弦(介于 -1 与 1 之间的值)

Math.cos(0 * Math.PI / 180);     // 返回 1(0 度的余弦)

Math.min() 和 Math.max() 可用于查找参数列表中的最低或最高值

Math.min(0, 450, 35, 10, -8, -300, -78);  // 返回 -300
Math.max(0, 450, 35, 10, -8, -300, -78);  // 返回 450

Math.random() 返回介于 0(包括) 与 1(不包括) 之间的随机数

Math.random();     // 返回随机数

15、条件语句

If-else

if (条件) {
    条件为 true 时执行的代码块
} else { 
    条件为 false 时执行的代码块
}
if (条件 1) {
    条件 1true 时执行的代码块
} else if (条件 2) {
    条件 1false 而条件 2true 时执行的代码块
 } else {
    条件 1 和条件 2 同时为 false 时执行的代码块
}

switch

switch(表达式) {
     case n:
        代码块
        break;
     case n:
        代码块
        break;
     default:
        默认代码块
} 

16、循环

fori(遍历数组

for (i = 0; i < cars.length; i++) { 
    text += cars[i];
}

forin(遍历对象,map,数组

for (key in object) {
  // code block to be executed
}

forof

const cars = ["BMW", "Volvo", "Mini"];

let text = "";
for (let x of cars) {
  text += x;
}
let language = "JavaScript";

let text = "";
for (let x of language) {
	text += x;
}

while

while (i < 10) {
    text += "数字是 " + i;
    i++;
}

do-while

do {
    text += "The number is " + i;
    i++;
 }
while (i < 10);

17、异常

try {
    adddlert("欢迎访问!");
}
catch(err) {
    document.getElementById("demo").innerHTML = err.message;
}

error对象

属性描述
name设置或返回错误名
message设置或返回错误消息(一条字符串)

error.name

错误名描述
EvalError已在 eval() 函数中发生的错误
RangeError已发生超出数字范围的错误
ReferenceError已发生非法引用
SyntaxError已发生语法错误
TypeError已发生类型错误
URIError在 encodeURI() 中已发生的错误
var message, x;
message = document.getElementById("p01");
message.innerHTML = "";
x = document.getElementById("demo").value;
try { 
  if(x == "")  throw "是空的";
  if(isNaN(x)) throw "不是数字";
  x = Number(x);
  if(x < 5)  throw "太小";
  if(x > 10)   throw "太大";
}
catch(err) {
  message.innerHTML = "输入:" + err;
}
try {
     // 供测试的代码块
}
 catch(err) {
     // 处理错误的代码块
} 
finally {
     // 无论结果如何都执行的代码块
}

18、map

属性

PropertyDescription
size获取 Map 对象中某键的值。

方法

MethodDescription
new Map()创建新的 Map 对象。
set()为 Map 对象中的键设置值。
get()获取 Map 对象中键的值。
entries()返回 Map 对象中键/值对的数组。
keys()返回 Map 对象中键的数组。
values()返回 Map 对象中值的数组。
clear()删除 Map 中的所有元素。
delete()删除由键指定的元素。
has()如果键存在,则返回 true。
forEach()为每个键/值对调用回调。

19、set

属性

PropertyDescription
size获取 Map 对象中某键的值。

方法

MethodDescription
new Set()创建新的 Set 对象。
add()向 Set 添加新元素。
clear()从 Set 中删除所有元素。
delete()删除由其值指定的元素。
entries()返回 Set 对象中值的数组。
has()如果值存在则返回 true。
forEach()为每个元素调用回调。
keys()返回 Set 对象中值的数组。
values()与 keys() 相同。

20、函数进阶

1、改变this指向

call

var person = {
    fullName: function() {
        return this.firstName + " " + this.lastName;
    }
}
var person1 = {
    firstName:"Bill",
    lastName: "Gates",
}
var person2 = {
    firstName:"Steve",
    lastName: "Jobs",
}
person.fullName.call(person1);  // 将返回 "Bill Gates"
var person = {
  fullName: function(city, country) {
    return this.firstName + " " + this.lastName + "," + city + "," + country;
  }
}
var person1 = {
  firstName:"Bill",
  lastName: "Gates"
}
person.fullName.call(person1, "Seattle", "USA");

bind

var person = {
    fullName: function() {
        return this.firstName + " " + this.lastName;
    }
}
var person1 = {
    firstName:"Bill",
    lastName: "Gates",
}
var person2 = {
    firstName:"Steve",
    lastName: "Jobs",
}
person.fullName.bind(person1)();  // 将返回 "Bill Gates"
var person = {
  fullName: function(city, country) {
    return this.firstName + " " + this.lastName + "," + city + "," + country;
  }
}
var person1 = {
  firstName:"Bill",
  lastName: "Gates"
}
person.fullName.bind(person1, "Seattle", "USA")();

apply

var person = {
    fullName: function() {
        return this.firstName + " " + this.lastName;
    }
}
var person1 = {
    firstName: "Bill",
    lastName: "Gates",
}
person.fullName.apply(person1);  // 将返回 "Bill Gates"
var person = {
  fullName: function(city, country) {
    return this.firstName + " " + this.lastName + "," + city + "," + country;
  }
}
var person1 = {
  firstName:"Bill",
  lastName: "Gates"
}
person.fullName.apply(person1, ["Oslo", "Norway"]);

2、闭包

在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。

function a() {
    var i = '初始值';
    i = i + "—_执行a"
    // 此处的函数b访问了父级函数a中的局部变量i,成为了一个闭包
    function b() {
        i = i + "_执行b"
        console.log(i)
    }
    return b;
}
var c = a(); // 此时 i 的值为 :初始值—_执行a
c()          // 此时 i 的值为 :初始值—_执行a_执行b
c()          // 此时 i 的值为 :初始值—_执行a_执行b_执行b
var a = "global variable";
var F = function () {
  var b = "local variable";
  var N = function () {
    var c = "inner local";
    return b;
  };
 return N;
};
var d = F()
d()

目前还没看出除了模块化还有什么作用,,,

3、回调

function myDisplayer(some) {
  document.getElementById("demo").innerHTML = some;
}

function myCalculator(num1, num2, myCallback) {
  let sum = num1 + num2;
  myCallback(sum);
}

myCalculator(5, 5, myDisplayer);

4、promise

1、promise状态/结果
Promise.statePromise.result
Pending(进行中)undefined(工作时)
resolved/Fulfilled(已完成)结果值
Rejected(已失败)error 对象
2、基本语法
const promise = new Promise(function(resolve, reject) {
  // … some code

  If (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});

promise.then(function(value) {
  // success
}, function(error) {
  // failure
});
3、Promise 新建后就会立即执行
let promise = new Promise(function(resolve, reject) {
  console.log('1');
  resolve();
});

promise.then(function() {
  console.log('2');
});

console.log('3');
4、调用resolve或reject并不会终结 Promise 的参数函数的执行
new Promise((resolve, reject) => {
  resolve(1);
  console.log(2);
}).then(r => {
  console.log(r);
});
// 2
// 1
5、一般不要在then方法里面定义 Reject 状态的回调函数(即then的第二个参数),应当使用catch方法
// bad
promise
  .then(function(data) {
    // success
  }, function(err) {
    // error
  });

// good
promise
  .then(function(data) { //cb
    // success
  })
  .catch(function(err) {
    // error
  });
6、Promise 对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止
function doSomething(){
    return new Promise((resolve, reject)=>{
        console.log("dosomething");
        resolve("lianxing")
    });
}
function doSomethingS(res){
    return new Promise((resolve, reject)=>{
        console.log("dosomethingS");
        reject(res)
    });
}
function doSomethingSS(res){
    return new Promise((resolve, reject)=>{
        console.log("dosomethingSS");
        resolve(res)
    });
}
function failureCallback(err) {
    console.log("Got the final err result "+err);
}
doSomething().then(function(result) {
    return doSomethingS(result);
})
    .then(function(newResult) {
        return doSomethingSS(newResult);
    })
    .then(function(finalResult) {
        console.log('Got the final result: ' + finalResult);
    })
    .catch(failureCallback);
7、finally
promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});
8、状态传递

p1的状态决定了p2的状态,如果p1的状态是pending,那么p2的回调函数就会等待p1的状态改变;如果p1的状态已经是resolved或者rejected,那么p2的回调函数将会立刻执行

const p1 = new Promise(function (resolve, reject) {
  // …
});

const p2 = new Promise(function (resolve, reject) {
  // …
  resolve(p1);
})
9、Promise.all

Promise.all()方法接受一个数组作为参数

参数对象里所有的promise对象都成功的时候才会触发成功,一旦有任何一个iterable里面的promise对象失败则立即触发该promise对象的失败

P的状态由p1、p2、p3决定

  • 只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数
  • 只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数
const p1 = new Promise((resolve, reject) => {
  resolve('hello');
})

const p2 = new Promise((resolve, reject) => {
  throw new Error('报错了');
})

const p=Promise.all([p1, p2])
.then(result => console.log(result))
.catch(e => console.log(e));
const p1 = new Promise((resolve, reject) => {
    resolve('hello');
})

const p2 = new Promise((resolve, reject) => {
    resolve('world');
})

const p3 = new Promise((resolve, reject) => {
    resolve('!!!');
})

Promise.all([p1, p2, p3])
    .then(result => console.log(result))
    .catch(e => console.log(e));

如果作为参数的 Promise 实例,自己定义了catch方法,那么它一旦被rejected,并不会触发Promise.all()的catch方法,并且此实例执行完成catch后状态也会转变为resolved

const p1 = new Promise((resolve, reject) => {
    resolve('hello');
})

const p2 = new Promise((resolve, reject) => {
    resolve('world');
})

const p3 = new Promise((resolve, reject) => {
    throw new Error('报错了');
}).catch((err)=>{
    console.log(err);
})

Promise.all([p1, p2, p3])
    .then(result => console.log(result))
    .catch(e => console.log(e));
10、Promise.race

Promise.race()方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例

当iterable参数里的任意一个子promise被成功或失败后,父promise马上也会用子promise的成功返回值或失败详情作为参数调用父promise绑定的相应句柄,并返回该promise对象

const p1 = new Promise((resolve, reject) => {
        setTimeout(()=>{
            resolve("我是一号");
        },1000)
    })

    const p2 = new Promise((resolve, reject) => {
        setTimeout(()=>{
            resolve("我是二号");
        },5000)
    })

    const p3 = new Promise((resolve, reject) => {
        setTimeout(()=>{
            resolve("我是三号");
        },8000)
    })

    Promise.race([p1, p2, p3, new Promise((resolve, reject) => {
        setTimeout(()=>{
            reject("timeout")
        },100)
    })])
        .then(result => console.log(result))
        .catch(e => console.log(e));
11、Promise.resolve

参数是一个 Promise 实例

Promise.resolve将不做任何修改、原封不动地返回这个实例

参数是一个thenable对象(具有then方法的对象)

Promise.resolve方法会将这个对象转为 Promise 对象,然后就立即执行thenable对象的then方法

Promise.resolve('foo')
// 等价于
new Promise(resolve => resolve('foo'))
let thenable = {
  then: function(resolve, reject) {
    resolve(42);
  }
};

let p1 = Promise.resolve(thenable);
p1.then(function(value) {
  console.log(value);  // 42
});

参数不是具有then方法的对象,或根本就不是对象

const p = Promise.resolve('Hello');

p.then(function (s){
  console.log(s)
});

不带有任何参数

const p = Promise.resolve();

p.then(function () {
  // ...
});

立即resolve()的 Promise 对象,是在本轮“事件循环”(event loop)的结束时执行,而不是在下一轮“事件循环”的开始时

setTimeout(function () {
  console.log('3');
}, 0);

Promise.resolve().then(function () {
  console.log('2');
});

console.log('1');

// 1
// 2
// 3
12、Promise.reject
const p = Promise.reject('出错了');
// 等同于
const p = new Promise((resolve, reject) => reject('出错了'))

p.then(null, function (s) {
  console.log(s)
});
// 出错了

Promise.reject()方法的参数,会原封不动地作为reject的理由,变成后续方法的参数

const thenable = {
  then(resolve, reject) {
    reject('出错了');
  }
};

Promise.reject(thenable)
.catch(e => {
  console.log(e === thenable)
})
// true

5、闭包

实现闭包最常见的方式就是函数嵌套(并不是形成闭包的唯一方式!)

function a() {
    var i = '初始值';
    i = i + "—_执行a"
    // 此处的函数b访问了父级函数a中的局部变量i,成为了一个闭包
    function b() {
        i = i + "_执行b"
        console.log(i)
    }
    return b;
}
var c = a(); // 此时 i 的值为 :初始值—_执行a
c()          // 此时 i 的值为 :初始值—_执行a_执行b
c()          // 此时 i 的值为 :初始值—_执行a_执行b_执行b

函数a虽然已执行完,但因为内部包含闭包函数b,所以函数 a 的执行期上下文会继续保留在内存中,不会被销毁,所以局部变量 i 仍是初始值—_执行a

1、特点
  • 被闭包函数访问的父级及以上的函数的局部变量(如范例中的局部变量 i )会一直存在于内存中,不会被JS的垃圾回收机制回收
  • 闭包函数实现了对其他函数内部变量的访问
2、优点
  • 能够读取函数内部的变量
  • 可以减少全局变量的定义,避免全局变量的污染
  • 在内存中维护一个变量,可以用做缓存

21、Async/await

async 用于申明一个 function 是异步的,await(async wait) 用于等待一个异步方法执行完成

async其实是promise的语法糖(下面两个其实是等同的

async function myFunction() {
  return "Hello";
}
async function myFunction() {
  return Promise.resolve("Hello");
}

promise语法与async语法对比

myFunction().then(
  function(value) { /* 成功时的代码 */ },
  function(error) { /* 出错时的代码 */ }
);
async function myFunction() {
  return "Hello";
}
myFunction().then(
  function(value) {myDisplayer(value);},
  function(error) {myDisplayer(error);}
);

Async/await极大的简化了promise

function takeLongTime(n) {
  return new Promise(resolve => {
  	setTimeout(() => resolve(n + 200), n);
  });ß
}

function step1(n) {
	console.log(`step1 with ${n}`);
	return takeLongTime(n);
}

function step2(n) {
	console.log(`step2 with ${n}`);
	return takeLongTime(n);
}

function step3(n) {
	console.log(`step3 with ${n}`);
	return takeLongTime(n);
}
function doIt() {
console.time("doIt");
const time1 = 300;
step1(time1)
.then(time2 => step2(time2))
.then(time3 => step3(time3))
.then(result => {
	console.log(`result is ${result}`);
	console.timeEnd("doIt");
});
}

doIt();
async function doIt() {
  console.time("doIt");
  const time1 = 300;
  const time2 = await step1(time1);
  const time3 = await step2(time2);
  const result = await step3(time3);
  console.log(`result is ${result}`);
  console.timeEnd("doIt");
}

doIt();

此时差距不大,但是如果下一次结果依赖前面所有的结果

function step1(n) {
	console.log(`step1 with ${n}`);
	return takeLongTime(n);
}

function step2(m, n) {
	console.log(`step2 with ${m} and ${n}`);
	return takeLongTime(m + n);
}

function step3(k, m, n) {
	console.log(`step3 with ${k}, ${m} and ${n}`);
	return takeLongTime(k + m + n);
}
async function doIt() {
  console.time("doIt");
  const time1 = 300;
  const time2 = await step1(time1);
  const time3 = await step2(time1, time2);
  const result = await step3(time1, time2, time3);
  console.log(`result is ${result}`);
  console.timeEnd("doIt");
}

doIt();
// Promise.resolve返回一个解析过的Promise对象!!!
function doIt() {
  console.time("doIt");
  const time1 = 300;
  step1(time1)
  .then(time2 => {
    return step2(time1, time2).then(time3 => [time1, time2, time3]);
  })
  .then(times => {
    const [time1, time2, time3] = times;
    return step3(time1, time2, time3);
  })
  .then(result => {
    console.log(`result is ${result}`);
    console.timeEnd("doIt");
  });
}

doIt();

22、JSON

JavaScript Object Notation(JavaScript 对象标记法)

{"employees":[
    { "firstName":"Bill", "lastName":"Gates" },
    { "firstName":"Steve", "lastName":"Jobs" },
    { "firstName":"Elon", "lastName":"Musk" }
]}

JSON.parse() 用来解析json数据

JSON.stringify() 用来把 JavaScript 对象转换为字符串

23、DOM

在这里插入图片描述

24、BOM

25、WEB API

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

眼眸流转

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

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

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

打赏作者

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

抵扣说明:

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

余额充值