一边学习前端,一边通过博客的形式自己总结一些东西,当然也希望帮助一些和我一样开始学前端的小伙伴。
如果出现错误,请在评论中指出,我也好自己纠正自己的错误
author: thomaszhou
- 目录
- [1. 基本语法]
- [2. 排序sort()默认和自定义]
- [3. js一些简单提高性能实例]
- [4. this的理解和应用]
- [5. 点击事件的调试错误]
- [6. js可以为所有标签添加任何自定义属性]
- [7. 数据类型和类型转换]
- [8. 函数传参(未完成)]
- [9. 作用域]
- [10. 定时器]
- [11. 日期对象]
- [12. 字符串方法]
- [13. 数组方法]
- json,对象
基本语法-1
- javascript分别提供内置函数 parseInt()和parseFloat(),转换为数字 注:如果被转换的字符串,同时又数字和字符构成,那么parseInt会一直定位数字,直到出现非字符。 所以"10abc" 会被转换为 10
- 使用内置函数Boolean() 转换为Boolean值 当转换字符串时:非空即为true 当转换数字时:非0即为true 当转换对象时:非null即为true
- Number和parseInt一样,都可以用来进行数字的转换 区别在于,当转换的内容包含非数字的时候,Number() 会返回NaN(Not a Number) parseInt() 要看情况,如果以数字开头,就会返回开头的合法数字部分,如果以非数字开头,则返回NaN
- getElementsByTagName和getElementsById区别!
- 返回值不同:getElementsByTagName是选择标签的类型。返回的是一个一堆的标签,也就是一个集合(不是数组,但是拥有和数组一样的方法).getElementsById返回的是一个标签
var oLi = oDiv.getElementsByTagName('li');//oLi其实是一个集合for(var i = 0; i < arrUrl.length; i++) { // 如果oLi[i]后的 事件 或者 属性 是确定的,可以用.来写 oLi[i].index = i; oLi[i].onclick = fn1; 重要!!!!!!!!!!!!! // 如果通过函数参数来改变oLi[i]的事件 或者 属性,就用oLi[i][evt]来写,例如evt就是参数, //oLi[i]的点击事件还可以如下写: // var evt = onclick; // oLi[i][evt] = fn1; }复制代码
- 写法不同:getElementsById只能写成document.getElementsById,但是getElementsByTagName前面不止可以写ducument还可以写别的,如下:
(1) var oUl = document.getElementsByTagName('ul')[0]; /*如何用getElementsByTagName来找一个标签,就加个[0]*/ var oli = oUl.document.getElementsByTagName('li'); /*选择的是ul标签下的所有li标签*/(2)如果查找的标签只有一个,可以用id,class,也可以用TagName,但是如果用TagName就要加上一个[0] var oImag = oDiv.getElementsByTagName('img')[0];复制代码
- 静态方法和动态方法: getElementsByTagName是动态方法:即使前面写了语句获取某个类型标签返回为0,只要后面有添加该类型标签,就可以直接访问,不需要再来一次查找。 但是getElementsById如果前面返回值为0,后面如何添加了,也需要再次重复操作一次查找才可以
aSpan[i].style.left
是修改left值,如果遇到要将整个样式进行修改,也就是新写一个样式,将之前通过js对标签style进行修改的那些样式的全部进行一个替换,可以考虑用aSpan[i].style.cssText
(记住:是将js操作修改的样式全部替换成一个新的,标签本身通过css设置的样式不变)- 数组:中可以包含不同的数据类型: 例如:数子、字符串、数组、路径(例如存放图片地址)等 7.函数:函数的参数如果是字符串,就像是一个字符串数组
function fn1(args) { console.log(args[0]); console.log(typeof args[0]);//string } fn1('qwe');//q fn1(234);//undefined ----typeof undefined也是undefined复制代码
排序sort()默认和自定义-2
- sort()默认升序,但是只适用于0~9,因为:
var array1 = [0,1,5,10,15]; array1.sort();//结果为:0,1,10,15,5---->完全不符合复制代码
原因:是这个函数在进行排序的过程影响其值的根本原因。(其实,在使用sort()进行排序的时候会调用toString()函数将其值转换成字符串在进行比较,是按ASCII进行比较的)
解决方法:自定义sort()
compare(a,b)返回的值小于0:那么a就小于b,也就是说a排在了b的前面
compare(a,b)返回的值大于0: 那么a就大于b,也就是说a排在了b的后面
compare(a,b)返回的值等于0:那么a就等于b,也就是说a和b的位置保持不变
var Array1 = [0,1,5,10,15];Array1.sort(function(a,b){ return b-a;});结果是:15,10,5,1,0复制代码
解释:a,b表示数组中的任意两个元素,若return > 0 b前a后;reutrn < 0 a前b后;a=b时存在浏览器兼容,简化一下:a-b输出从小到大排序,b-a输出从大到小排序。
var arr1 = [0,19,5,10,15],//数字 arr2 = ['500', '70', '9'];//数字形式的字符串 arr3 = [500, '70', '9'];//数字和数字形式的字符串混合 function compare(a, b) { return a-b;// return (a < b)? -1: (a > b)? 1: 0;//利用相减的方法,可以对字符串形式的数字和纯数字都有效,而不需要专程纯数字在比较!!!!! } console.log(arr1.sort());//[0, 10, 15, 19, 5] console.log(arr1.sort(compare));//[0, 5, 10, 15, 19] console.log(arr1.sort(compare)[1]);//5 console.log(arr2.sort());//["500", "70", "9"] console.log(arr2.sort(compare));//["9", "70", "500"] console.log(arr3.sort());//[500, "70", "9"] console.log(arr3.sort(compare));//["9", "70", 500] //得出,对于数字和数字类型的字符串,用了compare函数都是按照数字的大小排序!!!!!!复制代码
- 针对(单个属性)的对象数组排序
var obj1 = [ { 'name': 'john', 'age': 13}, { 'name': 'aohn', 'age': 93}, { 'name': 'bohn', 'age': 53} ], obj2 = [//age的值改为字符形式 { 'name': 'john', 'age': '13'}, { 'name': 'aohn', 'age': '93'}, { 'name': 'bohn', 'age': '53'} ] //对象数组排列 function objectSort(args) { var sortOrder = 1; if (args[0] === '-') { sortOrder = -1; args = args.substr(1); console.log(args); } return function (a, b) { var result = a[args] - b[args]; return result * sortOrder; } } console.log(obj1.sort(objectSort('age'))); console.log(obj2.sort(objectSort('age')));//结果一样//正序:正序和逆序同时显示就出错,只有当只有一个的时候就没问题??? console.log(obj1.sort(objectSort('-age')));//逆序:正序和逆序同时显示就出错,只有当只有一个的时候就没问题???复制代码
- 针对(多个属性)的对象数组排序
复制代码
- 利用sort将数组内的元素弄成随机排列
// 数字数组随机排列:让数组的数字大小随机排列 function randomSort(a, b) { return Math.random() - 0.5//因为默认random是0~1,减去0.5就是-0.5~0.5,正负为一半概率 } console.log(arr1.sort(randomSort));// ["blue", "hum", "zelu"]默认就是字符串排序复制代码
性能方面-3:
例1 for(var i = 0; i < arr.length ; i++) /*里面的arr.length会每次循环都计算一次长度,这样影响性能!*/修改为: var num = arr.length; for(var i = 0; i < num ; i++)复制代码
例2 for( var i=0; i<6000; i++ ){ document.body.innerHTML += ''; /*每次循环都需要dom一次,性能不好*/ } /*解决方法:设置一个字符串str,将每次的操作都作用在str上,等循环结束,一次性全部加在document.body.innerHTML中*/ var str = ''; for( var i=0; i<6000; i++ ){ str += '';} } document.body.innerHTML = str;复制代码
例3 下面代码的点击事件执行点击都会生成4个div,但是每次点击都会生成4个,如何限制按钮的功能只保证第一次有效 var arr1 = ['qwe','qwe','sdf','qwe']; for(var i = 0; i < arr1.length;i++){ document.body.innerHTML += ''+arr1[i]+''; /*如果是 = ,那就是修改,如果是 += ,那就是不断相加*/ }方法:写一个判断(创建变量onoff,初始为true,点击事件结束后赋值为false,此时通过if判断无法执行 点击事件) var arr1 = ['qwe','qwe','sdf','qwe']; oBtn1.onclick = function(){ onoff = true; if(onoff){ for(var i = 0; i < arr1.length;i++){ document.body.innerHTML += ''+arr1[i]+''; } onoff=false;}}复制代码
- 注:标签的背景属性是不可以用===来判断的,因为背景后面跟着颜色(多种表达方式)、url等等。一般牵扯到判断,尽量用变量 如何实现多个div的背景图片的点击事件(点击一次换一张图片,再点击一次,恢复原来的图片),通过变量判断每个点击事件(点击一次后)
this的理解和应用-4
this 指的是调用当前方法(函数)的那个对象
- 判断this的指向
- 直接在中写一个alert(this);这个this是window
- 只要见到单独的fn1(),那么this就是window。这个this表达的是window不是obtn1,因为是windw调用的,不是oBtn1调用的
举例: function fn1(){alert(this);}// 只要见到单独的fn1(),那么this就是window,但是如果是oBtn1.onclick = fn1;//那么this指的就是oBtn1(谁调用的函数,this就指向谁!) eg1: fn1(); this ---> window eg2: oBtn1.onclick = fn1; this -----> oBtn1 eg3: oBtn1.onclick = function(){ fn1(); } this ---> window复制代码
题外话!(点击事件的函数赋值为什么不能oBtn1.onclick = fn1(),这样写为什么是错的❌?)
- this应用:
//this ---> aBtn 的三种写法//第一种 var aBtn = document.getElementsByTagName('input'); for(var i = 0;i < aBtn.length;i++){ aBtn[i].onclick = function() { this.style.background = 'red'; } }//第二种 var aBtn = document.getElementsByTagName('input'); that = null; for(var i = 0;i < aBtn.length;i++){ aBtn[i].onclick = function() { that = this; fn1(); } } function fn1(){ that.style.background = 'red'; }//第三种 var aBtn = document.getElementsByTagName('input'); for(var i = 0;i < aBtn.length;i++) { aBtn[i].onclick = fn1; } function fn1(){ this.style.background = 'red'; }复制代码
点击事件的调试错误-5
var aBtn = document.getElementsByTagName('input'); for(var i = 0;i < aBtn.length;i++){ aBtn[i].onclick = function(){ that = this; fn1(); } /*由于下一句代码呆滞程序出错,加载页面没有出错,但是点击时出错,且错误定位在209行, 不需要用alert()调试错误.错误只发生在点击后,也就是说是函数点击事件错误或者是调用点击事件时发生错误, 本例子是下一句发生错误,也就是调用点击事件的时候发生错误,多次定义同一点击事件!*/ // aBtn[i].onclick = fn1; ❌的源头 } function fn1(){ that.style.background = '#2a426c'; }复制代码
js可以为所有标签添加任何自定义属性-6
- 例子1:创建3个li标签,每个li的背景图都是一张图片,即共三个图片,每个图片都写一个点击事件(点击一次变一下背景图片,再点一下就回去前一张图):
document.body.innerHTML = '
方法一的问题:由于是多个图片并行添加点击事件,而onoff是全局变量,如果点击第一个li的图片1,图片变成2,然后再点击第二个li的图片1,此时是执行else语句(图片变成1),但是问题在于此时第二个li的图片就是1,所以点击事件在用户看起来是失灵的!每次换一个li点击,都需要点击两次才可以生效,这就是问题
方法二:同样是利用判断,但是,不是利用一个全局变量,而是利用每个li的自定义属性onOff。每次置为true和false都是对当前li的自定义属性onOff属性操作,这样就不会影响到其他的 li 标签,每个onOff都是仅针对对应的标签
注:
- 给一些标签数组设置自定义属性的时候,会用到for循环,但是给标签数组设置自定义函数的语句要在for循环的开头写好,例如下面第二句代码
aLi[i].onOff = true;
如果写在了按钮事件里面,就会出错!(因为写在里面的话,如果不做一些类似闭包等操作,i的值不是从0-->aLi.length-1,而是总是length-1) - 该方法是通过自定义创建一个仅属于某个标签的属性,但是如果目前的代码中有通过自定义属性来操作的一些别的功能,我们最好把该属性拿来判断,因为如果有现成可以用的,那就用现成的,如果没有,才去创造一个新的
for(var i = 0; i < aLi.length; i++){ aLi[i].onOff = true; //设置自定义属性onOff aLi[i].onclick = function(){ if(this.onOff){ this.style.background = 'url(2.jpg)'; this.onOff = false; } else{ this.style.background = 'url(1.jpg)'; this.onOff=true; }} }复制代码
-
自定义属性---设置索引值index(适用于想建立“匹配”,“对应”关系)
-
例子2:还是三个li,点击每个li时,点击多次依次为A、B、C、D,然后循环,三个li各自独立完成功能
实现方法:创建一个数组
var arr = ['A','B','C','D']
,然后为每个li标签设置一个自定义属性num,初始都为0,在不超过数组arr
的长度,每次点击都num++
以及将li的value值或者innerHTML置为arr[num]
-
例子三:三个button,三个p标签,一个包含字符串的数组,点击button,通过索引值将数组对应的值,对应的对p标签作出value的修改(利用自定义属性创建--索引)
数组也可以包含字符串,图片,路径等等
-
数据类型和类型转换-7
- 任何非空的数据类型,都可以添加自定义属性和自定义方法
- 可以通过
typeof
判断数据类型,例如:typeof n判断n的数据类型 - js的数据类型:数字,字符串,布尔,函数,对象(obj、[]、{}、null),undefine
- 从html上获取到的值,innerHTML和一些属性,都是字符串!!!!!!!!
- 显式类型转换:
- Number()函数:转化为数字,出现空一般情况下转为0(除json外),如果遇到字母或者符号,obj类型,json,undefine直接就是NaN
var a = '100';var b = '000100';var c = '----100';var d = ''; 以及 var d = null;var e = 'true';var f = function(){var a = 777};//转换函数var g = ['4'];//一个值var h = [1,3,5];//多个值var i = json = {};var j ;//undifine//Number(a):字符串直接转换为数字alert(Number(a)+100);// 100+100alert(Number(b));//100alert(Number(c));//NaN 含有符号alert(Number(d));//0alert(Number(e));//true --> 1 false --> 0alert(Number(f));//NaNalert(Number(g));//4alert(Number(h));//NaNalert(Number(i));//json不论是空还是有东西,都是 NaNalert(Number(j));//NaN复制代码
- parseInt()函数:原理是从第一个开始往后找,一旦遇到不是数字的(如果开头是+或者—或者空格是可以的),立马截断,然后把之前读到的数字转换成int型数字。(注:适用于转换一些数字开头的字符串,例如b)
- parseInt(a,10) 表示按照10进制转换,也可以是二进制,十六进制等等。
var a = 'a100';var b = '100px';var c = '000100';var d = '+100';var e = ' 100'; 以及 e = 00000100var f = null;alert(parseInt(a,10));//NaNalert(parseInt(b,10));//100alert(parseInt(c,10));//100alert(parseInt(d,10));//100 认识'+ - = ' 分别是 100 -100 100alert(parseInt(e,10));//100 空格 和 0 自动忽略alert(parseInt(f,10));//NaN复制代码
- parseInt()和parseFloat()的区别
var a = '12.34fff';var b = '12.3.4';alert(parseInt(a));//12alert(parseFloat(a));//12.34alert(parseFloat(b));//12.3 只认识第一个小数点复制代码
//两个转换的值相等,就可以判断为整数 if(parseInt(a) == parseFloat(a)){ alert('a是小数'); }else{ alert('a是整数'); } 6. **隐式类型转换**
隐式类型转换: + 200 + '3' 变成字符串 '2003'
- * / % '200' - 3 变成数字 197++ -- '2'++ 变成数字 3> < 数字的比较是一个数字和一个字符串,那就是默认数子进行比较alert( 10000000 > '9' ); 、 字符串的比较 alert( '10000000' > '9' ); ! 取反 !'asd' true 把右边的任何数据类型转成布尔值== alert('2' == 2) true 只是判断值(=== 是判断 数据类型 和 值 都必须相同)```复制代码
- 转换失败的时候返回NaN。有4个特点:
- NaN在bool型中是 false
- NaN一定是出现非法操作
- NaN是一个数字类型(number),但是它不是一个数字
- 除NaN以外,所有的数据类型的值都是等于本身
- isNaN() 判断某些值是不是数字:
- 是数字,就是false不是数子,就是true**
- isNaN()内部是通过number()函数来判断是不是数字!
var arr = [ '100px', 'abc'-6, [], -98765, 34, -2, 0, '300', , function(){alert(1);}, null,document, [], true, '200px'-30,'23.45元', 5, Number('abc'), function(){ alert(3); }, 'xyz'-90 ];/* 1、找到arr里所有的数字:-98765, 34, -2, 0, 5*/for(var i = 0; i < arr.length; i++){//方法一:把所有数字都找出来 if((typeof arr[i] != 'string')&&(parseFloat(arr[i]) == arr[i])){ console.log(arr[i]); } //方法二:判断是数字,而不是NaN if((typeof arr[i] === 'number')&&(arr[i] === arr[i]))} 复制代码
- charAt(i)把字符串的字符单独拿出来
str = '123';str.charAt(2);//3复制代码
作用域-9
浏览器: “JS解析器过程” 1) JS 的预解析:“找一些东西” :仅 var和function 所有的变量,在正式运行代码之前,都提前赋了一个值:未定义 所有的函数,在正式运行代码之前,都是整个函数块 注:遇到重名的:只留一个(变量和函数重名了,就只留下函数), 多函数的话,函数留最后的那个! 2)逐行解读代码: 表达式:= + - * / % ++ -- ! 参数…… 表达式可以修改预解析的值!注:script 全局变量、全局函数 自上而下 ===> 1 是可以执行的,因为自上而下,上面的东西会存进仓库然后杯使用和读取, 就像一开头会用script引用一些js文件一样 复制代码
var a = 1;function fn1(){ alert(a); // 1 //(作用域链,里面找不到var和函数,就跳到父级,然后找到a=1,所以返回1(由里到外)) a = 2; //找不到a,然后又是作用域链往外面爬,遇到a = 1;然后a =2是将全局a赋值为2}fn1();alert(a); // 2预处理结果为:a = undefined fn1 = function fn1{...}逐行解读:如上注释注: 1. 函数内部找不到变量的声明,就会跳出来找同名的全局变量,如果也没有才会报错!!!!(由里到外),;但是外面不能直接用局部变量(函数内) ** 想要获取函数内的值---解决办法: 方法一: 声明一个全局变量,再函数中的局部变量赋值给全局变量 var str = ''; function fn1(){ var a = '大鸡腿~'; str = a;} 方法二:申明另一个函数,利用参数来传递局部变量 function fn2(){ var a = '9999999克拉钻石23456789'; fn3(a);} fn2(); function fn3(a){ alert(a);}复制代码
例子1:alert(a); // function a (){ alert(4); }var a = 1; alert(a); // 1function a (){ alert(2); }alert(a); // 1var a = 3; alert(a); // 3function a (){ alert(4); }alert(a); // 3 alert( typeof a ); //numbera();报错,因为此时a是变量不是函数解析过程: “JS解析器过程” 1)JS 的预解析: ===> 读取到var a = 1 ==> a = undefined ===> a = function a(){ alert(2); } ===> 读取到var a = 3 ==> a = undefined ===> a = function a (){ alert(4); } ===> 只留函数,函数留最后的那个 所以预解析的结果是:a = function a (){ alert(4); } 注:遇到重名的:只留一个(变量和函数重名了,就只留下函数) 2)逐行解读代码: 由于预解析得出a = function a (){ alert(4); } 按顺序读,第一个alert(a);是返回一个函数,预处理的结果!复制代码
例子2:var a = 1;function fn1(){ alert(a); // undefined var a = 2;}fn1();alert(a); // 1解析过程: “JS解析器过程” 1)JS 的预解析: ===> 读取到var a = 1 ==> a = undefined ===> fn1 = function fn1(){ alert(a); var a = 2;} ===> 只留函数 所以预解析的结果是:fn1 = function fn1(){ alert(a); var a = 2;} 2)逐行解读代码: 解析结果为表达式 函数调用: 1)函数内部预解析(和外部预解析一样!) alert(a); ==> null var a = 2; ==> a=undefined 2)逐行解读代码 alert(a) ==> undefined alert(a); ==> a是全局变量a,不是局部的a,所以是a复制代码
例子3:var a = 1;function fn1(a){ 参数就相当于一个局部变量,就相当于var a;, 但是没有赋值,所以内部js解析器是读取到a=undefine; alert(a); // undefined a = 2;}fn1(); 下面是fn1(a);alert(a); // 1例子4:var a = 1;function fn1(a){ alert(a); // 1 a = 2;}fn1(a);alert(a); // 1复制代码
-
定时器-10
- 函数的返回值 return:返回值
- return可以返回的类型有:数字、字符串、布尔、函数、对象(元素[数组]{}\null)、未定义
- 函数名+括号:fn1() ==> return 后面的值;
- 所有函数默认返回值:未定义;
- return 后面任何代码都不执行了;
a、返回对象alert(fn2()); ----> 显示整个function(b){}(包括注释)function fn2(){return function (b){ alert(a+b); // 嘿嘿,我是注释~};}a、返回对象fn3().onload = function (){document.body.innerHTML = 123;};function fn3(){return window;}b、通过双括号来调用 函数 内的 函数fn2(20)(10); function fn2(a){return function (b){ alert(a+b); // 嘿嘿,我是注释~};}复制代码
- 函数的return小应用
模仿jquery,封装一个 $方法function $( v ){ if( typeof v === 'function' ){ --> 如果v是函数 window.onload = v;} else if ( typeof v === 'string' ) { --> 如果v是字符串 return document.getElementById(v);} else if ( typeof v === 'object' ) { --> 如果v是一个对象,例如this return v;}}$(function(){ --> 直接用$()方法$('btn1').onclick = function(){ $( this ).style.background = 'yellow';};});复制代码
- argument
fn1( 1,2,3 ); // 实参——实际传递的参数// function fn1( a,b,c ){ // 形参——形式上,abc这些名代表123function fn1(){ //arguments => [ 1,2,3 ] —— 实参的集合 alert( arguments ); -->[ 1,2,3 ] alert( arguments.length ); -->3 alert( arguments[arguments.length-1] );像数组一样,通过[]来定位参数}!!! 当函数的参数个数无法确定的时候:用 arguments如下:// alert( sum( 1,2,3 ) ); // 6// alert( sum( 1,2,3,4 ) ); // 10function sum (){var n = 0;for( var i=0; i
- 获取元素样式:要注意三点
-
获取到的是计算机(浏览器)计算后的样式
-
background: url() red …… 复合样式(不要获取)
backgroundColor 单一样式(不要用来做判断)
-
不要获取未设置后的样式:不兼容
-
注:该$方法是上个return小应用里面的自定义方法
- 函数的返回值 return:返回值
alert( getComputedStyle( $('div1') ).width ); IE6 7 8 不兼容 alert( $('div1').currentStyle.width ); 标准浏览器不兼容 例子1:对于以上两个方法的使用,最好用if-else来多方位考虑 if( $('div1').currentStyle ){ //当为标准浏览器时 alert( $('div1').currentStyle.width ); } else { //当为ie 6 7 8时 alert( getComputedStyle( $('div1')).width );// alert( getComputedStyle( $('div1'),1).width ); FF 4.0 之前要加一个参数,任何数字都可以,此处为1 } 例子2:自定义获取元素的属性方法getStyle方便以后调用function getStyle(obj,attr){ return obj.currentStyle?obj.currentStyle[attr]:getComputedStyle(obj)[attr]; } 调用方法: var div2 = document.getElementById('div1') getStyle(div2,'left')) 如果要获取右外边距,不要写成 getStyle( div2, 'margin-right' ) ); 正确写法:alert( getStyle( div2, 'marginRight' ) );复制代码
- 定时器
定时器:时间概念 var timer = setInterval( 函数, 毫秒 ); 重复执行(发动机) clearInterval( timer ); 清除定时器 var timer = setTimeout( 函数, 毫秒 ); 仅执行一次!!一些需要重复操作定时器的操作不要用!!! clearTimeout( timer );复制代码
注:for(var i=0; i<3; i++){ document.title = i; } -->瞬间i = 2javascript的for循环瞬间完成,没有时间根据例子1: 功能:到i加到10自动停止 i = 0; var timer = null; function fn1(){ i++; document.title = i; if( i === 10 ){ clearInterval( timer ); } } timer = setInterval( fn1, 200 );例子2:功能:每秒切换一张图片,循环显示var aBtn = document.getElementsByTagName('input');var arrUrl = [ 'img/1.jpg', 'img/2.jpg', 'img/3.jpg', 'img/4.jpg' ];var num = 0;var timer = null;var oBody = document.body;aBtn[0].onclick = function (){ clearInterval( timer ); //必须先进行clearInterval(),才能按钮的正常 // 如果不先清除,因为多次按第一个按钮就会不断的创建新timer(不会覆盖之前的timer) timer = setInterval(function(){ oBody.style.background = 'url('+ arrUrl[num] +')'; num++; num %= arrUrl.length; }, 1000);};aBtn[1].onclick = function (){ clearInterval( timer );};例子3:这种只需要操作一次定时器的操作,可以考虑用settimeout()功能:2s后显示一张图片,然后3s后再消失window.onload = function (){ var miaov = document.getElementById('miaov'); setTimeout( function(){ miaov.style.display = 'inline-block'; 2s后显示 setTimeout(function(){ 嵌套两个定时器,显示后3s再消失 miaov.style.display = 'none'; }, 3000); }, 2000);};例子4:类似鼠标移到qq头像,就会弹果,见《ex5定时器.html》复制代码
- 回调函数
功能:先右移到500,再往下移动到500 Abtn[3].onclick = function(){ move(Odiv,'left',12,500,function(){ move(Odiv,'top',12,500) ------>回调函数 }) }; 参数 obj:对象 attr:属性 temp:步长 end:终点位置 回调函数endFn,第5个参数 function move(obj,attr,temp,end,endFn){ //判断步长是正还是负,也就是向前还是向后 temp = parseInt(getStyle(obj,attr))end) && (temp>0) || (speed < end) &&(temp<0) ){ //判断是往前还是往后,通过通过传参的temp正负来判断 speed = end; } obj.style[attr]= speed + 'px'; if ( speed == end ) { //可加不可加 clearInterval( obj.timer );// 待left操作结束再执行回调函数,所以放在这个if语句中 endFn && endFn();// 等同于如下语句 /*如果endFn参数不为空,就调用回调函数 if ( endFn ) { endFn(); } */ } },30); }复制代码
日期对象-11
- 系统时间
var mytime = new Date();//获取系统当前时间- 然后通过一些方法获取年,月,日,星期,天,时分秒, var iyear = mytime.getFullYear();//2017 var imonth = mytime.getMonth()+1;//得出来的比真实月份小1,所以要加1 var iday = mytime.getDate();//日 var iWeek = mytime.getDay(); var ihours = mytime.getHours();// alert(ihours); var imin = mytime.getMinutes(); var isec = mytime.getSeconds(); var str = '';// 下面是日期的的一些对照 if( iWeek === 0 ) iWeek = '星期日'; if( iWeek === 1 ) iWeek = '星期一'; if( iWeek === 2 ) iWeek = '星期二'; if( iWeek === 3 ) iWeek = '星期三'; if( iWeek === 4 ) iWeek = '星期四'; if( iWeek === 5 ) iWeek = '星期五'; if( iWeek === 6 ) iWeek = '星期六'; str = iyear+'-'+imonth+'-'+iday+'-'+iWeek+'-'+ihours+':'+onTwo(imin)+':'+onTwo(isec); alert(str)//2017-7-28-星期五-17:23:45 //设置时间: oDate.setDate( oDate.getDate() + 5 );//将天数加5天 // toGMTString() 方法可根据格林威治时间 (GMT) 把 Date 对象转换为字符串,并返回结果。 alert( oDate.toGMTString()); 注:为了更佳合理,如果是1:8:2的时间应该要变成01:08:02,自定义函数onTwo() function onTwo ( n ) { //返回的是一个字符串 return n < 10 ? '0' + n : '' + n;}复制代码
实例1:图片时钟(通过修改img标签的src)![]()
![]()
![]()
![]()
![]()
复制代码
- 倒计时
// 现在的时间点(在变)// 未来的时间点(不变)var iNow = new Date();//法一:数字形式获取时间的毫秒形式 var iNew = new Date( 2017, 12, 23, 0,0,0 );//iNewh获取的是毫秒为单位// 毫秒 -> 秒(向下取整--去掉小数点)var t = Math.floor((iNew - iNow)/1000);//死公式-转换成 天 时 分 秒 的单位,记住// 天:Math.floor(t/86400)// 时:Math.floor(t%86400/3600)// 分:Math.floor(t%86400%3600/60)// 秒:t%60var str = Math.floor(t/86400)+'天'+Math.floor(t%86400/3600)+'时'+Math.floor(t%86400%3600/60)+'分'+t%60+'秒';alert( str );// 法二:数字形式:new Date( 2013,4,1,9,48,12 );//如果要通过某个控件来获取未来的时间,建议用字符串形式,因为可以通过dom操作引入value值// 字符串形式:new Date('June 10,2013 12:12:12');复制代码
实例2:设置一个未来时间,然后显示倒计时 距离:还剩:复制代码
测试一个方法的用时
var startime = +new Date();//+new date() == new Date().valueof()返回当前毫秒数//这里放测试的代码var endtime = +new Date();console.log("耗时为"+(endtime - startime)+'ms');复制代码
//+new Date() 中的+其实相当于.valueOf();// 以下四句console代码都是可以返回当前时间的毫秒数console.log(+new Date);//1512049475622console.log(+new Date());// 1512049475622var s = new Date();console.log(s.valueOf());// 1512049475624console.log(s.getTime());// 1512049475624//以下是返回的字符串形式console.log(s.toLocaleString()); // 2017/11/30 下午9:44:35console.log(s.toLocaleDateString()); // 2017/11/30console.log(s.toLocaleTimeString()); // 下午9:44:35复制代码
字符串方法-12
(1)字符长度var str = 'aaaaa'; alert(str.length); str.length = 1;//但是使其长度为1,无效 alert(str);//还是aaaaa // 头三个方法前面是接一个字符串//第三个方法的前面是接Stringalert( 'miaov'.charAt(2) );//输出:字符串'miaov'第3个的字符不能赋值给charAt()alert( 'miaov'.charCodeAt(2) );//输出字符串'miaov'第3个的字符的ASC编码// String.fromCharCode()是可以通过编码返回对应的字符//这就弹出23383和23443的字符(用,来隔开,可以转换多个)alert( String.fromCharCode(22937, 21619) );//返回22937和 21619编码对应的字符复制代码
(2)alert( str.indexOf('m') );//返回str中查找第一个字符m的位置// 如果第2个值为负数,默认当成0来处理alert( str.indexOf('m', 5) );//从第五个位置开始,返回str中查找第一个字符m的位置 var str = '字符串'; var str1 = '字符串 ';//空格也算字符长度 alert( str.length );//str--3 str1--5(含两空格) alert( str.charAt() );//找字符串的某一个,什么都不写和charAt(0)就是默认第一个, alert(str.charAt(0)); alert( str.charCodeAt() );// 返回字符的计算机储存编码,字的编码是23383 alert( str.charCodeAt(1) ); //参数同charAt一样 // 0~9 48~57 a~z 97~122 A~Z 65~90 alert( String.fromCharCode(23383, 23383) );//字字复制代码
- substring()和slice()-截取字符串函数
var str = 'this is a bag';str.substring(2);//从第2个位置开始截取-is is a bagalert( str.substring(0,2) );//截取0-2位置的字符// 两个都是正数的情况:可以检测两个数大小,自动变成(0,2),就和上一行同等alert( str.substring(2,0) );alert( str.substring(-3, 2) ); // -3 当成0处理alert( str.substring(2, -3) );slice()截取方法和substring()的区别:alert( str.slice( 2, 0 ) ); // 不交换位置,但也没有结果alert( str.slice( -4, -2 ) ); // 负数从后面倒着往前数~复制代码
(4) 字符串比较:第一个字符的编码大小,即charCodeAt()的值 alert( '莫涛' > '杜鹏' );//true alert( 'abbbbb' > 'b' );//false alert( '10000' > '2' );//false 大小写转换: alert( str.toUpperCase() ); // 转成大写 alert( str.toLowerCase() ); // 转成小写复制代码
- str.split()分割函数--可以把字符串变成函数
var str = 'www.baidu.com';//存储的是一个数组形式,然后就可以把arr当作数组来处理(可用数组的方法)alert(str.split('.') ); // [ 'www', 'baidu', 'com' ]var arr = str.split( '.' );// alert( arr[1] );var str1 = 'leo';//如果不放置分割符,就是整个字符为一个数组的元素 alert( typeof str1.split() ); // [ 'leo' ]//如果只写个空字符为分割符,那就是每个字符都分别分割 alert( str1.split('') ); // [ 'l', 'e', 'o' ]var str2 = '百度网页';alert( str2.split('度') );//['百','网页']var str3 = '/www.baidu.com/'; alert( str3.split('/').length );//[ , www.baidu.com, ].第一个和第三个是空格var str4 = '2013-11-29-23-07';//-分割,且只保留前3段alert( str4.split('-', 3) );//['2013','11','29'] 复制代码
- indexOf(),lastIndexOf(),search(),concat()
var str = 'abcsssbc'; console.log(str.indexOf('bc',1));//1 第一次出现的字符串的位置 console.log(str.indexOf('bc',2));//6 第二次出现的字符串的位置// 没找到返回-1 console.log(str.lastIndexOf('bc'))//6 匹配的字符串最后出现的位置 console.log(str.search(/bc/g));//返回于正则表达式查找内容匹配的第一个字符串的位置 console.log(str.concat('aa'));//abcsssbcaa str和字符串aa进行拼接复制代码
- join()拼接函数 ->str.join()是以()里面的内容来拼接,相当于split的对立面
例子:替换段落中的某些文字(html):sadgergfsdfss阿斯顿设施的阿斯顿啊 啊实打实的爽肤水的方式水淀粉水淀粉十大方式地方十大发生的法十大方式发的法十大法的身份 水淀粉是地方十大发生的
替换文字(js)://替换字符串里面的指定字符串!// !!!!!如果这两句话写在外面,功能错误,为什么?// !!!!因为每次点击都要获取案件的值,获取控件的值是需要通过点击时间来操作的,而不是放在点击事件外// var tar =aInp[6].value;// var trans = aInp[7].value; aInp[8].onclick = function(){ var tar =aInp[6].value; var trans = aInp[7].value; if (!tar)return; op.innerHTML = op.innerHTML.split(tar).join(trans); };复制代码
trim()方法 已移除前导空格、尾随空格和行终止符的原始字符串。
var s = ' Hello ';s.trim();复制代码
数组方法-13
- 标准的json格式{key:value}
var json = { name : 'leo', age : 32 };alert( json.name );var json2 = { name : 'miaov' };//推荐写成这个格式,key都用''圈住,对于增删改查完全等同var json2 = { 'name' : 'miaov' };//访问的两种方式,js任何的.都可以用[]取代,只是格式要注意alert( json2.name );//适用于上面两种写法alert( json2['name'] );//适用于上面两种写法//替换值-两种方式json2.name = '妙味';json2['name'] = 'miaov';复制代码
- json格式和数组的形式可以互为结合
// { [], [], [] } [ {}, {}, {} ]var arr = [ { 'name' : 'TM', 'age' : 23 }, { 'name' : 'leo', 'age' : 32 } ]; alert( arr[0].name + '今年有' + arr[1]['age'] );var arrUrl = [ 'img/1.png', 'img/2.png', 'img/3.png', 'img/4.png' ];var arrText = [ '小宠物', '图片二', '图片三', '面具' ];//变成json格式var imgData = { url : [ 'img/1.png', 'img/2.png', 'img/3.png', 'img/4.png' ], text : [ '小宠物', '图片二', '图片三', '面具' ]};alert( imgData.url[2] );复制代码
- json格式的遍历
- json只能用的遍历for in 语法,因为json没有长度length
- 数组,两种for循环都可以使用
var arr = [ 'a', 'b', 'c' ];第一种for ( var i in arr ) { alert( arr[i] );}第二种for (var i = 0;i < arr.length;i++){ console.log(arr[i]);}复制代码
var json4 = { 'name' : 'thomas', 'age' : 3, 'fun' : '前端开发' };for ( var attr in json4 ) { alert( attr );//返回的是key--name,age,fun alert( json4[attr] );//返回的是value--thomas,3,前端开发}//json和数组混合的遍历//var json5 = { [], [], [] }var json5 = { 'url' : [ 'img/1.png', 'img/2.png', 'img/3.png', 'img/4.png' ], 'text' : [ '小宠物', '图片二', '图片三', '面具' ]};for ( var attr in json5 ) { for ( var i=0; i < json5[attr].length; i++ ) { alert( json5[attr][i] ); }}// var arr = [ {}, {}, {} ];var arr = [ { 'name' : 'TM', 'age' : 23 }, { 'name' : 'leo', 'age' : 32 } ];for(var i = 0; i < arr.length; i++){ for(var attr in arr[i]){ console.log(arr[i][attr]);//TM 23 leo 32 console.log(attr);//name age name age }}复制代码
- 对象
//对象的遍历方法和查询方法 var test = { "events": ["carrot", "exercise", "weekend"], "squirrel": false}// 另一种遍历对象数组的方式 for (item in test) { console.log(item); }// 判断某个元素是否在test对象数组里面 if(('events' in test)){ console.log('event在test对象中'); }复制代码
- 数组的情况(push,unshift,pop,shift,splice,concat,reverse,replace)
数组定义// var arr = [ 1,2,3 ];// var arr = new Array(1,2,3);// alert( arr );数组可以存放多种数据类型的数据, var arr = [ 'aaa',2,3 ]; //数组可以查看长度,修改长度 alert( arr.length ); // 3 arr.length = 0; alert( arr );//null//数组添加-------- var arr = [ 1,2,3 ]; alert(arr.push(4));//输出添加4后的arr长度 arr.push(4);//从后面添加4 alert(arr);//1,2,3,4,4 arr.unshift(5);//从前面添加 // IE 6 7 不支持 unshift 返回值 alert(arr.unshift(5));//同push// alert(arr);//5,5,1,2,3,4//数组删除----------var arr = [ 1,2,3 ];// pop()从后删除,shift()从前删除,返回值都是被删除的那个值 var arr = [ 1,2,3 ]; alert( arr.pop() );//3 alert( arr );//1,2 alert( arr.shift() );//1 alert( arr );//2 //小实例---------- var arr = [ 1,2,3 ]; arr.push(arr.shift()) alert(arr);//2,3,1相当于集体向前移一位 arr.unshift(arr.pop());//相当于集体后前移一位,3,1,2复制代码
**注:**由于unshift比push慢非常多,一个更好的解决办法是:线reverse,在用push,然后再reverse就可以完成相同的效果,而且效率更高
//splice()---------------- splice()可以删除、替换、添加,但是返回值就是删除、替换、添加的那个值(或那几个值) var arr = [ 1,2,3 ];// 删除 arr.splice(0,1);//从第0个位置开始,删除一个,即1 alert(arr);//2,3// 添加 arr.splice(0,0,'aaaaaa');//第0个位置,插入'aaaaaa' alert(arr);//aaaaaa.2,3//替换 arr.splice(0,2,5);//第0个位置,用5来替换后面两个值 alert(arr);//5,3 //concat()链接数组-------------var arr1 = [ 1,2,3 ];var arr2 = [ 4,5,6 ];var arr3 = [ 7,8,9 ];alert( arr1.concat( arr2, arr3 ) );//可以连接多个数组//倒序方法reverse()var arr1 = [ 1,2,3,4,5,6 ]; arr1.reverse(); alert( arr1 );//6,5,4,3,2,1//倒叙字符串var str = 'abcdef';//通过split转为数组,然后倒叙,再变为字符串 alert(str.split('').reverse().join('')); //replace()替换 // replace(/\//g, '') 的作用是把/替换成''。 var aa= "adsdd/sdsd12/";bb=aa.replace(/\//g, '') ;//bb=adsddsdsd12解释:1。/pattern/是正则表达式的界定符,里面的内容(pattern)是要匹配的内容,就是本例中的/\//;2。\是转义的意思,\/代表的是/字符。3。JavaScript中应该是字符串的replace() 方法如果直接用str.replace(/\//g, '')只会替换第一个匹配的字符. 而str.replace(/\//g, '')则可以替换掉全部匹配的字符(g为全局标志)。复制代码
- sort排序
var arr = [ 'c', 'd', 'a', 'e' ]; arr.sort(); alert( arr );//a,c,d,e 默认按照字符排序var arr2 = [ 4,3,5,5,76,2,0,8 ]; arr2.sort();// 对纯数字排序时,默认情况是错误的,8<76 alert( arr2 );//0,2,3,4,5,5,76,8 自定义排序规则 arr2.sort(function ( a, b ) {// 如果a-b<0不动,反之调换位置 return a - b; // 如果b-b<0不动,反之调换位置// return b-a;降序});alert( arr2 );//0,2,3,4,5,5,8,76复制代码
例子1:如果对var arrWidth = [ '345px', '23px', '10px', '1000px' ];排序?
arrWidth.sort(function ( a, b ) {//转化为数字,然后排序 return parseInt(a) - parseInt(b);});复制代码
例子2:自定义一个打乱数组次序的函数 var arr = [ 1,2,3,4,5,6,7,8 ];
arr.sort(function ( a, b ) {//random()函数是0~1的随机数,如果>0.5就调换位置 return Math.random() - 0.5;});复制代码
- 随机函数
alert( Math.round(3.4) );//四舍五入--4 Math.random();//0~1的随机数 //0~10 alert( Math.round(Math.random()*10) ); //5~10 alert( Math.round( Math.random()*5 + 5 ) ); //20~100 alert( Math.round( Math.random()*80 + 20 ) ); // x ~ yvar x = 3;var y = 49;alert( Math.round( Math.random()*(y-x) + x ) );// 0~x alert( Math.round( Math.random()*x) );// 1~xalert( Math.ceil( Math.random()*x) );//ceil()向下取整复制代码