javascript第二周知识点

261 阅读15分钟

一:数据类型转换

1:显式转换:程序员主动调用函数完成的类型的转换:

1、转字符串

a、xx.toString(); //xx不能是undefined和null,报错,两者不能使用.去操作
b、String(xx); //万能的,完全等效于隐式转换,但还不如+""
一般来说两个都不用,页面上获取到的数据都是字符串

2、转数字

a、字符串转数字:parseInt/Float(str);
从左向右,依次读取每个字符,碰到非数字字符就停止转换,如果一开始就不认识,则为NaN
parseInt不认识小数点,parseFloat认识第一个小数点
b、Number(xx); //万能的,完全等效于隐式转换,但还不如-0 *1 /1 %1

3、转布尔

Boolean(xx);//万能的,但还不如!!x
只有6个为false:0,"",undefined,null,NaN,false,其余都为true
在某些地方会自动带有此方法:分支条件;循环条件

2:隐式转换:一般都出现在运算符和表达式中

二:运算符和表达式:

1、算术运算符:+ - * / %

具有隐式转换:默认转为数字,再运算
特殊:a、+运算,只要碰上一个字符串,两边都会转为字符串,再拼接
b、- * / %,只要是纯数字组成字符串,也可以转为数字

2、比较/关系运算符:> < >= <= == != === !==

1、返回的结果:布尔值:true、false
具有隐式转换:默认一切都转为数字,再比较大小
特殊:a、如果参与比较【两个都是字符串】,按位pk每个字符的十六进制unicode号(十进制ASCII码)
0-9<A-Z<a-z<汉字
汉字第一个字:一:4e00(ascii码:19968)
最后一个字:龥:9fa5(ascii码:40869)
b、NaN,参与任何比较运算结果都为false,解决:!isNaN(x)
x是一个数字,结果true
x是一个NaN,结果就为false
c、undefined==null;
问题:null==undefined结果为true,区分不开undefined和null
解决:全等===:数值相同 并且 数据类型也要相同,即不再带有隐式转换 2、!==:不带隐式转换的不等比较

3、逻辑运算符:

a、&&:全部条件都为true,结果才为true;只要有一个为false,结果就为false
b、||:全部条件都为false,结果才为false;只要有一个为true,结果就为true
c、 !:颠倒bool值
d、特殊:短路逻辑:只要前一个条件已经可以得出最终结论,则后续条件不会再执行
1、&&:如果前一个条件满足,则后一个操作才执行,如果前一个条件不满足,则后一个操作不执行
实现了一个【简单】的分支:目的:简化if(){},操作只能用一句话
语法:条件&&(操作)
b、||:两个值中二选一 -解决浏览器兼容问题

案例
btn.onclick=function(e){
e=e||window.event;//解决浏览器的兼容性问题:
 //e->undefined->false
console.log(e.screenX);
}

4、位运算:

左移:m<<n,读作m左移了n位,m*2的n次方 - 缺点:底数只能是2
右移:m>>n,读作m右移了n位,m/2的n次方 - 缺点:底数只能是2

5、赋值运算:+= -= *= /= %= ++ --

一句话完成了两个操作,先运算再赋值回去 ,比如:i++ => i+=1 => i=i+1;
a、递增 vs 累加
递增:i++,每次只能加1
累加:i+=n,每次加几由我们自己决定
b、笔试题:++i 和 i++ 的区别?
1、单独使用时,放前放后无所谓都一样
2、如果参与了别的表达式,变量中的值都会+1
前++,返回的是加了之后的新值
后++,返回的是加了之前的旧值

案例1
var a=2;//7
var b=a++ + ++a + a++ + ++a + a++;
      2      4      4      6      6
//			console.log(b);
//			console.log(a);

案例2
var a=2;
var b=++a + ++a + a++ + a++ + ++a + a++ + ++a;
//     3      4      4      5      7      7      9
console.log(b);//39
console.log(a);//9

6、三目运算

如何使用:
1、条件?操作1:默认操作;
2、条件1?操作1:条件2?操作2:条件3?操作3:默认操作;
特殊:1、只能完成【简单】的分支 - 操作只能有一句话;2、默认操作不能省略 - 会报错

三:自定义函数:方法,一段提前被定义好的,可以反复使用的代码段

1、如何使用

a、创建/定义/声明函数&返回结果:2种方式

1、*声明方式:用function关键字进行声明,只有变量、常量、函数具有声明方式。

function 函数名(形参,...){
	函数体
	return 返回值;
}

2、直接量方式:

var 函数名=function(形参,...){
	 函数体
	 return 返回值;
}	

函数名其实也是一个变量名

b、调用函数&接住结果

var result=函数名(实参,...);

注意:return后面跟着一个数据,可以将数据返回到全局作用域中,但是仅负责返回,不负责保存,所以我们需要自己创建一个变量接住函数调用的结果
return只能写一次,而且最好写在函数体的后面

2、作用域:2个

a、全局作用域:全局变量 和 全局函数,在任何位置都可以访问/使用
b、函数/局部作用域:局部变量 和 局部函数,只能在当前函数调用时内部可用
有了作用域才有变量的使用规则:优先使用自己的,自己没有找全局,全局都没有报错
c、建议:千万不要对未声明的变量直接赋值,导致全局污染
d、哪些属于局部变量:直接在函数作用域中创建的变量;形参

案例1
//全局污染
function f1(){
a=100;
console.log(a);//100
}
f1();	
console.log(a);//100

案例2
//修改全局
var a=1;
function f1(){
a=100;
console.log(a);//100
}
f1();	
console.log(a);//1

3、声明提前

a、规则:在程序执行之前,悄悄将var声明的变量和function声明的函数集中提前到当前作用域的顶部,但是赋值留在原地,变量比函数更轻
b、笔试题:如果看到先试用后创建,多半都是考声明提前

                        //案例1
			var a=10;
			function f1(a,b,c){
				console.log(a);//undefined
				var a=20;
				console.log(a);//20
			}
			f1();
			console.log(a);//10

			// 案例2
			function fn(){
				console.log(1);
			}
			fn();//2
			function fn(){
				console.log(2);
			}
			fn();//2
			var fn=100;
			fn();//报错:fn不是一个方法

			// 案例3
			var fn=function(){console.log(1)};
			fn();//1
			var fn=100;
			fn();//报错
			var fn=function(){console.log(2)};
			function fn(){console.log(3)};
			fn();//不执行

			// 案例4
			function fn(){
				console.log(1);
			}
			fn();//1
			var fn=100;
			var fn=function(){
				console.log(2);
			}
			fn();//2

4、按值传递:两个变量之间进行赋值

1、如果传递的是原始类型的值:两个变量之间赋值,做操作,互不影响的 - 其实是复制了一个副本给对方
2、如果传递的是引用类型的对象:Array、Function
两个变量之间赋值,做操作,是会相互影响的 - 因为两个用的是同一个地址值

四、预定义的全局函数:可以直接在任何位置使用的函数:

1、编码和解码

编码:var code=encodeURIComponent("str");
解码:var 原文=decodeURIComponent(code);

2、isFinite(num):判断num是不是在有效范围之内

三种情况会为false:分母为0,NaN,Infinity

3、重要的:parseInt/Float()、eval()、isNaN()

五:分支结构:根据条件的不同,执行不同的操作

switch...case结构

语法:
	  switch(变量/表达式){
		case1:
		操作1;
		break;
		case2:
		操作2;
		break;
		default:
		默认操作;
	  }

注意:
1、默认只要满足一条路,会把后面所有的操作全都做完,解决:break:一般放在操作的后面,但是:a、最后default不需要加break, b、如果连续的多个操作是一样的效果,也可以省略中间部分
2、不带有隐式转换
3、default可以省略不写

六:循环结构:反复执行 相同 或 相似的操作

1、while循环:

语法:        var 循环变量=几;
	      while(循环条件){
		循环体;
		变量变化;
	      }

2、do...while循环:

语法:        var 循环变量=几;
	      do{
		循环体;
		变量变化;
	      }while(循环条件)

3、面试题:while 和 do...while的区别?

只看第一次,如果第一次大家都满足条件,两者没有区别
如果第一次大家都不满足条件,while一次都不会执行,而do...while至少会执行一次

4、for循环:

        for(var 循环变量=几;循环条件;变量变化){
		循环体;
	}

5、循环终止语句:

break - 退出整个循环
continue - 退出本次循环

七:数组:一个变量可以保存多个数据

1、创建:2种方式

a、直接量:var arr=[值1,....];
b、构造函数:var arr=new Array(值1,....);
//缺陷:面试中:new Array(3);设置一个长度为3的空数组

2、访问:

获取:arr[i]; - 特殊:下标越界:得到undefined
添加/替换:arr[i]=新值; - 特殊:下标越界:得到稀疏数组

3、3大不限制:

不限制长度、类型、下标越界

4、length的三个固定套路:

获取倒数第n个元素:arr[arr.length-n];
向末尾添加元素:arr[arr.length]=新值
缩容:arr.length-=n;

5、遍历数组:

                for(var i=0;i<arr.length;i++){
			arr[i];//当前次元素
		}

6、特殊点:如果要释放一个引用类型:需将每个变量都要释放才能真的释放干净

7、索引数组:下标都是数字组成的数组 - 默认

8、关联(hash)数组:下标是可以自定义的数组

a、创建:2步

1、创建一个空数组:var arr=[];
2、添加自定义下标并且赋值:arr["自定义"]=值;

b、访问:arr["自定义下标"];

c、遍历

问题:不能使用for循环,因为length失效了,关联数组永远为0,而且下标也在是一个数字
解决:for in循环:(不光可以遍历关联数组,也可以遍历索引数组)

                            语法:for(var i in 数组名){
				 数组名[i]
			      }

注意:JS中除了undefined和null不是一个对象,万物皆对象,而且一切对象的底层都是hash数组

9、二维数组:数组中的值再次引用了一个数组

何时使用:在一个数组内在此细分内容

a、创建:

var arr=[ [ ],[ ],[ ] ];

b、访问:arr[r][c];

特殊:面试中:
列下标越界:返回undefined
行下标越界:报错:undefined不能使用[]

c、遍历二维数组:必然需要两个循环嵌套:外层循环控制行,内层循环控制列

                        公式
                        for(var r=0;r<arr.length;r++){
				for(var c=0;c<arr[r].length;c++){
					console.log(arr[r][c]);
				}
			}

八 :数组的API:函数,但是只有数组可以使用的方法

1、数组 转为 字符串:(不会修改原数组)

var str=arr.join("自定义连接符");

特殊:
a、如果没有传入实参,则和toString/String,完全一样,默认由,分割
b、固定套路:2个
1、笔试题:提供一个数组给你,让你无缝拼接数组里面的内容变为一个字符串

案例
var arr=["h","e","l","l","o"," ","w","o","r","l","d"];
var str=arr.join("")
console.log(str);//"hello world";

2、开发中:将数组中的数据拼接为页面上的元素:初级版数据渲染

案例
var cities=["北京","南京","西京","东京","重庆"];
var str="<option>"+cities.join("</option><option>")+"</option>";
sel.innerHTML=str;  //innerHTML可以识别标签

2、拼接数组:添加元素到的末尾的新方式(不会修改原数组)

var newArr=arr.concat(值1,arr1...);

特殊:
a、此方法不修改原数组,只会返回一个新数组
b、此方法传参支持数组参数,并且会悄悄的打散这个数组,单独传入

3、截取子数组:从starti(i指下标)位置截取到endi+1位置的元素,组成一个新数组(不会修改原数组)

var subArr=arr.slice(starti,endi+1)

特殊:
a、此方法不修改原数组,只会返回一个新数组
b、含头不含尾
c、第二实参可以省略:从starti截到末尾
第一实参也可以省略:从头截到尾
d、支持负数参数,-1代表倒数第一个

4、删除、插入、替换:(会修改原数组)

删除:var dels=arr.splice(starti,n);//从starti开始删除n个

特殊:此方法其实也有返回值,所有删除的元素组成的一个新数组

插入:arr.splice(starti,0,值1,...);//从starti开始删除0个,插入了新元素

特殊:原来starti位置的元素以及后续元素都会被向后移动

替换:var dels=arr.splice(starti,n,值1,...);

特殊:插入的个数和删除的个数可以随意

5、翻转数组:arr.reverse();(会修改原数组)

6、排序:两种方式:

a、笔试题:冒泡排序:把数组中的每一个数字取出来,前一个和后一个进行比较,如果前一个>后一个,两者就要交换位置:

                案例:
			var arr=[13,25,4,3675,12,23,3,215,2,1,42,4,65,473,2431,123];
			for(var j=0;j<arr.length-1;j++){
				for(var i=0;i<arr.length-(j+1);i++){
					if(arr[i]>arr[i+1]){
						var m=arr[i];
						arr[i]=arr[i+1];
						arr[i+1]=m;
					}
				}
			}	
			console.log(arr);

b、正式开发中:数组API提供的排序 arr.sort();

特殊:1、默认按照字符串按位PK每个字符的unicode号排序
2、按照数字排序:

arr.sort(function(a,b){//a是后一个数,b是前一个数
	return a-b;
})

3、降序排列:

arr.sort(function(a,b){
	return b-a;
})

注意:JS中只有数组可以排序,以后我们见到网页上任何具有排序功能的案例,底层一定都是一个数组

7、栈和队列:4个API:添加元素和删除元素的新方式

a、栈:一端封闭,只能从另一端进出的操作

开头进:arr.unshift(值1,...);
开头出:var first=arr.shift();//一次只能删掉一个,并且会返回删除的元素
缺点:每一次进出都会修改其他人的下标
结尾进:arr.push(值1,...);
结尾出:var last=arr.pop();//一次只能删掉一个,并且会返回删除的元素
优点:不会影响到其他元素的下标

b、 队列:只能从一端进入,另一端出:

开头进:arr.unshift(值1,...);
结尾出:var last=arr.pop();//一次只能删掉一个,并且会返回删除的元素
结尾进:arr.push(值1,...);
开头出:var first=arr.shift();//一次只能删掉一个,并且会返回删除的元素

8、实现:二级联动:4个重点

1、必须使用二维数组,而且二维数组的数据顺序一定要和一级的对应上
2、select专属事件:select.onchange=function():状态改变事件:选中项发生改变才会触发
3、select具有一个属性:this.selectedIndex;获取选中项的下标 - 只有select不需要自定义下标
4、其实绑定事件的部分就是函数名,也可以拿来调用 select.onchange();

案例
                    <script type="text/javascript">
			var cities=["-请选择-","北京","南京","西京","东京","重庆"];
			var qx=[
				["-请选择-"],
				["-请选择-","北京1","北京2","北京3","北京4"],
				["-请选择-","南京1","南京2","南京3","南京4"],
				["-请选择-","西京1","西京2","西京3","西京4"],
				["-请选择-","东京1","东京2","东京3","东京4"],
				["-请选择-","重庆1","重庆2","重庆3","重庆4"],
			]	
			sel1.innerHTML="<option>"+cities.join("</option><option>")+"</option>";
			sel1.onchange=function(){
				var i=this.selectedIndex;
				sel2.innerHTML="<option>"+qx[i].join("</option><option>")+"</option>";
			}
			sel1.onchange();	
		</script>

九:String的概念:字符串,多个字符组成的只读字符数组

1、为什么字符串也可以叫数组呢?

和数组有共同点:a、支持下标 - 获取某个字符;b、支持length - 字符的长度;c、遍历;d、数组不修改原数组的API,字符串也可以使用(concat、slice)
不同点:数组修改原数组的API,字符串都不可以使用,但是字符串也有很多属于自己的API

2、只读:字符串中的所有的API都不会修改原字符串,只会返回新字符串

3、引用类型的对象:11个

String(字符串) Number(数字) Boolean(布尔) - 具有包装类型
Array(数组) Function(函数) Math(数学) Date(日期) RegExp(正则) Error(错误) Object(面向对象)
Global - 全局对象:在浏览器端被window对象给代替了:window对象可以省略不写出来
包装类型:将原始类型的值变为一个引用类型的对象
1、为什么undefined和null不能使用.:不具有包装类型,没有任何的属性和方法

十:String API

1、转字符串:\

作用:3个

a、字符串中如果出现了和字符串冲突的符号,可用\将其转义为原文
" "
b、特殊功能: 换行:\n ;制表符:\t
c、可以书写unicode号 表示一个字
\uXXXX 汉字的第一个字:4e00 ;汉字的最后一个字:9fa5

2、转换大小写:统一的转为大写或小写,再比较,忽略大小写: 验证码

大写:var newStr=str.toUpperCase();

小写:var newStr=str.toLowerCase();

3、原文与ascii码的转换

获取字符串中指定位置的字符的ascii码

var ascii=str.charCodeAt(i);

通过ascii码转回原文

var 原文=String.fromCharCode(ascii);

案例:随机验证码
                <script type="text/javascript">
			var arr=[];//空数组:放着我们可能出现的字符
			for(var i=48;i<=52;i++){
				arr.push(String.fromCharCode(i));
			}
			for(var i=65;i<=90;i++){
				arr.push(String.fromCharCode(i));
			}
			for(var i=97;i<=122;i++){
				arr.push(String.fromCharCode(i));
			}
			for(var i=19968;i<=40869;i++){
				arr.push(String.fromCharCode(i));
			}
			var code="";
			while(code.length<4){
				console.log(1);
				var r=parseInt(Math.random()*(arr.length));
				if(code.indexOf(arr[r])==-1){
					code+=arr[r]
				}
			}
			var user=prompt("请输入验证码"+code);
			if(user.toUpperCase()==code.toUpperCase()){
				document.write("<h1 style='color:green;'>验证通过</h1>")
			}else{
				document.write("<h1 style='color:red;'>验证失败</h1>")
			}	
		</script>

4、检索字符串:检查索引/下标:从starti位置开始找右侧的第一个关键字的下标

var i=str/arr.indexOf("关键字",starti);

作用:判断有没有
特殊:a、starti可以省略,如果省略则从0开始
b、返回值:找到了,返回第一个字符的下标;没找到,返回-1
c、数组也可以使用此方法
d、笔试题:找到所有关键字的位置

                                案例
                               var str="no zuo no die no can no bibi";
				var i=-1;
				while((i=str.indexOf("no",i+1))!=-1){
					console.log("找到了:"+i);
				}

5、拼接字符串:var newStr=str.concat(str1,str2...) 还不如 +运算

6、截取字符串:3个

a、var subStr=str/arr.slice(starti,endi+1);

b、var subStr=str.substring(starti,endi+1);

//不支持负数参数

c、var subStr=str.substr(starti,n);

//截取的个数,不必考虑含头不含尾

7、替换字符串:

var newStr=str.replace("关键字"/正则表达式,"新内容");

8、切割/分割字符串:作用:str 转换为arr

var arr=str.split("自定义切割符");

特殊:
1、切割符可以自定义,切割过后返回一个数组,数组中不再包含切割符
2、如果传入的切割符是一个"",每一个字符都会被切开

十一:其他知识点

1、 计算时会带有舍入误差:

解决:var str=num.toFixed(保留小数位数); - 按小数位四舍五入,但是返回的会是一个字符串

2、获取第一个字的ascii码:

var ascii=str.charCodeAt(0);

3、定时器

a、开启定时器:

                timer=setInterval(function(){
			操作
		},间隔毫秒数)

b、关闭定时器:

clearInterval(timer);

4、鼠标移入/移出

鼠标移入:onmouseover

鼠标移出:onmouseout

案例:简单的轮播
                <div id="carousel" class="carousel">
			<img src="img/1.jpg"/>
			<button><</button>
			<button>></button>
		</div>	
		<script type="text/javascript">
			var srcs=["img/1.jpg","img/2.jpg","img/3.jpg"],
			btns=document.getElementsByTagName("button"),
			img=document.getElementsByTagName("img")[0];
			
			for(var i=0;i<btns.length;i++){
				btns[i].onclick=function(){
					if(this.innerText==">"){
						var first=srcs.shift();
						srcs.push(first);
						img.src=srcs[0];
					}else{
						var last=srcs.pop();
						srcs.unshift(last);
						img.src=srcs[0];
					}
				}
			}
			timer=setInterval(function(){
				var first=srcs.shift();
				srcs.push(first);
				img.src=srcs[0];
			},1000);
			carousel.onmouseover=function(){//鼠标移入
				clearInterval(timer);
			}
			carousel.onmouseout=function(){//鼠标移除
				timer=setInterval(function(){
					var first=srcs.shift();
					srcs.push(first);
					img.src=srcs[0];
				},1000);
			}	
		</script>
案例:复杂的轮播(未封装)
<div id="carousel" class="carousel">
			<div class="carousel_img">
				<img class="active" src="img/1.jpg"/>
				<img src="img/2.jpg"/>
				<img src="img/3.jpg"/>
			</div>
			<img src="img/3.jpg"/>
			<button><</button>
			<button>></button>
			<ul>
				<li dy="0" class="active"></li>
				<li dy="1"></li>
				<li dy="2"></li>
			</ul>
		</div>
		
		<script type="text/javascript">
			var btns=document.getElementsByTagName("button"),
			imgs=document.getElementsByTagName("img"),//[img,img,img,img]
			lis=document.getElementsByTagName("li"),//[li,li,li]
			j=0;
			for(var i in btns){
				btns[i].onclick=function(){
					if(this.innerText==">"){
						j++;
						j==lis.length&&(j=0);
						
						for(var i=0;i<lis.length;i++){
							lis[i].className="";
							imgs[i].className="";
						}
						
						imgs[j].className="active";
						lis[j].className="active";
					}else{
						j--;
						j==-1&&(j=lis.length-1);
						
						for(var i=0;i<lis.length;i++){
							lis[i].className="";
							imgs[i].className="";
						}
						
						imgs[j].className="active";
						lis[j].className="active";
						
					}
				}
			}
			
			for(var i in lis){
				lis[i].onclick=function(){
					j=this.getAttribute("dy");//修改全局
					
					for(var i=0;i<lis.length;i++){
						lis[i].className="";
						imgs[i].className="";
					}
						
					imgs[j].className="active";
					lis[j].className="active";
				}
			}
			
			timer=setInterval(function(){
				j++;
				j==lis.length&&(j=0);
						
				for(var i=0;i<lis.length;i++){
					lis[i].className="";
					imgs[i].className="";
				}
						
				imgs[j].className="active";
				lis[j].className="active";
			},1000)
			
			carousel.onmouseover=function(){
				clearInterval(timer);
			}
			
			carousel.onmouseout=function(){
				timer=setInterval(function(){
					j++;
					j==lis.length&&(j=0);
							
					for(var i=0;i<lis.length;i++){
						lis[i].className="";
						imgs[i].className="";
					}
							
					imgs[j].className="active";
					lis[j].className="active";
				},1000)
			}
		</script>
案例:复杂的轮播(封装版)
                <script type="text/javascript">
			var btns = document.getElementsByTagName("button"),
				imgs = document.getElementsByTagName("img"), //[img,img,img,img]
				lis = document.getElementsByTagName("li"), //[li,li,li]
				j = 0;
			for(var i in btns) {
				btns[i].onclick = function() {
					if(this.innerText == ">") {
						animate(1)
					} else {
						animate(-1)
					}
				}
			}
			for(var i in lis) {
				lis[i].onclick = function() {
					animate(0, this)
				}
			}
			timer = setInterval(function() {
				animate(1);
			}, 1000)
			carousel.onmouseover = function() {
				clearInterval(timer);
			}
			carousel.onmouseout = function() {
				timer = setInterval(function() {
					animate(1);
				}, 1000)
			}

			function animate(num, li) {
				if(num) {
					j += num; //2
					if(j == lis.length) {
						j = 0
					} else if(j == -1) {
						j = lis.length - 1;
					}
				} else {
					j = parseInt(li.getAttribute("dy"));
				}
				for(var i = 0; i < lis.length; i++) {
					lis[i].className = "";
					imgs[i].className = "";
				}
				imgs[j].className = "active";
				lis[j].className = "active";
			}
			

		</script>

5、创建元素并且渲染页面

a、创建空标签

var elem=document.createElement("标签名");

b、设置必要的属性或事件

elem.属性名="属性值";
elem.on事件名=function(){函数体} - 事件都可以在创建时提前绑定上

c、创建好的元素渲染到DOM树上

父元素.appendChild(elem);

案例:根据一个字符串渲染出表格
                <script type="text/javascript">
			//从数据库获取而来的
			var str="李5%刺客%10#王二麻子%奶妈%90";
			var table=document.createElement("table");
			var arr=["姓名","职业","剩余生命"];
			var tr=document.createElement("tr");
			table.appendChild(tr);
			var peoples=str.split("#");
			for(var i=0;i<peoples.length;i++){
				var tr=document.createElement("tr");
				var people=peoples[i].split("%");
				for(var j=0;j<people.length;j++){
					var td=document.createElement("td");
					td.innerHTML=people[j];
					tr.appendChild(td);
				}
				table.appendChild(tr);
			}
			bd.appendChild(table);
		</script>