js基础知识(第一篇)

整理的比较乱凑合看吧

JavaScript概念

JavaScript是基于对象和事件驱动,并具有安全性能的客户端脚本语言,弱类型的语言。
解释执行 (编译-》代码转为0和1)
由三部分组成:
ECMAScript(核心)
DOM(文档对象模型)document object model
BOM(浏览器对象模型)browser object model

1.在HTML标签中直接写入JS代码(用的少)

点击
2.在HTML文档中写入代码 4.注释 // /**/

变量的声明和定义
var a = 10;
var是关键字, a是变量名, =是赋值符号 10是值
变量的命名规则
变量是由数字、字母、下划线(_)和美元符号($)的一种或者几种组成,且不能以数字开头,严格区分大小写。
(驼峰法则,见名知义)
JavaScript数据类型: 数值、字符串、布尔、undefined、null、对象

通过typeof关键字,对这5种数据类型会返回下面的值(以字符串形式显示)
undefined ---------- 如果值未定义 Undefined
boolean ---------- 如果这个值是布尔值 Boolean
string ---------- 如果这个值是字串符 String
number ---------- 如果这个值是数值类型 Number
object ---------- 如果这个值是对象或null Object
null被认为是一个空的对象引用。

两个表格的加减乘除:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
	</head>
	<body>
		
			<input type="text" value="" id="ipt">
			<input type="text" value="" id="ipt02">
			<input type="button" value="计算" id="ipt03">
			<script>
		
			ipt03.onclick=function(){
				
				var ipt=document.getElementById('ipt')
				var num=parseInt(ipt.value)
				var ipt02=document.getElementById('ipt02')
				var num1=parseInt(ipt02.value)
				console.log(num+num1)
				console.log(num-num1)
				console.log(num*num1)
				console.log(num/num1)
				}		
	             </script>
	</body>
</html>

js基本结构

&&与 and 同真则真 有一假则假
|| 或 or 同假则假 有一真则真
! 取反

1 if…else 结构
if代码块后面,还可以跟一个else代码块,表示不满足条件时,所要执行的代码。
if (m == 3) {
// 满足条件时,执行的语句
} else {
// 不满足条件时,执行的语句
}
上面代码判断变量m是否等于3,如果等于就执行if代码块,否则执行else代码块。

2 对同一个变量进行多次判断时,多个if…else语句可以连写在一起

if (m == 0) {
  // ...
} else if (m == 1) {
  // ...
} else if (m == 2) {
  // ...
} else {
  // ...
}
if (m > 90) {
  // ...A
} else if (m<80&&m>70) {
  // ...B
} else if (m<70&&m>60) {
  // ...C
} else {
  // ...D

BOM DOM 定时器和延时器

BOM的概念
提供了独立于页面内容而与浏览器进行交互的对象,其核心对象是window
在浏览器中,window对象(注意,w为小写)指当前的浏览器窗口。它也是所有对象的顶层对象。
“顶层对象”指的是最高一层的对象,所有其他对象都是它的下属。JavaScript规定,浏览器环境的所有全局变量,都是window对象的属性。
var a = 1;
window.a // 1
上面代码中,变量a是一个全局变量,但是实质上它是window对象的属性。声明一个全局变量,就是为window对象的同名属性赋值

浏览器代理检测,可以检测出来用户使用的浏览器类型,也可以检测浏览器所在的操作系统
navigator.userAgent
判断浏览器类型

var t = navigator.userAgent;
			if(t.indexOf('Trident')!= -1){
				console.log('ie内核')
			}else if(t.indexOf('Presto')!= -1){
				console.log('欧朋')
			}else if(t.indexOf('Chrome')!= -1){
				console.log('chrome ')
			}else if(t.indexOf('Safari')!= -1){
				console.log('Safari ')
			}else{
				console.log('其他')
			}

判断是移动端还是PC(重要)
//移动端

var ua = navigator.userAgent.toLowerCase();

			if (ua.indexOf('mobi') !=-1) {
			  // 手机浏览器
			  console.log('手机')
			} else {
			  // 非手机浏览器
			  console.log('非手机')
			}

判断是移动端还是PC(重要)
//移动端

var ua = navigator.userAgent.toLowerCase();
		if (ua.indexOf('mobi') !=-1) {
		  // 手机浏览器
		  console.log('手机')
			if(ua.indexOf('android') !=-1){
				console.log('移动端 安卓')
			}else if(ua.indexOf('ipod') !=-1
    || ua.indexOf('iphone') !=-1 
    || ua.indexOf('ipad') !=-1)
			{
				console.log('移动端  苹果手机')
			}
		} else {
		  // 非手机浏览器
		  console.log('非手机')
		}

location对象
location对象包含有关当前 URL 的信息。
location对象是 Window 对象的一个部分,可通过 window.location 属性来访问。

属性:hash、host、hostname、href、pathname、port、protocol、search
href:设置或返回完整的 URL。(常用)
hash:设置或返回从井号 (#) 开始的 URL(锚)。
search:设置或返回从问号 (?) 开始的 URL(查询部分)。(常用)

host 设置或返回主机名和当前 URL 的端口号。
hostname 设置或返回当前 URL 的主机名。
pathname 设置或返回当前 URL 的路径部分。
port 设置或返回当前 URL 的端口号。
protocol 设置或返回当前 URL 的协议。

location对象
方法:assign(url), replace(url) , reload()
assign() 加载新的文档。
reload() 重新加载当前文档。
replace() 用新的文档替换当前文档

window.open();
打开一个新的浏览器窗口。

window.close();
关闭浏览器窗口。

alert(arg1)
显示带有一段消息和一个确认按钮的警告框。

prompt(arg1,arg2)
显示可提示用户输入的对话框

confirm(arg1) (偶尔)
显示带有一段消息以及确认按钮和取消按钮的对话框。

history对象:
history对象保存着用户上网的历史记录,从窗口被 打开的那一刻算起.
后退一页 history.go(-1) history.back()
前进一页 history.go(1) history.forward()
前进两页 history.go(2)

window.onload
load事件发生在文档在浏览器窗口加载完毕时。window.onload属性可以指定这个事件的回调函数。
window.onload = function() {
console.log(‘页面加载完毕’)
};

定时器和延时器
JavaScript 提供定时执行代码的功能,叫做定时器(timer),主要由setTimeout()和setInterval()这两个函数来完成。
延时器
setTimeout函数用来指定某个函数或某段代码,在多少毫秒之后执行。它返回一个整数,表示定时器的编号,以后可以用来取消这个定时器。

var timerId = setTimeout(func, delay);

上面代码中,setTimeout函数接受两个参数,第一个参数func是将要推迟执行的函数名,第二个参数delay是推迟执行的毫秒数。

console.log(1);
		//推迟执行
		setTimeout(function(){
			console.log(2)
		},1000);
		console.log(3);

定时器
setInterval(func,time)
有两个参数,第一个参数是一个函数,第二个参数是时间间隔,单位是毫秒
每间隔time毫秒,会执行一次函数
setInterval的返回值是一个数字

function box(){
	console.log(1)
}
var timer = setInerval(box,1000);

上面代码意思是,没间隔1000毫秒,box函数执行一次。
取消定时器的执行
如果想要取消定时器的执行我们需要拿到setInerval定时器函数的返回值,调用clearInterval,清除定时器
clearInterval(timer),调用之后box函数就不会再执行了!

switch结构

switch (fruit) {
  case "banana":
    // ...
    break;
  case "apple":
    // ...
    break;
  default:
    // ...
}

上面代码根据变量fruit的值,选择执行相应的case。如果所有case都不符合,则执行最后的default部分。需要注意的是,每个case代码块内部的break语句不能少,否则会接下去执行下一个case代码块,而不是跳出switch结构。

有些时候我们可以利用穿透效果简单代码

switch (month) {
  case 2:
    console.log('28或者29天')break;
  case  1:
  case 3:
  case 5:
    console.log('31天');
    break;
  default:
    console.log('30天');
}

字符串(string)

replace方法用于替换匹配的子字符串,一般情况下只替换第一个匹配(除非使用带有g修饰符的正则表达式)。
‘aaa’.replace(‘a’, ‘b’) // “baa”
‘aaa’.replace(/a/g, ‘b’) // “bbb”
字符串的创建方式

var s1 = 'abc';
var s2 = new String('abc');
typeof s1 // "string"
typeof s2 // "object"

上面代码中,变量s1是字符串,s2是对象。
所以,String对象也叫包装对象
除了用作构造函数,String对象还可以当作工具方法使用,将任意类型的值转为字符串。
String(true) // “true”
String(5) // “5”
上面代码将布尔值ture和数值5,分别转换为字符串

字符串实例的length属性返回字符串的长度。
‘abc’.length // 3
字符串对象是一个类似数组的对象(很像数组,但不是数组)。

new String('abc')
// String {0: "a", 1: "b", 2: "c", length: 3}
(new String('abc'))[1] // "b"

上面代码中,字符串abc对应的字符串对象,有数值键(0、1、2)和length属性,所以可以像数组那样取值。
charAt方法返回指定位置的字符,参数是从0开始编号的位置。

var s = new String('abc');
s.charAt(1) // "b"
s.charAt(s.length - 1) // "c"

这个方法完全可以用数组下标替代。

'abc'.charAt(1) // "b"
'abc'[1] // "b"

slice方法用于从原字符串取出子字符串并返回,不改变原字符串。它的第一个参数是子字符串的开始位置,
第二个参数是子字符串的结束位置(不含该位置)。
‘JavaScript’.slice(0, 4) // “Java”

如果省略第二个参数,则表示子字符串一直到原字符串结束。
‘JavaScript’.slice(4) // “Script”

如果参数是负值,表示从结尾开始倒数计算的位置,即该负值加上字符串长度。

'JavaScript'.slice(-6) // "Script"
'JavaScript'.slice(0, -6) // "Java"
'JavaScript'.slice(-2, -1) // "p"

如果第一个参数大于第二个参数,slice方法返回一个空字符串。
‘JavaScript’.slice(2, 1) //

substring方法用于从原字符串取出子字符串并返回,不改变原字符串,跟slice方法很相像。它的第一个参数表示子字符串的开始位置,第二个位置表示结束位置(返回结果不含该位置)。
‘JavaScript’.substring(0, 4) // “Java”

如果省略第二个参数,则表示子字符串一直到原字符串的结束。
‘JavaScript’.substring(4) // “Script”

如果第二个参数大于第一个参数,substring方法会自动更换两个参数的位置。
‘JavaScript’.substring(10, 4) // “Script”
// 等同于
‘JavaScript’.substring(4, 10) // “Script”

substr方法用于从原字符串取出子字符串并返回,不改变原字符串,跟slice和substring方法的作用相同。

substr方法的第一个参数是子字符串的开始位置(从0开始计算),第二个参数是子字符串的长度。
‘JavaScript’.substr(4, 6) // “Script”

如果省略第二个参数,则表示子字符串一直到原字符串的结束。
‘JavaScript’.substr(4) // “Script”

如果第一个参数是负数,表示倒数计算的字符位置。如果第二个参数是负数,将被自动转为0,因此会返回空字符串。
‘JavaScript’.substr(-6) // “Script”
‘JavaScript’.substr(4, -1) // “”
上面代码中,第二个例子的参数-1自动转为0,表示子字符串长度为0,所以返回空字符串

indexOf方法用于确定一个字符串在另一个字符串中第一次出现的位置,返回结果是匹配开始的位置。
如果返回-1,就表示不匹配。
‘hello world’.indexOf(‘o’) // 4
‘JavaScript’.indexOf(‘script’) // -1

indexOf方法还可以接受第二个参数,表示从该位置开始向后匹配。
‘hello world’.indexOf(‘o’, 6) // 7

lastIndexOf方法的用法跟indexOf方法一致,主要的区别是lastIndexOf从尾部开始匹配,indexOf则是从头部开始匹配。
‘hello world’.lastIndexOf(‘o’) // 7

另外,lastIndexOf的第二个参数表示从该位置起向前匹配
‘hello world’.lastIndexOf(‘o’, 6) // 4

trim方法用于去除字符串两端的空格,返回一个新字符串,不改变原字符串。
’ hello world '.trim()
// “hello world”

该方法去除的不仅是空格,还包括制表符(\t、\v)、换行符(\n)和回车符(\r)。
‘\r\nabc \t’.trim() // ‘abc’

toLowerCase方法用于将一个字符串全部转为小写,toUpperCase则是全部转为大写。它们都返回一个新字符串,不改变原字符串。

‘Hello World’.toLowerCase()
// “hello world”

‘Hello World’.toUpperCase()
// “HELLO WORLD”

split方法按照给定规则分割字符串,返回一个由分割出来的子字符串组成的数组。
‘a|b|c’.split(’|’) // [“a”, “b”, “c”]

如果分割规则为空字符串,则返回数组的成员是原字符串的每一个字符。
‘a|b|c’.split(’’) // [“a”, “|”, “b”, “|”, “c”]

ES5数组新增数组方法

静态方法
Array.isArray()
Array.isArray方法返回一个布尔值,表示参数是否为数组。它可以弥补typeof运算符的不足。
var arr = [1, 2, 3];
typeof arr // “object”
Array.isArray(arr) // true
上面代码中,typeof运算符只能显示数组的类型是Object,而Array.isArray方法可以识别数组。

实例(对象)方法
map方法将数组的所有成员依次传入参数函数,然后把每一次的执行结果组成一个新数组返回。

var numbers = [1, 2, 3];
var res = numbers.map(function (n) {
  return n + 1;
});
res// [2, 3, 4]
numbers
// [1, 2, 3]

上面代码中,numbers数组的所有成员依次执行参数函数,运行结果组成一个新数组返回,原数组没有变化。。
map方法接受一个函数作为参数。该函数调用时,map方法向它传入三个参数:当前成员、当前位置和数组本身。

[1, 2, 3].map(function(elem, index, arr) {
  return elem * index;
});
// [0, 2, 6]

上面代码中,map方法的回调函数有三个参数,elem为当前成员的值,index为当前成员的位置,arr为原数组([1, 2, 3])
forEach方法与map方法很相似,也是对数组的所有成员依次执行参数函数。但是,forEach方法不返回值,只用来操作数据。这就是说,如果数组遍历的目的是为了得到返回值,那么使用map方法,否则使用forEach方法。
forEach的用法与map方法一致,参数是一个函数,该函数同样接受三个参数:当前值、当前位置、整个数组。

function log(element, index, array) {
  console.log('[' + index + '] = ' + element);
}
[2, 5, 9].forEach(log);
// [0] = 2
// [1] = 5
// [2] = 9

forEach方法与map方法很相似,也是对数组的所有成员依次执行参数函数。但是,forEach方法不返回值,只用来操作数据。这就是说,如果数组遍历的目的是为了得到返回值,那么使用map方法,否则使用forEach方法。
forEach的用法与map方法一致,参数是一个函数,该函数同样接受三个参数:当前值、当前位置、整个数组。

function log(element, index, array) {
  console.log('[' + index + '] = ' + element);
}
[2, 5, 9].forEach(log);
// [0] = 2
// [1] = 5
// [2] = 9

注意,forEach方法无法中断执行,总是会将所有成员遍历完。如果希望符合某种条件时,就中断遍历,要使用for循环。

var arr = [1, 2, 3];
for (var i = 0; i < arr.length; i++) {
  if (arr[i] === 2) break;
  console.log(arr[i]);
}
filter()
filter方法用于过滤数组成员,满足条件的成员组成一个新数组返回。
它的参数是一个函数,所有数组成员依次执行该函数,返回结果为true的成员组成一个新数组返回。该方法不会改变原数组。
filter方法的参数函数可以接受三个参数:当前成员,当前位置和整个数组。
var res = [1, 2, 3, 4, 5].filter(function (elem, index, arr) {
  return index % 2 === 0;
});
res// [1, 3, 5]

上面代码返回偶数位置的成员组成的新数组。

reduce方法依次处理数组的每个成员,最终累计为一个值。reduce是从左到右处理(从第一个成员到最后一个成员)
reduce方法参数是一个函数,该函数接受以下两个参数。
1累积变量,默认为数组的第一个成员
2当前变量,默认为数组的第二个成员

var res = [1, 2, 3, 4, 5].reduce(function (a, b) {
  console.log(a, b);
  return a + b;
})
// 1 2
// 3 3
// 6 4
// 10 5
res//最后结果:15

上面代码中,reduce方法求出数组所有成员的和。第一次执行,a是数组的第一个成员1,b是数组的第二个成员2。第二次执行,a为上一轮的返回值3,b为第三个成员3。第三次执行,a为上一轮的返回值6,b为第四个成员4。第四次执行,a为上一轮返回值10,b为第五个成员5。至此所有成员遍历完成,整个方法的返回值就是最后一轮的返回值15。

indexOf(),lastIndexOf()
indexOf方法返回给定元素在数组中第一次出现的位置,如果没有出现则返回-1。
var a = ['a', 'b', 'c'];
a.indexOf('b') // 1
a.indexOf('y') // -1
indexOf方法还可以接受第二个参数,表示搜索的开始位置。

[‘a’, ‘b’, ‘c’].indexOf(‘a’, 1) // -1
上面代码从1号位置开始搜索字符a,结果为-1,表示没有搜索到。

lastIndexOf方法返回给定元素在数组中最后一次出现的位置,如果没有出现则返回-1。
var a = [2, 5, 9, 2];
a.lastIndexOf(2) // 3
a.lastIndexOf(7) // -1
注意,这两个方法不能用来搜索NaN的位置,即它们无法确定数组成员是否包含NaN。

[NaN].indexOf(NaN) // -1
[NaN].lastIndexOf(NaN) // -1
这是因为这两个方法内部,使用严格相等运算符(===)进行比较,
而NaN是唯一一个不等于自身的值

严格模式

启用方法
进入严格模式的标志,是一行字符串use strict。
‘use strict’;
老版本的引擎会把它当作一行普通字符串,加以忽略。新版本的引擎就会进入严格模式。
严格模式可以用于整个脚本,也可以只用于单个函数
(1) 整个脚本文件
use strict放在脚本文件的第一行,整个脚本都将以严格模式运行。如果这行语句不在第一行就无效,整个脚本会以正常模式运行。(严格地说,只要前面不是产生实际运行结果的语句,use strict可以不在第一行,比如直接跟在一个空的分号后面,或者跟在注释后面。)

  <script>
  'use strict';
  console.log('这是严格模式');
</script>
<script>
  console.log('这是正常模式');
</script>
上面代码中,一个网页文件依次有两段 JavaScript 代码。前一个<script>标签是严格模式,后一个不是。
如果use strict写成下面这样,则不起作用,严格模式必须从代码一开始就生效。
<script>
  console.log('这是正常模式');
  'use strict';
</script>

(2)单个函数
use strict放在函数体的第一行,则整个函数以严格模式运行。

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

严格模式
变量声明(必须要使用var)

函数不能有重名的参数

正常模式下,如果函数有多个重名的参数,可以用arguments[i]读取。严格模式下,这属于语法错误。
function f(a, a, b) {
‘use strict’;
return a + b;
}
严格模式
禁止八进制的前缀0表示法
正常模式下,整数的第一位如果是0,表示这是八进制数,比如0100等于十进制的64。严格模式禁止这种表示法,整数第一位为0,将报错。
‘use strict’;
var n = 0100;

禁止 this 关键字指向全局对象
正常模式下,函数内部的this可能会指向全局对象(window),严格模式禁止这种用法,避免无意间创造全局变量。

function f() {// 正常模式
  console.log(this === window);
}
f() // true
function f() {// 严格模式
  'use strict';
  console.log(this === undefined);
}
f() // true
上面代码中,严格模式的函数体内部this是undefined。这种限制对于构造函数尤其有用。使用构造函数时,有时忘了加new,这时this不再指向全局对象,而是报错。
function f() {
  'use strict';
  this.a = 1;
};f();// 报错,this 未定义

创设 eval 作用域
正常模式下,JavaScript 语言有两种变量作用域(scope):全局作用域和函数作用域。严格模式创设了第三种作用域:eval作用域。
正常模式下,eval语句的作用域,取决于它处于全局作用域,还是函数作用域。严格模式下,eval语句本身就是一个作用域,不再能够在其所运行的作用域创设新的变量了,也就是说,eval所生成的变量只能用于eval内部。

(function () {
  'use strict';
  var x = 2;
  console.log(eval('var x = 5; x')) // 5
  console.log(x) // 2
})()
上面代码中,由于eval语句内部是一个独立作用域,所以内部的变量x不会泄露到外部

日期对象及常见API

"Jan",“Feb”,“Mar”,“Apr”,“May”,“Jun”,“Jul”,“Aug”,“Spt”,“Oct”,“Nov”,“Dec”
1月——12月

Date对象是 JavaScript 原生的时间库。它以1970年1月1日00:00:00作为时间的零点,可以表示的时间范围是前后各1亿天(单位为毫秒)
日期对象创建
Date可以当作构造函数使用。对它使用new命令,会返回一个Date对象的实例。如果不加参数,实例代表的就是当前时间。

var today = new Date();
today
// "Tue Dec 01 2015 09:34:43 GMT+0800 (CST)"
// 等同于
today.toString()
// "Tue Dec 01 2015 09:34:43 GMT+0800 (CST)"

对Date实例求值,返回的是一个字符串,代表该实例对应的时间。
日期处理

 oDate.getDate()      返回一个月中的某一天 (1 ~ 31)
 oDate.getDay()       返回一周中的某一天 (0 ~ 6)
 oDate.getMonth()  返回月份 (0 ~ 11)
 oDate.getFullYear() 以四位数字返回年份
作为构造函数时,Date对象可以接受多种格式的参数,返回一个该参数对应的时间实例。
// 参数为时间零点开始计算的毫秒数
new Date(1378218728000)(最常用)
// Tue Sep 03 2013 22:32:08 GMT+0800 (CST)
/ 参数为多个整数,
// 代表年、月、日、小时、分钟、秒、毫秒
new Date(2013, 0, 1, 0, 0, 0, 0)
// Tue Jan 01 2013 00:00:00 GMT+0800 (CST)
new Date(2013, 15)
// Tue Apr 01 2014 00:00:00 GMT+0800 (CST)
参数也可以是一个字符串(最常用)
日期字符串应该符合 RFC 2822 和 ISO 8061 这两个标准,即YYYY-MM-DDTHH:mm:ss.sssZ格式
new Date('2013-2-15')
new Date('2013/2/15')
new Date('02/15/2013')
new Date('2013-FEB-15')
new Date('FEB, 15, 2013')
new Date('Feberuary, 15, 2013')
new Date('15 Feb 2013')
new Date('15, Feberuary, 2013') 
 上面多种日期字符串的写法,返回的都是同一个时间

日期处理

 oDate.getDate()      返回一个月中的某一天 (1 ~ 31)
 oDate.getDay()       返回一周中的某一天 (0 ~ 6)
 oDate.getMonth()  返回月份 (0 ~ 11)
 oDate.getFullYear() 以四位数字返回年份
 oDate.getHours()    返回当前小时(0-23)
 oDate.getMinutes() 返回当前分钟 (0 ~ 59)
 oDate.getSeconds()       返回当前秒(0 ~ 59)
 oDate.getMillisenconds()  返回当前毫秒(0 ~ 999)

注意,月份从0开始计算,但是,天数从1开始计算。另外,除了日期的默认值为1,小时、分钟、秒钟和毫秒的默认值都是0。

oDate.getTime()       返回1970年1月1日至今的毫秒数
oDate.setDate()      设置月中的某一天 (1 ~ 31)
 oDate.setMonth()  设置月份 (0 ~ 11)
 例:oDate.setMonth(9);   alert(oDate.getMonth())
oDate.setFullYear()设置年份(四位数)
oDate.setHours()             设置小时(0-23)
oDate.setMinutes()          设置分钟 (0 ~ 59)
oDate.setSeconds()          设置秒(0 ~ 59)
oDate.setMillisenconds()  设置毫秒(0 ~ 999)
oDate.setTime()                 设置1970年1月1日至今的毫秒数

这些参数如果超出了正常范围,会被自动折算。比如,如果月设为15,就折算为下一年的4月

日期的运算
类型自动转换时,Date实例如果转为数值,则等于对应的毫秒数;如果转为字符串,则等于对应的日期字符串。所以,两个日期实例对象进行减法运算时,返回的是它们间隔的毫秒数;进行加法运算时,返回的是两个字符串连接而成的新字符串。

var d1 = new Date(2000, 2, 1);
var d2 = new Date(2000, 3, 1);

d2 - d1
// 2678400000
d2 + d1
// "Sat Apr 01 2000 00:00:00 GMT+0800 (CST)Wed Mar 01 2000 00:00:00

静态方法
Date.parse方法用来解析日期字符串,返回该时间距离时间零点(1970年1月1日 00:00:00)的毫秒数。
日期字符串应该符合 RFC 2822 和 ISO 8061 这两个标准,即YYYY-MM-DDTHH:mm:ss.sssZ格式,其中最后的Z表示时区。但是,其他格式也可以被解析,请看下面的例子。

Date.parse('Aug 9, 1995')
Date.parse('January 26, 2011 13:51:50')
Date.parse('Mon, 25 Dec 1995 13:30:00 GMT')
Date.parse('Mon, 25 Dec 1995 13:30:00 +0430')
Date.parse('2011-10-10')
Date.parse('2011-10-10T14:48:00')

定时器

setInterval(func,time)
有两个参数,第一个参数是一个函数,第二个参数是时间间隔,单位是毫秒
每间隔time毫秒,会执行一次函数
setInterval的返回值是一个数字
function box(){
	console.log(1)
}
var timer = setInerval(box,1000);
上面代码意思是,没间隔1000毫秒,box函数执行一次。
取消定时器的执行
如果想要取消定时器的执行我们需要拿到setInerval定时器函数的返回值,调用clearInterval,清除定时器
clearInterval(timer),调用之后box函数就不会再执行了!

函数作用域

作用域
作用域(scope)指的是变量存在的范围。
局部作用域和全局作用域
在 ES5 的规范中,Javascript 只有两种作用域:
一种是全局作用域,变量在整个程序中一直存在,所有地方都可以读取;
另一种是函数作用域,变量只在函数内部存在。

函数外部声明的变量就是全局变量(global variable)
在函数内部定义的(使用var)变量,外部无法读取,顾称为“局部变量”(local variable)

var v = 1;//全局变量
function f() {
  var b = 2;//局部变量
  console.log(b);
  console.log(v);//它在函数内部可以读取全局变量,但是局部变量的不能再函数外部访问
}
f()

上面的代码表明,函数f内部可以读取全局变量v。
函数内部定义的变量,会在该作用域内覆盖同名全局变量。

var v = 1;
function f(){
  var v = 2;
  console.log(v);
}
f() // 2
v // 1

上面代码中,变量v同时在函数的外部和内部有定义。结果,在函数内部定义,局部变量v覆盖了全局变量v。

注意,对于var命令来说,局部变量只能在函数内部声明,在其他区块中声明,一律都是全局变量。

if (true) {
  var x = 5;
}
console.log(x);  // 5

上面代码中,变量x在条件判断区块之中声明,结果就是一个全局变量,
可以在区块之外读取。

递归函数
函数可以调用自身,这就是递归。

简单来说,就是函数自己执行过程中,调用自己本身。

f(n)求前n项和

F(n)=F(n-1)+n = F(n-2)+n-1 +n= F(n-3)+n-2 + n-1 + n
......   F(1)+2+3+4.... n-1 + n 


// F(100)= F(99)+100= F(98)+99+100 = F(1)+2+3+4.....+99+100

递归的步骤:
//1.先找临界值,即无需计算 就能获取的值
//2.找本次 和上一次的关系 f(n) = f(n-1)+n (数学归纳)
//3.假设 当前函数已经可以使用了,调用自身计算上一次的运行结果,再写出本次运行结果 即可

//求1-n之间的和
//1 ........ 100
    // 1-  1000
  //1. 临界值1
//2. sum(n-1)+n = sum(n)
  function sum1(n) {
            //临界值
            if(n==1){
                return 1;
            }
            return sum1(n-1)+n;
        }

构造函数及对象类型(了解)

面向对象编程(Object Oriented Programming,缩写为 OOP)是目前主流的编程范式。它将真实世界各种复杂的关系,抽象为一个个对象,然后由对象之间的分工与合作,完成对真实世界的模拟。

面向对象编程的第一步,就是要生成对象。对象是单个实物的抽象。通常需要一个模板,表示某一类实物的共同特征,然后对象根据这个模板生成

JavaScript 语言使用构造函数(constructor)作为对象的模板。所谓”构造函数”,就是专门用来生成实例对象的函数。它就是对象的模板,描述实例对象的基本结构。一个构造函数,可以生成多个实例对象,这些实例对象都有相同的结构。

构造函数就是一个普通的函数,但是有自己的特征和用法。

var Vehicle = function () {
  this.price = 1000;
};

上面代码中,Vehicle就是构造函数。为了与普通函数区别,构造函数名字的第一个字母通常大写。
构造函数的特点有两个。
函数体内部使用了this关键字,代表了所要生成的对象实例。

生成对象的时候,必须使用new命令

new命令的作用,就是执行构造函数,返回一个实例对象。

var Vehicle = function () {
  this.price = 1000;
};
var v = new Vehicle();
v.price // 1000

上面代码通过new命令,让构造函数Vehicle生成一个实例对象,保存在变量v中。这个新生成的实例对象,从构造函数Vehicle得到了price属性。new命令执行时,构造函数内部的this,就代表了新生成的实例对象,this.price表示实例对象有一个price属性,值是1000。

函数

函数的概念

函数是一段可以反复调用的代码块。
作用
在程序设计中,常将一些常用的功能模块编写成函数,以减少重复编写程序段的工作量。
提高代码的复用性、可读性等

函数的创建方式(函数的声明)

(1)function 命令
function命令声明的代码区块,就是一个函数。function命令后面是函数名,函数名后面是一对圆括号。函数体放在大括号里面。
	function 函数名称() {
    		函数中要执行的代码;
	 }

function print() {
  console.log(1);
}

上面的代码命名了一个print函数,以后使用print()这种形式,就可以调用相应的代码。这叫做函数的声明

(2)函数表达式
除了用function命令声明函数,还可以采用变量赋值的写法。

var print = function() {
  console.log(1);
};

这种写法将一个匿名函数(没有名字的函数)赋值给变量。这时,这个匿名函数又称函数表达式

函数的执行(调用)

函数定义好之后,函数中的代码在程序运行过程中不会执行;

function print() {
 	console.log(1);
}

通过函数名称调用函数,调用时执行函数中的代码;调用函数时,要使用圆括号运算符

print();

事件的概念种类
事件:就是发生的事情
事件驱动:就是发生了某件事情之后要处理的手段和过程

参数的声明

函数名后面是一对圆括号,里面是传入函数的参数

function 函数名称(参数列表){
    函数体中的代码;
}

函数定义的时候的参数,称为形参

function print(s) { 
  console.log(s);
}


function add(a,b) { 
  console.log(a+b);
}
参数的传递
	print(1);

调用函数的时候,传入了 参数 1,1的值给了形参s。
函数调用时候传入的参数叫做实参
函数的返回值:
JavaScript 引擎遇到return语句,就直接返回return后面的那个表达式的值,后面即使还有语句,也不会得到执行。
也就是说,return语句所带的那个表达式,就是函数的返回值。

注、return语句不是必需的,如果没有的话,该函数就不返回任何值,或者说返回undefined。

function add(x, y) {
  return x + y; //返回x+y的和
}

var res = add(1, 1) ;//把函数的返回值 赋值给 变量res
console.log(res);//2

变量的声明提升:
函数内部会产生“变量提升”现象。在函数内部使用var命令声明的变量,不管在什么位置,变量声明都会被提升到函数体的头部。

function foo(x) {
  if (x > 100) {
    var tmp = x - 100;
  }
}

// 等同于
function foo(x) {
  var tmp;
  if (x > 100) {
    tmp = x - 100;
  };
}

arguments
由于 JavaScript 允许函数有不定数目的参数,所以需要一种机制,可以在函数体内部读取所有参数。这就是arguments对象的由来。
arguments对象包含了函数运行时的所有参数,arguments[0]就是第一个参数,arguments[1]就是第二个参数,以此类推。这个对象只有在函数体内部,才可以使用。

var f = function (one) {
  console.log(arguments[0]);
  console.log(arguments[1]);
  console.log(arguments[2]);
}

f(1, 2, 3)
通过arguments对象的length属性,可以判断函数调用时到底带几个参数。

循环

while循环
While语句包括一个循环条件和一段代码块,只要条件为真,就不断循环执行代码块。

while (条件) {
  语句;
}
 while语句的循环条件是一个表达式,必须放在圆括号中。代码块部分,如果只有一条语句,可以省略大括号, 否则就必须加上大括号。

下面的例子是一个无限循环,因为循环条件总是为真。注:写程序的时候尽量不要出现死循环

while (true) {
  console.log('Hello, world');
}

下面是while语句的一个例子。(重点)

var i = 0;
while (i < 100) {
  console.log('i 当前为:' + i);
  i = i + 1;
}
上面的代码将循环100次,直到i等于100为止。

do…while 循环
do…while循环与while循环类似,唯一的区别就是先运行一次循环体,然后判断循环条件。

do {
  语句
} while (条件);

不管条件是否为真,do…while循环至少运行一次,这是这种结构最大的特点。另外,while语句后面的分号注意不要省略。

var x = 3;
var i = 0;

do {
  console.log(i);
  i++;
} while(i < x);

for循环的使用(常用)
for语句是循环命令的另一种形式,可以指定循环的起点、终点和终止条件。它的格式如下。

for (初始化表达式; 条件; 递增表达式) {
  语句
}

for语句后面的括号里面,有三个表达式。

初始化表达式(initialize):确定循环变量的初始值,只在循环开始时执行一次。
条件表达式(test):每轮循环开始时,都要执行这个条件表达式,只有值为真,才继续进行循环。
递增表达式(increment):每轮循环的最后一个操作,通常用来递增循环变量。

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

上面代码中,初始化表达式是var i = 0,即初始化一个变量i;测试表达式是i < x,即只要i小于x,就会执行循环;递增表达式是i++,即每次循环结束后,i增大1。

break 语句和 continue 语句

break语句和continue语句都具有跳转作用,可以让代码不按既有的顺序执行。

break语句用于跳出代码块或循环。

var i = 0;
while(i < 100) {
  console.log('i 当前为:' + i);
  i++;
  if (i === 10) break;
}

上面代码只会执行10次循环,一旦i等于10,就会跳出循环。

continue语句
continue语句用于立即终止本轮循环,返回循环结构的头部,开始下一轮循环。

var i = 0;

while (i < 100){
  i++;
  if (i % 2 === 0) continue;
  console.log('i 当前为:' + i);
}

上面代码只有在i为奇数时,才会输出i的值。如果i为偶数,则直接进入下一轮循环。

for循环的嵌套,也称多层循环

for(var i=0;i<10;i++){//外层循环
	//外层循环执行一次,内层循环执行十次
	
	for(var j=0;j<10;j++){//内层循环
		document.write('*')
	}

	document.write('<br/>');
}

正则 正则分组

1:正则的概念
正则表达式(regular expression)是一个描述字符规则的对象。可以用来检查一个字符串是否含有某个子字符串,将匹配的子字符串做替换或者从某个字符串中取出符合某个条件的子串等。
为什么要用正则:
前端往往有大量的表单数据校验工作,采用正则表达式会使得数据校验的工作量大大减轻。常用效果:邮箱、手机号、身份证号等。
2:创建方式
第一种方式:

var reg = new RegExp(“study”,“ig”);   // 第二个参数为修饰符

i:表示忽略大小写ignore。
g:表示全局匹配,查找所有匹配而非在找到第一个匹配后停止 global。
第二种方式:

var reg = /study/ig;

3:正则对象方法
test: 正则实例对象的test方法返回一个布尔值,表示当前模式是否能匹配参数字符串
/cat/.test(‘cats and dogs’) // true
上面代码验证参数字符串之中是否包含cat,结果返回true。

如果正则表达式带有g修饰符,则每一次test方法都从上一次结束的位置开始向后匹配

var r = /x/g;
var s = '_x_x';
r.lastIndex // 0
r.test(s) // true

r.lastIndex // 2
r.test(s) // true

r.lastIndex // 4
r.test(s) // false

上面代码的正则表达式使用了g修饰符,表示是全局搜索,会有多个结果。接着,三次使用test方法,每一次开始搜索的位置都是上一次匹配的后一个位置。

带有g修饰符时,可以通过正则对象的lastIndex属性指定开始搜索的位置

var r = /x/g;
var s = '_x_x';

r.lastIndex = 4;
r.test(s) // false

上面代码指定从字符串的第五个位置开始搜索,这个位置是没有字符的,所以返回false。

exec:用于检索字符串中的正则表达式的匹配。返回一个数组,其中存放匹配的结果。如果未找到匹配,则返回值为null。

var s = '_x_x';
var r1 = /x/;
var r2 = /y/;

r1.exec(s) // ["x"]
r2.exec(s) // null

上面代码中,正则对象r1匹配成功,返回一个数组,成员是匹配结果;正则对象r2匹配失败,返回null。

4:字符串函数

replace: 按照给定的正则表达式进行替换,返回替换后的字符串。
字符串对象的replace方法可以替换匹配的值。它接受两个参数,第一个是正则表达式,表示搜索模式,第二个是替换的内容。
str.replace(search, replacement)
正则表达式如果不加g修饰符,就替换第一个匹配成功的值,否则替换所有匹配成功的值。

'aaa'.replace('a', 'b') // "baa"
'aaa'.replace(/a/, 'b') // "baa"
'aaa'.replace(/a/g, 'b') // "bbb"

//上面代码中,最后一个正则表达式使用了g修饰符,导致所有的b都被替换掉了。

match: 字符串实例对象的match方法对字符串进行正则匹配,返回匹配结果。

var s = '_x_x';
var r1 = /x/;
var r2 = /y/;
s.match(r1) //["x"]
s.match(r2) // null

//从上面代码可以看到,字符串的match方法与正则对象的exec方法非常类似:匹配成功返回一个数组,匹配失败返回null。

如果正则表达式带有g修饰符,则该方法与正则对象的exec方法行为不同,会一次性返回所有匹配成功的结果

var s = 'abba';
var r = /a/g;

s.match(r) // ["a", "a"]
r.exec(s) // ["a"]

search:检索与正则表达式相匹配的值。返回字符串中第一个与正则表达式相匹配的子串的起始位置。如果没有找到则返回-1。

'_x_x'.search(/x/)// 1

//上面代码中,第一个匹配结果出现在字符串的1号位置。
5:正则表达式构成
大部分字符在正则表达式中,就是字面的含义,比如/a/匹配a,/b/匹配b。如果在正则表达式之中,某个字符只表示它字面的含义(就像前面的a和b),那么它们就叫做“字面量字符”。

/dog/.test('old dog') // true

上面代码中正则表达式的dog,就是字面量字符,所以/dog/匹配old dog,因为它就表示d、o、g三个字母连在一起。
除了字面量字符以外,还有一部分字符有特殊含义,不代表字面的意思。它们叫做“元字符”,主要有以下几个
正则表达式是由普通字符(例如字符a到z)以及特殊字符(称为元字符)组成的文字模式。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。

元字符—限定符:
限定符可以指定正则表达式的一个给定组件必须要出现多少次才能满足匹配

*:匹配前面的子表达式零次或多次。。
+:匹配前面的子表达式一次或多次。
?:匹配前面的子表达式零次或一次。
{n}:匹配确定n次。
{n,}:至少匹配n次。
{n, m}:最少匹配n次且最多匹配m次。

// t 出现0次或1次

/t?est/.test('test') // true
/t?est/.test('est') // true

// t 出现1次或多次

/t+est/.test('test') // true
/t+est/.test('ttest') // true
/t+est/.test('est') // false

// t 出现0次或多次

/t*est/.test('test') // true
/t*est/.test('ttest') // true
/t*est/.test('tttest') // true
/t*est/.test('est') // true
/lo{2}k/.test('look') // true
/lo{2,5}k/.test('looook') // true

//上面代码中,第一个模式指定o连续出现2次,第二个模式指定o连续出现2次到5次之间

元字符—字符匹配符

字符匹配符用于匹配某个或某些字符。
[xyz]:字符集合。匹配所包含的任意一个字符。

/[abc]/.test('hello world') // false
/[abc]/.test('apple') // true

//上面代码中,字符串hello world不包含a、b、c这三个字母中的任一个,所以返回false;字符串apple包含字母a,所以返回true

[^xyz]: 表示除了x、y、z之外都可以匹配。

/[^abc]/.test('hello world') // true
/[^abc]/.test('bbc') // false

//上面代码中,字符串hello world不包含字母a、b、c中的任一个,所以返回true;字符串bbc不包含a、b、c以外的字母,所以返回false。

[a-z]:字符范围。匹配指定范围内的任意字符。
[abc]可以写成[a-c][0123456789]可以写成[0-9],同理[A-Z]表示26个大写字母。

/[a-z]/.test('b') // true

这样也可以:[0-9][0-9a-z][0-9a-zA-Z]
[0-9a-zA-Z]  表示数字0-9,大小字母
[^a-z]:表示不包含小写字母。

\d 匹配0-9之间的任一数字,相当于[0-9]。
 \D 匹配所有0-9以外的字符,相当于[^0-9]。
 \w 匹配任意的字母、数字和下划线,相当于[A-Za-z0-9_]。
\W 除所有字母、数字和下划线以外的字符,相当于[^A-Za-z0-9_]。
 \s 匹配空格(包括换行符、制表符、空格符等)。
 \S 匹配非空格的字符。
.:匹配除”\n”之外的任何单个字符。

元字符—定位符:
定位符可以将一个正则表达式固定在一行的开始或结束。也可以创建只在单词内或只在单词的开始或结尾处出现的正则表达式。
^:匹配输入字符串的开始位置。
$:匹配输入字符串的结束位置。

// test必须出现在开始位置/^test/.test(‘test123’) // true

// test必须出现在结束位置/test$/.test(‘new test’) // true

// 从开始位置到结束位置只有
test/^test / . t e s t ( ′ t e s t ′ ) / / t r u e / t e s t /.test('test') // true /^test /.test(test)//true/test/.test(‘test test’) // false

元字符—转义符:
\:用于匹配某些特殊字符。
正则表达式中那些有特殊含义的元字符,如果要匹配它们本身,就需要在它们前面要加上反斜杠。比如要匹配+,就要写成+。

/1+1/.test('1+1')// false

/1\+1/.test('1+1')// true

//上面代码中,第一个正则表达式之所以不匹配,因为加号是元字符,不代表自身。
第二个正则表达式使用反斜杠对加号转义,就能匹配成功。

元字符—选择匹配符:
|:可以匹配多个规则。
竖线符号(|)在正则表达式中表示“或关系”(OR),即cat|dog表示匹配cat或dog。
/11|22/.test(‘911’) // true
//上面代码中,正则表达式指定必须匹配11或22

// 匹配fred、barney、betty之中的一个
/fred|barney|betty/

//1-什么是分组

var reg = /(\d{2})/
reg.test('12');  //true
// 这里reg中的(/d{2})就表示一个分组,匹配两位数字


/hahaha/
/(ha){3}/

这两个表达式是等效的,但有了分组之后可以更急简洁

//2- 捕获型 分组 ()
// 被正则表达式捕获(匹配)到的字符串会被暂存起来,其中,由分组捕获到的字符串会从1开始编号,于是我们可以引用这些字符串:

var reg = /(\d{4})-(\d{2})-(\d{2})/;
var dateStr = '2018-04-18';
reg.test(dateStr);  //true
//引用捕获到的内容使用 $1 代表第一个分组的捕获到的内容
RegExp.$1   //2018
RegExp.$2   //04
RegExp.$3   //18

// 3-非捕获型 (?😃
// 有的时候只是为了分组并不需要捕获的情况下就可以使用非捕获型分组

var reg = /(?:\d{4})-(\d{2})-(\d{2})/
var date = '2012-12-21'
reg.test(date)
RegExp.$1 // 12
RegExp.$2 // 21

// 4- 结合replace方法做字符串自定义替换

var dateStr = '2018/04/18';
var reg = /(\d{4})\/(\d{2})\/(\d{2})/;
dateStr = dateStr.replace(reg, '$1-$2-$3') //"2018-04-18"
//不过这里需要注意的是/是需要用\转义的

// 5- 结合正则exec方法来使用
//通俗来说,分组就是在正则表达式中用()包起来的内容代表了一个分组

        var s;
        var re = new RegExp("d(b+)(d)", "ig");
        var str = "cdbBdbsbdbdz";
        var arr = re.exec(str);
        console.log(arr)

    
0: "dbBd"  正则整体匹配到的字符
1: "bB"    第一个小括号(分组)匹配到的字符
2: "d"     第二个小括号(分组)匹配到的字符
      
   第一个分组的结果也可以用 RegExp.$1   获取
     s = "$1 contains: " + RegExp.$1 + "\n";
     s += "$2 contains: " + RegExp.$2 + "\n";
     console.log(s)

6- 结合字符串match方法使用

      var str = "http://www.taobao.com:80/cuxiao/hongbao.html";
        var patt1 = /(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)/;
        arr = str.match(patt1);
        console.log(arr);
   
0: "http://www.taobao.com:80/cuxiao/hongbao.html"  整个正则匹配到的字符串
1: "http"     第一个分组 匹配到的字符串
2: "www.taobao.com"   第二个分组 匹配到的字符串
3: ":80"      第三个分组 匹配到的字符串
4: "/cuxiao/hongbao.html"   第四个分组 匹配到的字符串
        
        
      第一个分组的结果也可以用 RegExp.$1   获取
        console.log(RegExp.$1)//http
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于阅读和编写。它基于JavaScript语言的一个子集,但是可以被多种编程语言使用。JSON数据格式由键值对组成,键和值之间用冒号分隔,键值对之间用逗号分隔,整个数据用花括号包裹。JSON数据可以嵌套,也可以包含数组。JSON数据格式的优点是易于解析和生成,同时也易于传输和存储。 ### 回答2: JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,在Web应用中广泛使用。与XML类似,JSON也能够存储和传输数据,但是它更加简单、易于读写、易于理解和编写,且更适合于网络数据传输。 JSON的语法规则很简洁,由两大基本数据类型和三种基本结构构成。基本数据类型包括“对象”和“数组”,结构包括“键值对”、“值”列表和“对象”列表。其中,对象由一系列“键值对”构成,而数组则由一个有序的“值”列表构成。 JSON常见的使用场景有两个:一个是把JSON作为数据格式来传递数据,这通常通过HTTP请求进行。另一个是把JSON用来构建Web应用中的前端交互,例如AJAX的使用,前端通过请求JSON数据并将其解析成JavaScript对象来动态更新网页展示的数据等。 JSON有些特点需要我们注意。首先,JSON中的数据都是以明确的方式描述的,这使得解析和处理JSON相对容易。其次,JSON是一种独立的数据格式,与语言无关,可以很方便地用在不同的编程语言中。此外,因为其轻量级特性,JSON也逐渐成为了使用最广泛的数据交换格式之一。 在使用JSON的过程中,我们需要了解JSON的语法和结构,并根据需要进行存储、格式化、解析等操作。同时,我们还需要注意JSON的安全问题,例如数据类型不一致、格式不正确等,这些问题可能会导致代码出现漏洞或安全问题。因此,在使用JSON时我们需要保持警觉,严格遵守JSON的规范和安全标准,以免出现不必要的错误。 ### 回答3: JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,具有易读、易解释、易编写和易于开发的特点。它的设计目的是为了与JavaScript编程语言的正常操作相匹配,并且已经成为了一种事实上的数据交换标准。 JSON由两个结构构成:键值对和数组。键值对使用:分隔符分开键和值,使用,分隔符分开不同的键值对;数组使用[]表示,元素之间使用,分隔符分开。 JSON是一个纯文本格式,可以使用任何文本编辑器进行编辑。但是,所有的数据都需要严格遵守JSON格式。不允许出现未经转义的双引号、单引号、换行符等。 JSON的使用非常广泛,特别是在前端开发中,常用于实现Ajax异步数据传输和一些API接口的数据交换。与XML相比,JSON更加轻量级和易读,也更加方便JavaScript中的操作。 除此之外,还有一些和JSON相关的概念,如JSON Schema用于验证数据是否符合JSON格式,JSONP用于实现跨域请求数据等。 总之,了解JSON基础知识是前端开发中必备的技能之一,掌握JSON的语法规则和正确地处理JSON数据可以使开发更加高效和优雅。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值