四天学会JavaScript(Day1~Day4)

四天学会JavaScript(Day1~Day4)

Day1

前言

       一年一度的国庆长假终于来了,但是对于一名菜鸟来说,是绝对不能放过这么好的一个学习机会的,所以我打算花七天的时间把JavaScript的大体内容简单的过一遍。前端这一块呢,我几乎是一个小白。过去也只是写写Ajax,或者整几个XX事件,接收接收数据而已。所以这个国庆我是计划用七天的时间把JavaScript语言从头到尾,简单的过一遍。毕竟本人是后端开发的程序员,前端也不需要太过深入,换句话说是暂时不用太过深入。于是,前天下班的时候我就找领导借了本七百多页【JavaScript高级程序设计】的书,那么这四天的博客就是我四天的笔记。我会尽量把书中的精华总结出来。

       一般情况下呢,一个后端程序员在他入职之前肯定是经历了一个学习阶段。而学习阶段肯定是学过Servlet,JSP的,不然后面的SSM什么的都没法学。而学JSP的前提也是要首先会一点HTML,CSS,JavaScript或者Jquery。所以说像这种速成的学法比较适合有一定基础的人而不是零基础。零基础如果要专门学前端的话不建议速成。

第一天的学习内容

JavaScript基本语法
垃圾收集机制
引用数据类型
Array类型
顺序栈数据结构
顺序队列数据结构
RegExp

JavaScript简介

       JavaScript是诞生于1995年,很多没接触过JavaScript的人可能会认为这个语言一定和Java有关系,然而事实并不是这样。

       JavaScript刚诞生的时候,主要目的还是为了处理以前由服务器端语言比如说Perl负责的一些输入验证操作。再此之前,必须把表单数据发送到服务器端才能确定用户是否没有填写某个必填域,学过JavaWeb的人一定是很容易理解这个概念的。如果说表单的每次请求都要发给后端才能验证判断是否遗漏哪些必填项的话,响应的速度肯定是会慢很多的。所以现在JavaScript也逐渐成为市面上常见浏览器的必备功能。

       现如今呢,JavaScript已经变成了一个功能非常全面的编程语言,它从一个简单的输入验证器发展到现在确实非常出乎人的意料。你可以说它是一个非常简单的编程语言,也可以说它是一个非常难学的编程语言。说它简单,是因为它可以很快学会使用,但是如果要深入掌握,那就需要很多年的时间了。而我呢,是打算七天学完,所以说,我这七天也仅仅只是学会它的使用而已。如果要再深入研究底层的话应该是需要很长时间。

JavaScript基本语法

       JavaScript的语法很多都借鉴了C语言或者类C语言。在JavaScript中是区分大小写的,第一个字符必须是一个字母、下划线(_)或者美元符号($)符号。注视这一块也是C语言风格的注释,可以是//也可以是/**/。

       typeof 操作符可以让用户知道变量是什么数据类型。

<!DOCTYPE html>
<html>
    <head>
       <meta charset="utf-8" />
	   <title>网页标题</title>
	   <script type="text/javascript">
		   var flag = true;
		   alert(typeof flag);
		   //返回结果是 boolean
	   </script>
    </head>
    <body>
        
    </body>
</html>
NAN

       NAN是英文Not a Number的缩写,从英文意思就知道是非数值。这个数值主要表示本来要返回一个数值的操作数未返回数值的情况。(这样就不会抛错误了)。就举个例子,当 9 / "hello" 的时候,返回的则是NAN。因为9是数值但是"hello"不是数值而是字符串。isNAN()函数就是用来判断一个值到底是不是数值

	 alert(isNaN(NaN));	//true
	 alert(isNaN(666)); //false

数值转换

       在JavaScript里面有三个函数可以把非数值转换成数值: Number()、parseInt()、parseFloat()。第一个函数Number可以用于任何数据类型、另外两个函数就是专门给字符串用的,在Java语言里面也见过这样的方法。

       使用Number转化成数值的时候,字符串必须完全是数字,否则返回NAN。使用parseInt的时候,如果第一个字符是数值那么它会判断第二个字符是不是数值。直到遇见非数值的时候,后面的就不会再判断直接返回前面的内容了。就比如num3只返回了15一个道理。

		var num1 = Number("helloworld");	//NAN
		var num2 = parseInt("hello");		//NAN
		var num3 = parseInt("15asf96");		//15
		var num4 = parseInt("4546465");		//4546465
		var num5 = Number("asf45448f4sa86");	//NAN
		var num6 = Number("15464");			//15464
		var num7 = Number("15asfasf");		//NAN
		alert(num1 + " " + num2 + " " + num3 + " " + num4 + " " + num5 + " " + num6 + " " + num7);
字符串面量
\n 换行
\t 制表 tab
\b 退格
\r 回车
\\ 斜杠
\' 单引号
\"" 双引号
\xnn 以十六进制代码 nn 表示一个字符
\unnn 以十六进制代码表示一个uniCode字符
for-in 语句

       有点像for each

	for(var propName in window){
   
		document.write(propName);
	}
with语句

       with语句的作用是把代码的作用域全都设置到一个特定的对象中。下面两段代码的作用是相同的。

	   var str = "today is great day";
	   var a = str.substring(2);
	   var b = str.charAt(3);
	   alert("a = " + a + " b = " + b);
	   var str = "today is great day";
	   with(str){
   
		   var a = substring(2);
		   var b = charAt(3);
		   alert("a = " + a + " b = " + b);
	   }

函数

       在JavaScript中函数都是统一使用function来声明。如果需要返回直接return就好了。

	   function my(num1,num2){
   
			   return num1 + num2;
		   }
	   var result = my(9,9);
	   alert("result = " + result);
没有重载

       在JavaScript中,函数没有重载。假如程序员定义了两个名字相同的函数,调用的时候则会调用下面的那个。

= = 和 = = = 有什么区别?

       “= = =”首先计算其操作数的值,然后比较这两个值,比较过程没有任何类型转换。相等运算符“= =”如果两个操作数不是同一类型,那么相等运算符会尝试一些类型转换,然后进行比较

		   var a = 1;
		   var b = '1';
		   alert(a == b);	//true
		   alert(a === b);	//false

垃圾收集

       JavaScript具有自动垃圾收集机制,也就是说执行环境会负责管理代码执行过程中使用的内存。而在C和C++之类的语言中,开发人员的基本任务就是手工跟踪内存的使用情况,这样很容易造成许多问题。这个垃圾收集器的工作原理也很简单,其实就是找到那些不用的变量,然后释放掉它的内存。不需要像C++一样还要去delete。

       当我们在一个函数中定义了一个局部变量,那么这个局部变量会在该函数执行的过程中存在。而这个过程中会为该局部变量在栈(或者堆)的内存上分配相应的空间以便存储他们的值。直到函数要执行结束了,这个时候局部变量就没有存在的必要,然后就会释放他们供内存使用。

标记清除

       JavaScript中最常见的垃圾清理方式是标记清除。当变量进入环境的时候会将这个变量标记为进入环境,当变量要离开的时候会被标记成离开环境。垃圾收集器会在运行的时候给存储在内存中的所有变量都加上标记,然后它会去掉环境中的变量以及被环境中的变量引用的变量标记。而在此之后再被加上标记的变量就会被视为准备删除的变量,原因是环境中的变量已经无法访问这些变量了。最后垃圾收集器完成内存清除的工作。销毁那些带标记的值并收回他们所占用的内存空间。

管理内存

       虽然JavaScript已经具有了垃圾收集机制,但是在内存管理和垃圾收集面临的问题还是有点与众不同。最常见的问题就是分配给Web浏览器的可用内存数量通常要比分给桌面的要少。这样做的目的主要是为了防止运行JavaScript的网页耗尽全部系统内存而导致系统崩溃。内存限制问题不仅会影响给变量分配内存,同时还会影响调用栈以及在一个线程中能够同时执行的语句数量。所以说我们要确保占用最少的内存给浏览器最好的性能。

       如果说一个数据已经不再有用了,则可以把他置为Null来释放这个引用。通常称之为解除引用。

		  function fun(name){
   
			   var obj = new Object();
			   obj.name = name;
			   return obj;
		   }
		   var local = fun("hello world");
		   alert(local);
		   //手工解除引用
		   local = null;

       不过,这种做法并不意味着自动回收该值所占用的内存。解除引用的真正作用是让值脱离执行环境,方便垃圾收集器下次执行的时候将其回收。

引用数据类型

Object类型

       JavaScript中对象其实就是一组数据和功能的集合。对象可以通过执行new操作符跟要创建的对象类型的名称来创建。而创建Object类型的实例并为其添加属性或者方法就可以创建自定义对象。下面三段代码作为操作的案例。

使用构造函数的方法创建
	  function fun(){
   
		   var obj = new Object();
		   obj.name = "alvin";
		   obj.age = 12;
		   obj.score = 98;
		   alert("姓名: " + obj.name + " 年龄: " + obj.age + " 成绩: " + obj.score);
	  }
使用对象字面量的方法创建
      var person = {
   
		   name : "bob",
		   age : 18,
		   score : 98
	   };
	   alert("姓名: " + person.name + " 年龄: " + person.age + " 成绩: " + person.score);
还可以直接 = {},此类操作和 new Object() 是相同的
	   var person = {
   };
	   person.name = "alvin";
	   person.age = 18;
	   person.score = 78;
	   alert("姓名: " + person.name + " 年龄: " + person.age + " 成绩: " + person.score);

Array类型

       作为一名后端程序员来说,一看名字就知道这是数组,但是JavaScript的数组和Java或者C语言的数组不太一样。JavaScript的数组使用起来更加有点像是Python语言里面的列表。在C语言里面,数组的大小和类型都是固定的。也就是说,一旦定义了数组的大小和类型就不再可以改变。而JavaScript的数组大小可以动态调整,并且存储的类型可以是任何类型。下面一段代码举个例子。

	   var arr = new Array();
	   arr[0] = "hello";
	   arr[1] = 123;
	   arr[2] = 9.9;
	   arr[3] = true;
	   alert(arr);

       数组的创建方法还有一种,就是前面说过的字面量表示法

	   var arr = [1,2,3,4,5,6,7];
	   alert(arr);
检测数组

       在JavaScript里,如果要确定一个对象是不是数组就可以使用 instanceof 操作符得到满意的结果。

       var arr = [1,2,3,4,5];
	   if(arr instanceof Array){
   
		   alert("是数组");
	   }else{
   
		   alert("不是数组");
	   }

       但是这么做的话又会有一个问题,那就是它假定只有一个全局执行环境。如果网页中包含多个框架,那实际上就存在两个完全不同的全局执行环境,从而存在两个以上不同版本的Array构造函数。如果说我要从一个框架向另一个框架传入数组。那么传入的数组和第二个框架中原生创建的数组分别具有各自不同的构造函数。于是乎后面就出现了Array.isArray()方法。

	   var arr = [1,2,3,4,5];
	   if(Array.isArray(arr)){
   
		   alert("是数组");
	   }else{
   
		   alert("不是数组");
	   }
转换方法

       在JavaScript中所有对象都具有toLocaleString()、toString()和valueOf()方法。其中呢,valueOf 返回的还是数组本身,而调用toString就会返回数组的字符串。而每个元素之间都会有一个逗号,学过Java语言的话一定深有体会。

       toLocaleString() 和 toString咋一看显示的内容好像差不多啊。但实际上还是有一定区别的。toLocaleString()是为了取得每一项的值,调用的是每一项的toLocaleString()方法,而不是toString()方法。

栈和队列

       栈和队列都是属于数据结构一类,本人过去曾写过这类的博客。

栈和队列的基本概念

顺序栈和链栈

顺序栈和链栈的应用

顺序队和链队

使用自定义的栈来优化二叉树的遍历

       在JavaScript中也提供了一种让数组的行为类似于其他数据结构的方法。就比如说,数组可以表现得像栈。栈是一种可以限制插入和删除的数据结构,其本质更像是一种受限制的线性表。栈既可以用数组表示也可以用链表表示,而在这里自然是数组表示的顺序栈。

       push()方法可以接收任意数量的参数,把它们逐个添加到数组末尾,并且返回修改数组的长度。而pop()方法则是从数组末尾移除最后一项,减少length值。然后返回移除的项。

	   //创建一个数组
	   var arr = new Array();
	   //推入两项
	   var count = arr.push("alvin","bob");
	   alert(count);	//2
	   //再推入一个
	   count = arr.push("finally");
	   alert(count);
	   //取得最后一项
	   var item = arr.pop();
	   alert(item);  //这里返回的是 finally。 也就是最后一项
	   //结果
	   alert(arr);

       接着我们说说队列。队列和栈一样都是受限制的线性表。然后队列和栈是相反的数据结构,可以参考博客栈和队列的基本概念。栈是先进后出,而队列则是先进先出。由于push()是向数组末尾添加项的方法,所以模拟队列就需要一个从数组前端取的项的方法。而实现这个操作的方法则是shift()。它能够移除数组的第一项并且返回该项,然后数组长度-1。shift和push结合可以让数组用起来像是队列。

	  //创建一个数组
	   var arr = new Array();
	   //推入两项
	   var count = arr.push("alvin","bob");
	   alert(count);	//2
	   //再推入一个
	   count = arr.push("finally");
	   alert(count);
	   //取得最后一项
	   var item = arr.shift();
	   alert(item);  //这里返回的是 finally。 也就是最后一项
	   //结果
	   alert(arr);

       我们发现代码其实没什么改变,只是把pop换成了shift而已~

排序方法

       在数组中提供了两个用来排序的方法。它们分别是sort和reverse。sort是顺序,reverse是逆序,也就是翻转。

迭代方法

       在JavaScript中为数组定义了五个迭代方法。每个方法接收两个参数。要在每一项上运行的函数作为该函数作用域对象。影响this本身。传入这些方法中的函数会接收三个参数:数组项的值、该项在数组中的位置和数组对象本身。根据使用的方法不同,这个函数执行后的返回值可能会也可能不会影响方法的返回值。这里分别介绍一下

every() 对数组中的每一项给定运行函数,如果该函数对每一项都返回true,那么就返回true
filter() 对数组中的每一项给定运行函数,返回该函数会返回true的项组成数组。
forEach() 对数组中的每一项给定运行函数,这个方法没有返回值/
map() 对数组中的每一项给定运行函数,返回每次调用的结果组成的数组
some() 对数组中的每一项给定运行函数,如果该函数对任一项返回true那么就返回true。

       语法示例

   var numbers = [1,2,3,4,5,6,7];
   var result = numbers.some(function(item,index,array){
   
	  return (item > 2); 
   });
   alert(result);
归并方法

       在JavaScript中还为数组提供了两个归并数组的方法。他们都会迭代数组的所有项然后构建一个最终返回的值。reduce()是从第一个开始。而reduceRight()则是从最后一个开始。

	//求数组中所有值之和
	var arr = [1,2,3,4,5];
	var sum = arr.reduce(function(prev,cur,index,array){
   
		return prev + cur;
	});
	alert(sum);

Date类型

       JavaScript中的Data类型是在早期Java语言中util包中的Date基础上构建的。方法比较多,使用的时候可以看手册或者API。

	//获得当前的时间
	var now = new Date();
	alert(now);
	//设置时间
	now = new Date("2018-9-12");
	alert(now);
toDateString() 以特定的格式显示年,月,日,周
toTimeString() 以特定的格式显示时,分,秒,地区
toLocaleDateString() 以特定地区的格式显示年,月,日,周
toLocaleTimeString() 以特定地区的格式显示年,月,日,周
toUTCString() 以特定的格式完整的UTC日期

RegExp

       JavaScript通过RegEXp类型来支持正则表达式

	var patt=/pattern/modifiers; 

       pattern(模式) 描述了表达式的模式

       modifiers(修饰符) 用于指定全局匹配、区分大小写的匹配和多行匹配

       当使用构造函数创造正则对象时,需要常规的字符转义规则(在前面加反斜杠 \)。比如,以下是等价的:

	var re = new RegExp("\\w+");
	var re = /\w+/;

       每个正则表达式都可带有一或多个标志(flags),用来表明正则表达式的行为。正则表达式的匹配模式支持三种标志。

        g : 表示全局模式。这个模式将被应用于所有字符串,而不是在发现第一个匹配项的时候就立即停止。

        i : 表示不区分大小写模式。也就是确定匹配项时忽略模式和字符串的大小写。

        m :表示多行模式,就是在到达一行文本末尾时还会继续查找下一行中是否与模式匹配的项。

       所以说一个正则表达式就是一个模式和三个标志的组合体。不同的组合产生不同的效果。

    //匹配字符串中所有good 实例
	var pattern = /good/g;
	//匹配第一个bat或cat 不区分大小写
	var pattern2 = /[bc]at/i;
	//匹配所有以at结尾的三个字符的组合,不区分大小写
	var pattern3 = / .at/gi;
字面量模式 等价的字符串
/\[bc\]at/ "\ \[bc\\]at"
/\.at/ "\\.at"
/name\/age/ "name\\/age"
/\d. \d{1,2}/ "\\d. \\d{1,2}"
/\w\\hello\\123/ "\\w\\\\hello\\\\123"

       使用正则表达式字面量和使用RegExp构造函数创建的正则表达式不太一样。在JavaScript中正则表达式字面量始终会共享同一个RegExp实例,而使用构造函数创建的每一个RegExp实例都是一个新的实例。

RegExp实例属性
global 布尔值,表示是否设置了g的标志
ignoreCase 布尔值,表示是否设置了i的标志
lastIndex 整数,表示开始搜索下一个匹配项的字符位置,从0算起。
multiline 布尔值,表示是否设置了m的标志
source 正则表达式的字符串表示,按照字面量形式而非传入构造函数中的字符串模式返回。

       通过这些属性可以获知一个正则表达式的各方面信息

	var pattern = /\[bc\]at/i;
	//false
	alert(pattern.global);
	//true
	alert(pattern.ignoreCase);
	//false
	alert(pattern.multiline);
	//0
	alert(pattern.lastIndex);
	//\[bc\]at
	alert(pattern.source);

Day2

前言

       今天是国庆假期的第三天,也是我学JavaScript的第二天。我们知道,对于一个已经在职的程序员来说,学习一门新的编程语言,其实也就是学习它的语法,因为编程语言的概念大部分都是互通的,只要语法理解了就好上手。JavaScript我是用速成的方法学习,主要目的还是想把里面的东西都过一遍知道这些到底是怎么一回事。以后写代码看API的时候也容易看得懂,但是由于时间过短。语法和特性有可能会忘记一些,这种情况是很糟糕的。为了确保这七天下来,我能把语法和一些特性给记住,所以我决定每天学习完当天的内容之后,再使用JavaScript实现一种数据结构。这样七天下来我才能够记住语法并且看API也可以写的来。

第二天学习的内容

面向对象程序设计
链表数据结构(面向对象语法练习)
BOM
DOM
事件

RegExp后续

RegExp构造函数属性

       RegExp构造函数包含了一些属性,这些属性适用于作用域中的所有正则表达式,并且基于所执行的最近一次正则表达式操作而变化。关于这些属性的另一个独特之处,就是可以通过两种方式访问他们。换句话说这些属性分别有一个长属性名和一个短属性名。

长属性名 短属性名 说明
input $_ 最近一次要匹配的字符串。Opera未实现此属性
lastMatch $& 最近的一次匹配项。Opera未实现此属性
lastParen $+ 最近一次匹配的捕获组。Opera未实现此属性
leftContext $' input字符串中lastMatch之前的文本
multiline $* 布尔值,表示是否所有表达式都是多行模式。IE和Opera未实现此属性
rightContext $' input字符串中lastMatch之后的文本

面向对象程序设计

       关于面向对象的概念呢,这里就不多说了,直接学习语法就可以了。面向对象编程思想

       昨天学习了引用数据类型Object。所以现在也就大概知道对象是怎么创建的了。今天写两段代码回顾一下

对象的创建

构造函数法
  var person = new Object();
   person.name = "alvin";
   person.age = 18;
   //对象的方法
   person.sum = function(){
   
	   alert(person.name);
   }
   //调用
   person.sum();
字面量法
	var person = {
   
		name : "alvin",
		age : 19,
		fun : function(){
   
			alert("hello world");
		}
	};
	person.fun();

       除了这两种方法以外我们还有其他创建方式

工厂模式(寄生构造函数模式)

       工厂模式是软件工程领域的一种广为人知的设计模式。这种模式抽象了创建具体对象的过程。

	function createPerson(name,age,job){
   
		var o = new Object();
		o.name = name;
		o.age = age;
		o.job = job;
		o.hello = function(){
   
			alert("hello");
		}
		return o;
	}
	
	var person = createPerson("alvin",19,"work");
	person.hello();
	alert(person.name);
构造函数模式

       构造函数和普通的函数本质上没什么区别,只是构造函数在调用的时候是用new罢了。按照写代码的规范,构造函数一般就使用大写字母开头。

	function Person(name,age,job){
   
		this.name = name;
		this.age = age;
		this.job = job;
		this.hello = function(){
   
			alert("hello");
		};
	}
	var per = new Person("alvin",19,"work");
	per.hello();
	alert(per.name);
原型模式

       我们创建的所有函数都包含了prototype属性,这个属性是一个指针,指向一个对象。而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。

	function Person(){
   }
	Person.prototype.name = "alvin";
	Person.prototype.age = 29;
	
	var per1 = new Person();
	var per2 = new Person();
	alert(per1.name  == per2.name);	//true

       in操作符除了可以在for循环的时候使用,也可以用来判断一个属性是否存在一个对象里面。如果有就返回true,否则返回false。如果想要删除对象的属性的值则可以使用delete

	function Person(){
   
		
	}
	Person.prototype.name = "alvin";
	alert("name" in Person); //true
	alert(Person.prototype.name);	//alvin
	delete Person.name;
	alert(Person.name);	//什么也没有
更简单的原型语法
	function Person(){
   }
	Person.prototype={
   
		name : "alvin",
		age : 29,
		job : "java",
		hello : function(){
   
			alert("hello");
		}
	}
	var per = new Person();
	per.hello();
	alert(per.name);
组合使用构造函数模式和原型模式
	function Person(name,age,job){
   
		this.name = name;
		this.age = age;
		this.job = job;
	}
	Person.prototype = {
   
		constructor : Person,
		hello : function(){
   
			alert("hello");
		}
	}
	var per = new Person("alvin",19,"java");
	alert(per.name);
	per.constructor.age = 7;
	alert(per.constructor.age);

继承

       在JavaScript里面描述了原型链的概念,并且将原型链作为继承的主要方法。基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。实现原型链的一个基本模式代码如下

		function SuperType(){
   
			this.prototype = true;
		}
		SuperType.prototype.getSuperValue = function(){
   
			return this.prototy;
		}
		function SubType(){
   
			this.subproperty = false;
		}
		//继承SuperType
		SubType.prototype = new SuperType();
		SubType.prototype.getSuperValue = function(){
   
			return this.subproperty;
		}
		var instance = new SubType();
		alert(instance.getSuperValue());

       面向对象这块,内容比较多。下次有时间我单独学这一块。因为对于后端的我来说可能用的也不太多。今天还是主要把精力放在BOM和DOM上。接下来就再实现一个单链表数据结构来巩固下语法。

面向对象练习(实现单链表数据结构)

       关于单链表数据结构,我过去也写过一些这样的博客。那么今天为了巩固JavaScript在面向对象这一块儿的语法,就用JavaScript来实现一遍单链表的增删查改吧~不过我说实话...数据结构这种东西和编程语言也没有太大关系。它只是一种思想。所以等下我的代码风格可能还是和以前写C语言的风格差不多。

线性表的基本概念

单链表的操作

这里就再用JavaScript写一遍链表。
   //单向链表类
	function SingleLinkList(){
   
		//内部类
		function Node(data){
   
			this.data = data;
			this.next = null;
		}
		//头节点
		var head = new Node(null);
		//新增
		this.add = function(data){
   
			var temp = new Node(data);
			temp.next = head.next;
			head.next = temp;
		};
		//遍历
		this.print = function(){
   
			var temp = head.next;
			while(temp!= null){
   
				if(temp.next != null){
   
					console.log(temp.data + "->");
				}else{
   
					console.log(temp.data);
				}
				temp = temp.next;
			}
		};
		//修改
		this.replace = function(index,newData){
   
			var temp = head.next;
			var i = 0;
			//先找到它,找到之后直接改就是
			while(temp != null){
   
				if(i == (index - 1)){
   
					break;
				}
				i++;
				temp = temp.next;
			}
			var f = new Node(newData);
			temp.next.data = f.data;
		};
		//删除
		this.del = function(index){
   
			//找到之后直接删就是。。。
			var temp = head.next;
			var i = 0;
			//先找到它,找到之后直接改就是
			while(temp != null){
   
				if(i == (index - 1)){
   
					break;
				}
				i++;
				temp = temp
评论 59
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值