JavaScript学习(五)

JavaScript 正则表达式

正则表达式是构成搜索模式(search pattern)的字符序列。该搜索模式可用于文本搜索文本替换操作。
例:var patt = /w3school/i;
例子解释:
/w3school/i 是一个正则表达式。
w3school 是模式(pattern)(在搜索中使用)。
i 是修饰符(把搜索修改为大小写不敏感)。

正则表达式常用于两个字符串方法: search() 和 replace()。
search() 方法使用表达式来搜索匹配,然后返回匹配的位置。
replace() 方法返回模式被替换处修改后的字符串。
var str = "Visit W3School"; var n = str.search("W3School");
var str = "Visit W3School"; var n = str.search(/w3school/i);

var str = "Visit Microsoft!"; var res = str.replace("Microsoft", "W3School");
正则表达式修饰符

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

正则表达式模式
括号用于查找一定范围的字符串:
[abc] 查找方括号之间的任何字符。

<button onclick="myFunction()">试一试</button>
<p id="demo"></p>
<script>
function myFunction() {
  var str = "Is this all there is?";
  var patt1 = /[abc]/g; 
  var result = str.match(patt1);
  document.getElementById("demo").innerHTML = result;
}
</script>

[0-9] 查找任何从 0 至 9 的数字。
(x|y) 查找由 | 分隔的任何选项。

<script>
function myFunction() {
  var str = "re, green, red, green, gren, gr, blue, yellow";
  var patt1 = /(red|green)/g;
  var result = str.match(patt1);
  document.getElementById("demo").innerHTML = result;
}
</script>

元字符(Metacharacter)是拥有特殊含义的字符:

元字符描述
\d查找数字。
\s查找空白字符。
\b匹配单词边界。
\uxxxx查找以十六进制数 xxxx 规定的 Unicode 字符。

var patt1 = /\bW3/g;
Quantifiers 定义量词:

量词描述
n+匹配任何包含至少一个 n 的字符串。
n*匹配任何包含零个或多个 n 的字符串。
n?匹配任何包含零个或一个 n 的字符串。

var patt1 = /lo*/g;

使用 RegExp 对象

在 JavaScript 中,RegExp 对象是带有预定义属性和方法的正则表达式对象

test() 是一个正则表达式方法。它通过模式来搜索字符串,然后根据结果返回 true 或 false
var patt = /e/; patt.test("The best things in life are free!");
直接输出:/e/.test("The best things in life are free!");

exec() 方法是一个正则表达式方法。它通过指定的模式(pattern)搜索字符串,并返回已找到的文本。如果未找到匹配,则返回 null。/e/.exec("The best things in life are free!")

JavaScript 错误 - Throw 和 Try to Catch

try 语句能够测试代码块中的错误。
catch 语句可以处理错误。
throw 语句可以创建自定义错误。
finally 能够执行代码,在 try 和 catch 之后,无论结果如何

通过 adddlert 编写警告代码来故意制造了一个错误

<p id="demo"></p>
<script>
try {
    adddlert("欢迎访问!");
}
catch(err) {
    document.getElementById("demo").innerHTML = err.message;
}
</script>

try 语句允许您定义一个代码块,以便在执行时检测错误。

catch 语句允许你定义一个要执行的代码块,如果 try 代码块中发生错误。
JavaScript 语句 try 和 catch 成对出现:

try {
     供测试的代码块
}
 catch(err) {
     处理错误的代码块
} 

实例:

<script>
function myFunction() {
  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;
  }
}
</script>

finally 语句
finally 语句允许您在 try 和 catch 之后执行代码,无论结果:

try {
     // 供测试的代码块
}
 catch(err) {
     // 处理错误的代码块
} 
finally {
     // 无论结果如何都执行的代码块
}

例:

···同上实例
    finally {
        document.getElementById("demo").value = "";
    }

Error 对象
error 对象提供两个有用的属性:name 和 message。

error 的 name 属性可返回六个不同的值:

错误名描述
EvalError(评估错误)已在 eval() 函数中发生的错误
RangeError(范围错误)已发生超出数字范围的错误
ReferenceError(参考/引用错误)已发生非法引用
SyntaxError (语法错误)已发生语法错误
TypeError(类型错误)已发生类型错误
URIError(编码错误)在 encodeURI() 中已发生的错误

更新版本的 JavaScript 不会抛出任何 EvalError。请使用 SyntaxError 代替。

RangeError 会在您使用了合法值的范围之外的数字时抛出。例如:

var num = 1;
try {
    num.toPrecision(500);   // 数无法拥有 500 个有效数
 }
catch(err) {
    document.getElementById("demo").innerHTML = err.name;
} 

假如您使用(引用)了尚未声明的变量,则 ReferenceError 会被抛出:

var x;
try {
    x = y + 1;   // y 无法被引用(使用)
 }
catch(err) {
    document.getElementById("demo").innerHTML = err.name;
} 

假如您计算带语法错误的代码,会 SyntaxError 被抛出:

try {
    eval("alert('Hello)");   // 缺少 ' 会产生错误
}
catch(err) {
     document.getElementById("demo").innerHTML = err.name;
} 

假如您使用的值不在期望值的范围之内,则 TypeError 被抛出:

var num = 1;
try {
    num.toUpperCase();   // 您无法将数字转换为大写
 }
catch(err) {
    document.getElementById("demo").innerHTML = err.name;
} 

假如您在 URI 函数中使用非法字符,则 URIError 被抛出:

try {
    decodeURI("%%%");   // 您无法对这些百分号进行 URI 编码
 }
catch(err) {
    document.getElementById("demo").innerHTML = err.name;
} 

JavaScript 作用域

作用域指的是您有权访问的变量集合

局部 JavaScript 变量

局部变量的作用域是局部的:只能在函数内部访问它们。

// 此处的代码不能使用 carName 变量
function myFunction() {
    var carName = "porsche";
    // 此处的代码能使用 carName 变量
}
全局 JavaScript 变量

全局变量的作用域是全局的:网页的所有脚本和函数都能够访问它。

var carName = " porsche";
// 此处的代码能够使用 carName 变量
function myFunction() {
    // 此处的代码也能够使用 carName 变量
}
自动全局

如果您为尚未声明的变量赋值,此变量会自动成为全局变量。

myFunction();

// 此处的代码能够使用 carName 变量
function myFunction() {
    carName = "porsche";
}

在“严格模式”中不会自动创建全局变量。

HTML 中的全局变量

通过 JavaScript,全局作用域形成了完整的 JavaScript 环境。
在 HTML 中,全局作用域是 window。所有全局变量均属于 window 对象。

var carName = "porsche";

// 此处的代码能够使用 window.carName
document.getElementById("demo").innerHTML = "我可以显示 " + window.carName;

函数参数也是函数内的局部变量

JavaScript Hoisting

提升(Hoisting)是 JavaScript 将声明移至顶部的默认行为

<script>                        
x = 5; // 把 5 赋值给 x          [var x;
                                 //x=5(先声明)]
elem = document.getElementById("demo"); // 查找元素
elem.innerHTML = x;           // 在这个元素中显示 xvar x; // Declare x(后声明)
</script>

JavaScript 只提升声明,而非初始化

var x = 5; // 初始化 x
elem = document.getElementById("demo"); // 查找元素
elem.innerHTML = x + " " + y;           // 显示 x 和 y
var y = 7; // 初始化 y 
//结果:5 undefined

下面例子中的 y 仍然是未定义,这是因为只有声明(var y)而不是初始化(=7)被提升到顶部。

由于 hoisting,y 在其被使用前已经被声明,但是由于未对初始化进行提升,y 的值仍是未定义。
实例

var x = 5; // 初始化 x
var y;     // 声明 y
 
elem = document.getElementById("demo"); // 查找元素
elem.innerHTML = x + " " + y;           // 显示 x 和 y
 
y = 7;    // 把 7 赋值给 y

为了避免 bug,请始终在每个作用域的开头声明所有变量。

JavaScript 严格模式

“use strict”; 定义 JavaScript 代码应该以“严格模式”执行,在严格模式中,无法使用,例如,使用未声明的变量。
"use strict"; x = 3.14; // 这会引发错误,因为 x 尚未声明

"use strict";
myFunction();
function myFunction() {
     y = 3.14;   // 这会引发错误,因为 y 尚未声明
}
x = 3.14;       // 这不会引发错误
myFunction();

function  myFunction() {
	"use strict";
	 y = 3.14;   // 这会引发错误
}
为什么使用严格模式?

严格模式会把之前可接受的“坏语法”转变为真实的错误
在普通 JavaScript 中,如果向不可写属性赋值,开发者不会得到任何错误反馈。
在严格模式中,向不可写的、只能读取的、不存在的属性赋值,或者向不存在的变量或对象赋值,将抛出错误。

严格模式中不允许的事项
  1. 在不声明变量的情况下使用变量,是不允许的:"use strict"; x = 3.14; // 这将引发错误

  2. 对象也是变量在不声明对象的情况下使用对象也是不允许的:"use strict"; x = {p1:10, p2:20}; // 这将引发错误

  3. 删除变量(或对象)是不允许的:"use strict"; var x = 3.14; delete x; // 这将引发错误

  4. 删除函数是不允许的:"use strict"; function x(p1, p2) {}; delete x; // 这将引发错误

  5. 重复参数名是不允许的:"use strict"; function x(p1, p1) {}; // 这将引发错误

  6. 八进制数值文本是不允许的:"use strict"; var x = 010; // 这将引发错误

  7. 转义字符是不允许的:"use strict";var x = \010; // 这将引发错误

  8. 写入只读属性是不允许的:

"use strict";
var obj = {};
Object.defineProperty(obj, "x", {value:0, writable:false});
obj.x = 3.14;            // 这将引发错误
  1. 写入只能获取的属性是不允许的:"use strict"; var obj = {get x() {return 0} }; obj.x = 3.14; // 这将引发错误

  2. 删除不可删除的属性是不允许的:"use strict";delete Object.prototype; // 这将引发错误

  3. 字符串 “eval” 不可用作变量:"use strict"; var eval = 3.14; // 这将引发错误

  4. 字符串 “arguments”(参数) 不可用作变量:"use strict"; var arguments = 3.14; // 这将引发错误

  5. with 语句是不允许的:"use strict";with (Math){x = cos(2)}; // 这将引发错误

  6. 处于安全考虑,不允许 eval() 在其被调用的作用域中创建变量:

"use strict";
eval ("var x = 2");
alert (x);               // 这将引发错误

在类似 f() 的函数调用中,this 的值是全局对象。在严格模式中,现在它成为了 undefined

严格模式中不允许使用为未来预留的关键词。它们是:implements, interface, let, package ,private, protected, public, static, yield,
"例:use strict"; var public = 1500; // 这将引发错误

“use strict” 指令只能在脚本函数的开头被识别

this 关键词

  • 在方法中,this 指的是所有者对象。
  • 单独的情况下,this 指的是全局对象。
  • 在函数中,this 指的是全局对象。
  • 在函数中,严格模式下,this 是 undefined。
  • 在事件中,this 指的是接收事件的元素。
// 创建对象:
var person = {
  firstName: "Bill",
  lastName : "Gates",
  id     : 678,
  fullName : function() {
    return this.firstName + " " + this.lastName;
  }
};
// 显示来自对象的数据:
document.getElementById("demo").innerHTML = person.fullName();
</script>
  • 上面例子中,this 指的是 person 对象。person 对象是 fullName 方法的拥有者。

  • 单独使用时,拥有者是全局对象,因此 this 指的是全局对象。在浏览器窗口中,全局对象是 [object Window]function myFunction() { return this; }
    严格模式中,如果单独使用,那么 this 指的是全局对象 [object Window]

  • HTML 事件处理程序中,this 指的是接收此事件的 HTML 元素<button onclick="this.style.display='none'"> 点击来删除我!</button>

  • 严格模式不允许默认绑定。在严格模式下,this 是未定义的(undefined)。

call()apply() 这样的方法可以将 this 引用到任何对象。

var person1 = {
  fullName: function() {
    return this.firstName + " " + this.lastName;
  }
}
var person2 = {
  firstName:"Bill",
  lastName: "Gates",
}
person1.fullName.call(person2);  // 会返回 "Bill Gates"

当使用 person2 作为参数调用 person1.fullName 时,this 将引用 person2,即使它是 person1 的方法

箭头函数

基础函数写法:var hello; hello = function() { return "Hello World!"; }
箭头函数写法:1. var hello; hello = () => { return "Hello World!"; }
2.hello = () => "Hello World!";
带参数的箭头函数:hello = (val) => "Hello " + val;如果只有一个参数,您也可以略过括号

this 表示调用该函数的对象:

// 常规函数:
hello = function() {
  document.getElementById("demo").innerHTML += this;
}
// window 对象调用该函数:
window.addEventListener("load", hello);
// button 对象调用该函数:
document.getElementById("btn").addEventListener("click", hello);
// 箭头函数:
hello = () => {
  document.getElementById("demo").innerHTML += this;
}
// window 对象调用该函数:
window.addEventListener("load", hello);
// button 对象调用该函数:
document.getElementById("btn").addEventListener("click", hello);

JavaScript 类

JavaScript 类是 JavaScript 对象的模板;(不是对象)
使用关键字 class 创建类。请始终添加名为 constructor() 的方法
语法

class ClassName {
  constructor() { ... }
}

实例

class Car {
  constructor(name, year) {
    this.name = name;
    this.year = year;
  }
使用类
<script>
class Car {
  constructor(name, year) {
    this.name = name;
    this.year = year;
  }
}
const myCar = new Car("Ford", 2014); //const myCar2 = new Car("Ford", 2022);
document.getElementById("demo").innerHTML =
myCar.name + " " + myCar.year;     //myCar2.name + " " + myCar2.year;
</script>

Constructor 方法
构造方法是一种特殊的方法:

  • 它必须拥有确切名称的“构造函数”
  • 创建新对象时自动执行
  • 用于初始化对象属性
  • 如果未定义构造函数方法,JavaScript 会添加空的构造函数方法。
类方法

语法

class ClassName {
  constructor() { ... }
  method_1() { ... }
  method_2() { ... }
  method_3() { ... }
}

创建名为 “age” 的类方法,它返回车龄:

class Car {
  constructor(name, year) {
    this.name = name;
    this.year = year;
  }
  age() {
    let date = new Date();
    return date.getFullYear() - this.year;
  }
}
let myCar = new Car("Ford", 2014);
document.getElementById("demo").innerHTML = "My car is " + myCar.age() + " years old.";

向类方法发送参数:

//(类)同上
  age(x) {
    return x - this.year;
  }
}
let date = new Date();
let year = date.getFullYear();
let myCar = new Car("Ford", 2014);
document.getElementById("demo").innerHTML = "My car is " + myCar.age(year) + " years old.";

JSON(存储和传输数据的格式)

JSON 是存储和传输数据的格式。JSON 经常在数据从服务器发送到网页时使用。

什么是 JSON?

  • JSON 指的是 JavaScript Object Notation
  • JSON 是轻量级的数据交换格式
  • JSON 独立于语言 *
  • JSON 是“自描述的”且易于理解

实例:包含三条员工记录的数组(对象)

{
"employees":[
    {"firstName":"Bill", "lastName":"Gates"}, 
    {"firstName":"Steve", "lastName":"Jobs"},
    {"firstName":"Alan", "lastName":"Turing"}
]
}

JSON 语法规则

  • 数据是名称/值对
  • 数据由逗号分隔
  • 花括号保存对象
  • 方括号保存数组
var text = '{"employees":[' +    //创建包含 JSON 语法的 JavaScript 字符串
'{"firstName":"Bill","lastName":"Gates" },' +
'{"firstName":"Steve","lastName":"Jobs" },' +
'{"firstName":"Elon","lastName":"Musk" }]}';

obj = JSON.parse(text);//使用 JavaScript 的内建函数 JSON.parse() 来把这个字符串转换为 JavaScript 对象
document.getElementById("demo").innerHTML =
obj.employees[1].firstName + " " + obj.employees[1].lastName;
</script>

调试

console.log() 方法

代码中设置断点。
使用F12在浏览器(Chrome、IE、Firefox)中激活调试,然后在调试器菜单中选择“控制台”

<script>
a = 5;
b = 6;
c = a + b;
console.log(c);
</script>
debugger 关键词

debugger 关键词会停止 JavaScript 的执行,并调用(如果有)调试函数。
这与在调试器中设置断点的功能是一样的

此代码会在执行第三行之前停止运行:

var x = 15 * 5;
debugger;
document.getElementbyId("demo").innerHTML = x; 
样式

运算符周围的空格
请始终在运算符( = + - * / )周围以及逗号之后添加空格
代码缩进
请始终使用对代码块缩进使用 4 个空格
语句规则
简单语句的通用规则:请始终以分号结束单条语句

针对复杂语句(compound)的通用规则:

  • 请在第一行的结尾处写开括号
  • 请在开括号前使用一个空格
  • 请在新行上写闭括号,不带前导空格
  • 请不要以分号来结束复杂语句

对象规则
针对对象定义的通用规则:

  • 把开括号与对象名放在同一行
  • 在每个属性与其值之间使用冒号加一个空格
  • 不要在最后一个属性值对后面写逗号
  • 请在新行上写闭括号,不带前导空格
  • 请始终以分号结束对象定义

行长度小于 80
为了提高可读性,请避免每行的长度超过 80 个字符。
命名约定
请始终对您所有的代码使用相同的命名约定。例如:

  • 变量和函数名以驼峰大小写来写
  • 全局变量使用大写(我们不这样做,但是相当普遍)
  • 常量(比如 PI)使用大写

HTML 和 CSS 中的连字符:
HTML5 属性能够以 data- 开头(data-quantity, data-price)。
CSS 在 property-names 中使用连字符(font-size)。
Hyphens 可被错误地视为减法运算符。JavaScript 命名不允许使用连字符。

下划线:
许多程序员喜欢使用下划线(date_of_birth),特别是在 SQL 数据库中。
下划线经常被用在 PHP 参考资料中。

帕斯卡命名法(PascalCase):
C 语言程序员经常使用帕斯卡命名法。

驼峰大小写(camelCase):
JavaScript 本身、jQuery 以及其他 JavaScript 库使用驼峰大小写。

JavaScript 命名请不要以 $ 符号开头。此举会引起 JavaScript 库名称冲突。

在 HTML 中加载 JavaScript
使用简单的语法来加载外部脚本(type 属性不是必需的)<script src="myscript.js"></script>
访问 HTML 元素
使用“不整洁的” HTML 样式的后果,也许是导致 JavaScript 错误var obj = getElementById("Demo") var obj = getElementById("demo")
使用小写文件名
大多数 web 服务器(Apache、Unix)对文件名的大小写敏感:
london.jpg 无法视作 London.jpg 进行访问。
其他 web 服务器(微软的 IIS)对大小写不敏感:
london.jpg 能够以 London.jpg 或 london.jpg 来访问。
如果混合使用大小写,则必须严格保持连续和一致。
如果将站点从大小写不敏感的服务器转移至对大小写敏感的服务器,即使这种小错误也可能破坏您的网站。
为了避免这些问题,请始终使用小写文件名(如果可能)。

常见错误
意外使用赋值运算符

if 语句中意外使用赋值运算符(=)而不是比较运算符(===),JavaScript 程序可能会产生一些无法预料的结果。

期望松散的比较

在常规比较中,数据类型不重要。这条 if 语句返回 truevar x = 10; var y = "10"; if (x == y)
这条 switch 语句会显示提示框:
var x = 10;
switch(x) {
case 10: alert(“Hello”);
}

这条 switch 语句不会显示提示框:
var x = 10;
switch(x) {
case “10”: alert(“Hello”);
}

令人困惑的加法和级联

加法用于加数值。var x = 10 + 5; // x 中的结果是 15 var x = 10 + "5"; // x 中的结果是 "105"

令人误解的浮点

JavaScript 中的数字均保存为 64 位的浮点数(Floats)var x = 0.1; var y = 0.2; var z = x + y // z 中的结果并不是 0.3
var z = (x * 10 + y * 10) / 10; // z 中的结果将是 0.3

对 JavaScript 字符串换行
  • JavaScript 允许您把一条语句换行为两行:
  • 但是,在字符串中间来换行是不对的:
  • 如果必须在字符串中换行,则必须使用反斜杠
错位的分号

因为一个错误的分号,此代码块无论 x 的值如何都会执行:
if (x == 19); { // code block }

对 return 语句进行换行

在一行的结尾自动关闭语句是默认的 JavaScript 行为。
允许一条语句换行为两行
但是不允许return 语句换行为两行,因为它本身就是一条完整的语句

通过命名索引来访问数组

JavaScript 不支持带有命名索引的数组。
在 JavaScript 中,数组使用数字索引

var person = [];
person["firstName"] = "Bill";
person["lastName"] = "Gates";
person["age"] = 46;
var x = person.length;         // person.length 将返回 0
var y = person[0];              // person[0] 将返回 undefined
用逗号来结束定义

对象和数组定义中的尾随逗号在 ECMAScript 5 中是合法的

Internet Explorer 8 会崩溃。
JSON 不允许尾随逗号。

Undefined 不是 Null

JavaScript 对象、变量、属性和方法可以是未定义的。
此外,空的 JavaScript 对象的值可以为 null。
可以通过测试类型是否为 undefined,来测试对象是否存在
但是您无法测试对象是否为 null,因为如果对象未定义,将抛出错误

在测试非 null 之前,必须先测试未定义:
if (typeof myObj !== "undefined" && myObj !== null)

期望块级范围

JavaScript 不会为每个代码块创建新的作用域。很多编程语言都是如此,但是 JavaScript 并非如此。
认为这段代码会返回 undefinedfor (var i = 0; i < 10; i++) { // 代码块 } return i;

性能

减少循环中的活动

差的代码:
var i;
for (i = 0; i < arr.length; i++) {

更好的代码:
var i;
var l = arr.length;
for (i = 0; i < l; i++) {

减少 DOM 访问

假如您期望访问某个 DOM 元素若干次,那么只访问一次,并把它作为本地变量来使用:实例

var obj;
obj = document.getElementById("demo");
obj.innerHTML = "Hello"; 
缩减 DOM 规模
避免不必要的变量
延迟 JavaScript 加载

把脚本放在页面底部,使浏览器首先加载页面。
脚本在下载时,浏览器不会启动任何其他的下载。此外所有解析和渲染活动都可能会被阻塞。
HTTP 规范定义浏览器不应该并行下载超过两种要素。

避免使用 with

请避免使用 with 关键词。它对速度有负面影响。它也将混淆 JavaScript 作用域。
严格模式中不允许 with 关键词。

保留词

在 JavaScript 中,不能把这些保留词作为变量、标记或函数名来使用:

abstractargumentsawait*boolean
breakbytecasecatch
charclass*constcontinue
debuggerdefaultdeletedo
doubleelseenum*eval
export*extends*falsefinal
finallyfloatforfunction
gotoifimplementsimport*
ininstanceofintinterface
let*longnativenew
nullpackageprivateprotected
publicreturnshortstatic
super*switchsynchronizedthis
throwthrowstransienttrue
trytypeofvarvoid
volatilewhilewithyield

用星号标记的关键词是 ECMAScript 5 和 6 中的新词
避免使用 JavaScript 内建对象的名称、属性和方法:

ArrayDateevalfunction
hasOwnPropertyInfinityisFiniteisNaN
isPrototypeOflengthMathNaN
nameNumberObjectprototype
StringtoStringundefinedvalueOf

避免使用 HTML 和 Window 对象和属性的名称:

alertallanchoranchors
areaassignblurbutton
checkboxclearIntervalclearTimeoutclientInformation
closeclosedconfirmconstructor
cryptodecodeURIdecodeURIComponentdefaultStatus
documentelementelementsembed
embedsencodeURIencodeURIComponentescape
eventfileUploadfocusform
formsframeinnerHeightinnerWidth
layerlayerslinklocation
mimeTypesnavigatenavigatorframes
frameRatehiddenhistoryimage
imagesoffscreenBufferingopenopener
optionouterHeightouterWidthpackages
pageXOffsetpageYOffsetparentparseFloat
parseIntpasswordpkcs11plugin
promptpropertyIsEnumradioreset
screenXscreenYscrollsecure
selectselfsetIntervalsetTimeout
statussubmittainttext
textareatopunescapeuntaint
window

避免使用所有 HTML 事件处理程序的名称。
例如:

onbluronclickonerroronfocus
onkeydownonkeypressonkeyuponmouseover
onloadonmouseuponmousedownonsubmit
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值