您的位置:首页 > Web前端 > JavaScript

js 笔记

2015-06-24 13:26 549 查看
数据类型及相关操作

字符串,boolen,函数,数字,对象(obj,数组,json,null),未定义
obj:window,document,div
1.charAt() 通过字符串中某个字符的下标来找某个字符
var s=" miaov "; alert( s.charAt(2) ) //弹出i

2.obj 可以添加自定义属性 obj.abc=123
也可以添加函数 obj.fn1=function(){alert(1)} obj.fn1()

3.null 不支持自定义属性添加

4.Number() 把字符串变为数字 var s='100';Number(s)
对于空字符串 转换结果为0
对于布尔值 转换结果为0 或1
var a="+10" //10 非数字的符号+ - 和数字前面的000或者空 都进行智能转
[]// 0 var a=[];
['']//0 var a=[''];
[123] //123 var a=[123];
['123'] //123 var a=['123'];
'100px' //NaN var a="100px"
[1,2,3] //NaN var a=[1,2,3];
null //0 var a=null;
json的转不了 NaN var json={};
对于函数转出来 是NaN var a=function(){}
undefined //NaN var a;
含有非数字的字符串//NaN var a="100px";a

5.parseInt() 转为整数,如果遇到非数字的,之后的所有的都不算 ,从左到右 ,只能转字符串的东西 ,不认 小数点
var a='100px200' //100

parseInt(1,10) 第二个参数是以10进制来转,默认是以10进制

6.parseFloat() 认识一个小数点,第二个小数点后面的直接忽视

判断一个数字是整数还是小数 可通过parseInt()和parseFloat() 配合
var a=200;
if( parseInt(a) == parseFloat(a) ) ...

7.隐式类型转换 - * / % 运算时 可将字符串转为数字: 200-"3" //197
+ : 变成字符串 200+"3" //2003
++ -- : 字符串转为数字 var a='100';a++; //101
>< : '10'>9 //true 数字比较
'10'>'9' //false,字符串比较,按照字符串的位数来比的,第一位跟第一位比,第二位跟第二位比

! 把右边的数据类型转成boolen值
== : '2'==2 //true
'2'===2 //false

不管是显式类型转换还是隐式类型转换, 数据类型转换失败都是NaN

8.
NaN:不是一个数字 的 数字类型,就是转换失败,但又必须转换成一个数字类型,一旦程序出现NaN,肯定是进行了非法的运算操作
NaN:false
NaN==NaN //false,所有的东西和自己比较都是true,除了NaN

isNaN():不是数字,可以判断某些值是不是数字,内部依靠Number() 进行判断
不喜欢数字,见数字就是false,
而且字符串类型的数字也是false,
boolen类型的也是false,
数字类型的都是false

9. 函数传递参数,参数类型就是 js的数据类型,参数可以理解为变量,一个形参对应一个实参

-------------------------------------------------------------
js作用域
域:空间,范围,区域。。。
作用:读,写

浏览器:

--> alert(a);
var a=1; //加了var ,结果弹出 undefined

--> alert(a);
a=1; //不加var 直接报错: a is not defined

"js解析器":var 声明 , function fn1(){} 函数声明
1) "找一些东西":根据 var function 参数
/*
alert(a);
var a=1;//表达式
function fn1(){alert(2)} //函数声明
*/

-->如下注释代码,找的时候先根据var 找到a,并不会去读后面的值,而是提前给它设置了一个值 未定义,这是在执行代码之前,找的动作,所有的变量都是未定义
所有的变量,在正式运行代码之前,都赋了一个值,未定义
a=未定义

fn1=functon fn1(){alert(2)}
函数在正式运行代码之前都是整个函数块
>>第一步叫js的预解析

2) 逐行解读代码:从仓库中开始读,一开始仓库中 a=未定义

浏览器逐行解读代码:解读器:= + - * / % ++ -- 参数 !等,但凡能 改变 值的东西都是表达式
------------------------------------------------------------
预解析过程:把所有的代码进行筛选,最终存到仓库中的只有function a(){alert(4)}
1. 找到var a 并赋值 未定义
2. 跳过alert,找到函数 function a(){alert(2)}; 一个是 a=未定义,一个是函数声明 a=function a(){alert(2)} // a=fn, ;
遇到重名的,只会留下一个函数声明,跟有值没值有关。a=function a(){alert(2)}
3.读到var a=3,这时候不会读到3,a还是未定义 a=function a(){alert(2)}
4.找到 函数 function a(){alert(4)}; 两个重名的函数a,保留最后一个 a=function a(){alert(4)};
5.故仓库中的a=function a(){alert(4)};

解读代码是一行一行来:
alert(a);// 从仓库中开始,a是一个函数名,弹出 function a(){alert(4)};
var a=1;
alert(a); //表达式 a=1改变了a的值, 此处弹出1
function a(){alert(2)};
alert(a); //函数声明不影响a的值, 此处弹出1
var a=3;
alert(a); //表达式 a=3改变了a的值, 此处弹出3
function a(){alert(4)};
alert(a); //函数声明不影响a的值, 此处弹出3 ,a=3;

a();
alert(a) //报错,a is not a function,因为a=3,3() 浏览器不认
------------------------------------------------------------

script 全局变量 全局函数,自上而下

<script>
alert(a) //没有var,也没有函数声明,报错 a is not a function
</script> //script代码是单线程,一块读完了再读下面一块,报错了后会停留在当前,不会进行后续代码操作

<script>
a=1;
</script>

函数 也是一个域:由里到外
eg:
<script>
var a=1;
function fn1(){
alert(a); //undefined
var a=2;
}

fn1(); //undefined
alert(a) //1
</script>

//解读过程
1)预解析:
全局 a=undefined
fn1=function fn1(){
alert(a);
var a=2;
}

2)逐行解读代码:
表达式=, 仓库中的a 变成1
函数声明直接跳过,读函数调用
函数也是一个域,所以也要进行 预解析:var function 得到结果 a=undefined,读取的时候会优先在局部范围内找,这里找到了a是局部变量,和外面的没有一点关系。故fn1()是undefined
接下来表达式 = ,fn1中的a变成2,局部的,不关全局
最后弹出a是全局的,为1

eg:
<script>
var a=1;
function fn1(){
alert(a); //1
a=2;
}

fn1();
alert(a)//1
</script>

//解读过程基本同上
1)预解析:
全局 a=undefined
fn1=function fn1(){
alert(a);
var a=2;
}

2)逐行解读代码:
表达式=, 仓库中的a 变成1
函数声明直接跳过,读函数调用
函数也是一个域,所以也要进行 预解析:var function,此时找不到任何的var和function,它就会跳到上一层域中找,结果找到a=1
接下来表达式 = ,fn1中的a变成2,局部的,不关全局
最后弹出a是全局的,为1

子集作用域可以调到父级这样叫 作用域链

eg:
<script>
var a=1;
function fn1(a){
alert(a);//undefined
a=2;
}

fn1();
alert(a) //1
</script>

//解读过程
1)预解析:
全局 a=undefined
fn1=function fn1(a){
alert(a);
var a=2;
}

2)逐行解读代码:
表达式=, 仓库中的a 变成1
函数声明直接跳过,读函数调用
函数也是一个域,所以也要进行 预解析:var function,参数,参数本身就是一个 局部变量 var a,故此时函数内的a=undefined
函数调用,又没有传参,故调用弹出的a是undefined

eg:
var a=1;
function fn1(a){
alert(a);//弹出1
a=2;
}

fn1(a);//此时传进的参数是全局的a
alert(a) //弹出1

//获取函数内的值//////////////////////////////////////////////////////////////////////////////////////////////
1) 应用局部函数可以修改全局函数的值
var str='';
function fn1(){
var a="大鸡腿...";
str=a;
}
fn1();
alert(str)
2)
function fn1(){
var a="999克拉";
fn2(a); //全局函数fn2可以在任何地方调用,把a拿过来作为参数传进fn2,就可以得到a的值了
}
fn1();
function fn2(b){ //用b来接收a,当然也可以用a来接收a,这里的参数是变量名
alert(b)
}

////////代码规范////////////////////////////////////////////////////////////////////////////////////////////////

函数的{} 是作用域,是作用域就必须执行 与解析和 逐行解读代码
if的{} 不是作用域,它里面的变量时全局的
for的{} 不是作用域,它里面的变量时全局的

alert(a);// a可以被预解析为未定义,说明a是全局
alert(fn1) //FF报错,fn1 is not defined,chrome正常解析弹出函数。
//结论:FF不能解析下面函数,故定义全局变量或全局函数的时候能不在if中定义尽量不要在里面定义,拿到外面去,防止浏览器不能解析
if(true){
var a=1;
function fn1(){
alert(123)
}
}

for循环中的i,经常出错的地方
案例一:
for(var i=0;i<obj.length;i++){
obj[i].onclick=function(){
alert(i) //3
}
}
这个代码简写就是 var i=0;
function(){alert(i)}
函数中没有关于i的任何声明,于是就会到外面去找,外面循环结束i=3,故弹出3

案例二:
for(var i=0;i<obj.length;i++){
obj[i].onclick=function(){
alert(i) //undefined

for(var i=0;i<obj.length;i++){
obj[i].style.background='yellow'
}
}
}
onclick后面的函数是一个作用域,里面有var,故i=undefined

/////运算符和流程控制//////////////////////////////////////////////////////////////////////////////////////////////////////

数据类型的真和假:
真:非0数字,非空字符串(包括' '),true,函数,能找到的元素,数组(即使是空数组),json(即使是空的)
假:0, NaN, '', false , 不能找到的元素, null, undefined

1. 数字类型:0 和 NaN是假的,其他数字是真
2. 字符串:所有的非空字符串都是真的 空格也是非空
3. 函数:真
4. 对象(elem,数组,{},null)
5. undefined:假

///////////函数返回值 return///////////////////////////////////////////////////////////////////////////////////////////////////////////

return 返回值,数据类型:数字,字符串,对象(元素、数组、json、null),未定义,布尔值,函数

/**********eg:***************/
eg:
fn1();
function fn1(){
return 100 //fn1() ==> 100
}
alert(fn1())
/**********eg:***************/

///////////函数返回值 arguments///////////////////////////////////////////////////////////////////////////////////////////////////////////
arguments 可以读 也可以写
eg:
var a=1;
function fn1(a){
alert(a); //1
arguments[0]=3; //arguments[0]本质上就是形参a,此处改写 a为3,弹出 3
alert(a);
var a=2 ;//arguments[0]本质上就是形参a,此处改写 a为2
alert(a) //,弹出2
}
fn1(a);
alert(a);//内部函数未改变外部函数 即为1

/////////// currentStyle 和getComputedStyle//////////////////////////

知识点:obj.style.width只能获取行间样式的宽,如果写在样式表里是得不到的
如果要获取非行间样式,在标准浏览器下 可用getComputedStyle(obj).width 这种来获取,getComputedStyle指的是浏览器计算后的样式

js设置的样式优先级最高 > 其次是行间 > 最后是样式表
而getComputedStyle获取的就是浏览器计算后的结果,也就是说如果 行间 和 样式表 同时存在相同的属性值,它获取的是行间,如果js 又设置了,它获取的是js设置的

getComputedStyle不兼容ie6 7 8以下的浏览器,兼容ie9, chrome,ff,safari等标准浏览器
obj.currentStyle.width 兼容ie6 7 8,9 不兼容ff,chrome, obj.currentStyle.Width
可根据属性判断法 来使用不同的属性,如果浏览器认识 currentStyle则是ie 6 7 8,否则如果是getComputedStyle 则是标准浏览器
if(obj.currentStyle){
alert( obj.currentStyle.width )
}else{
alert( getComputedStyle(obj).width )
}

getStyle注意事项:
getStyle(obj,attr) 对于取颜色值,不能用background,可以用backgroundColor
getStyle(obj,attr) attr例如 'width' 不要有空格 ' width'
getStyle(obj,attr) 不要获取没有设置的样式,不然不兼容
getComputedStyle(obj,参数二) 对于ff 4.0之前,浏览器有个小bug,如果这里只有一个参数,没有参数二,那么结果就出不来,
至于第二个参数是什么无所谓,可以使字符串,也可以是0,false,甚至是函数,只要有一个就行,现在的ff已经是25以上,只要联网了ff就会自动更新,所以这里的第二个参数其实写不写没有多大关系

结论:obj.style.width 可以获取 => 行间样式 和 js 设置的样式,不能获取样式表的样式
getComputedStyle获取的就是浏览器计算后的样式,包括 => 非行间样式(样式表的样式) 行间样式 js设置的样式
js设置的样式优先级最高 > 其次是行间 > 最后是样式表

///////////////////定时器/////////////////////////////////////////////////////////////////////////////////////

设置定时器:setInterval(函数名,毫秒) 定时器会先看时间,然后再执行函数,重复不断的执行,像个发动机

小知识点:函数调用有3中方法
1.直接调用 fn()
2.通过事件 obj.onclick=function(){}
3.定时器 setInterval(函数名,毫秒) 注意这里的函数名 没有(),类似于setInterval(fn1,1000),每隔一秒重复执行,这个时间至少写14以上,因为jquery中最小是14

eg:让document的title每隔一秒 自增
var i=0;
function fn1(){
document.title=i;
i++;
}
setInterval(fn1,1000)

清除定时器:clearInterval(timer);
先定义一个空的定时器, 当i=4的时候,清除定时器,clearInterval()可以写在任何地方,因为timer总是先调用,清除的时候timer里面已经有值了
var i=0;
var timer=null;
function fn1(){
document.title=i;
i++;
if(i===4){
clearInterval(timer)
}
}
timer= setInterval(fn1,1000)

定时器原则:如果定时器是由事件开启的,一定要先关后开

延时定时器:setTimeout(函数,毫秒) 定时器会先看时间,然后再执行函数,只执行一次,像个炸弹,炸完就没了
var timer=setTimeout(函数,毫秒);
清除是 clearTimeout(timer)

妙味广告弹出 代码解读:
当读到第一个setTimeout的时候,不会立马执行里面的代码,等到2秒钟后执行,
读到立马的第二个setTimeout时,也不会立马执行里面的代码,等到3秒钟后执行
var miaov = document.getElementById('miaov');
setTimeout( function(){
miaov.style.display = 'inline-block';
setTimeout(function(){
miaov.style.display = 'none';
}, 3000);
}, 2000);

/***********************定时器的应用*********************************************/

重点研究:无缝滚动,运动时钟

/***********************系统时间对象*******************************************************/

new Date() 当前系统时间对象

日期对象出来的 年月日 时分秒 都是数字

new Date() 设置时间两种方法:
1.数字形式 new Date(2014,11,15,15,30,28) //数字的月份比实际要小一,故设置11月时要设置10
2.字符串形式 new Date('November 15,2014 15:31:29') //字符串的月份不用改,是怎样就怎样

计算两个时间差:
var t1=new Date();
var t2=new Date(2015,11,15,15,30,28);
var t=t2-t1; // 结果是以毫秒为单位
1秒=1000毫秒
t=Math.floor((t2-t1)/1000) ; //这样t就是以秒为单位,且没有小数点
秒转化为时间公式:
// 天:Math.floor(t/86400)
// 时:Math.floor(t%86400/3600)
// 分:Math.floor(t%86400%3600/60)
// 秒:t%60

var str=Math.floor(t/86400)+'天'+Math.floor(t%86400/3600)+'时'+Math.floor(t%86400%3600/60)+'分'+Math.floor(t%60)+'秒';

/*********************************字符串***********************************/
var str='miaov';
1.在字符串中,空格也算
str.charAt(i) 如果()中不写,默认找的是第一个,如果i超过字符串的范围,大了 或 小了 ,结果是空,取不到
字符串的取值范围0~str.length-1
2.str.charCodeAt() 结果:编码。 如果()中不写,默认找的是第一个字符串的unic编码值 //22937,括号中也是下标,只不过结果不再是对应的字符,而是字符对应的unic编码值
str.charCodeAt(1) //21619
取值范围0~str.length-1
3.String.fromCharCode(21619,22937) 括号中编码,结果:字符。 根据unic编码返回字符,可以直接alert出来看看,返回多个用','隔开
--------------------------
var str='0';
str.charCodeAt() // 48
var str='9';
str.charCodeAt() // 57

var str = '妙味课堂-WWW.miaov.com';

str.charAt(1); // '味'
str.charCodeAt(1); // 21619
String.fromCharCode(22937, 21619); // '妙味'

eg:输出unic编码为10000-20000的字符
var str = '';
for ( var i=10000; i<20000; i++ ) {
str += String.fromCharCode(i) + ' ';
}
document.body.innerHTML = str;

加密:
var aInp = document.getElementsByTagName('input');
var oDiv = document.getElementById('div1');

aInp[1].onclick = function () {
var str = aInp[0].value; // 妙味课堂
var str1 = '';
// alert( str.charCodeAt(0) );
for ( var i=0; i<str.length; i++ ) {
str1 += String.fromCharCode(str.charCodeAt(i)-520);
}
oDiv.innerHTML = str1;
};

str.indexOf('m', 4); // 9
str.lastIndexOf('o'); // 16

'1000' < '2' // true
'1000' > 2 // true

str.substring(0, 4); // '妙味课堂'
str.slice(-3); // 'com'

str.toUpperCase(); // '妙味课堂-WWW.MIAOV.COM'
str.toLowerCase(); // '妙味课堂-www.miaov.com'

str.split('.', 2); // [ '妙味课堂-WWW', 'miaov' ]

var arr = [ 'www', 'miaov', 'com' ];
arr.join('aaa'); // 'www.miaov.com'

总结:
0~9 --> unic编码值48-57
a~z --> unic编码值97-122
A~Z --> unic编码值65-90
在 只允许输入 0-9的数字等方面,可以通过字符串的方法来实现
判断数字 之前用的 isNaN,但是它不能判断空格

--------------------------------------------
indexOf(目标字符串,左到右起始位置) 字符串 查找字符串的下标:
lastIndexOf(目标字符串,右到左起始位置)
方法1:循环 找 'a'的位置,比较繁琐
var str="www.miaov.com/2013www";
for(var i=0;i<str.length;i++){
if(str.charAt(i)==='a') alert(i) //4
}

方法2:indexOf('m'),从左到右找,从0位开始,找到了返回下标位置,找到了之后不会继续往后面找,找不到 返回-1
如果要设置从第几位开始找,则应设置第二个参数,第二个参数不能为负数,如果是负数则还是从第0个开始往后面找,如果第二个参数超出查找范围,例如500,返回-1
indexOf('m',5) //返回下标12
var str="www.miaov.com";
str.indexOf('m') //返回下标 4

indexOf(接收的是字符串) eg:indexOf('ww',2) //18

如果要找一个 字符串 出现多少次 以及出现的位置,则需要进行一个特殊的for循环操作:
var str='花朵,以它鲜艳的色彩、婀娜多姿的体态和芳香的气味吸引着人们。花朵,实际上是缩短了的变态枝。花朵瓣的结构也像叶子一样,可分表皮、基本薄壁组织和维管束三部分。花朵瓣的表皮大多具有独特的乳头状突起(见封二),也有毛状体和气孔,表面的角质层常呈现';
//alert(str);
var s='花朵';
var i=0;
for(;str.indexOf(s,i)!=-1;){
alert(str.indexOf(s,i)); // 0 30 45 77
i=str.indexOf(s,i)+s.length;
}
也可以用while循环
var str='花朵,以它鲜艳的色彩、婀娜多姿的体态和芳香的气味吸引着人们。花朵,实际上是缩短了的变态枝。花朵瓣的结构也像叶子一样,可分表皮、基本薄壁组织和维管束三部分。花朵瓣的表皮大多具有独特的乳头状突起(见封二),也有毛状体和气孔,表面的角质层常呈现';
//alert(str);
var s='花朵';
var i=0;
while( str.indexOf(s,i)!=-1 ){
alert( str.indexOf(s,i) );
i=str.indexOf(s,i)+s.length;
}

------------------------------------------
字符串的比较:
比较的是 第一个字符的unic编码

alert( '莫涛' > '杜鹏' ) // true

'莫'.charCodeAt() //33707
'杜'.charCodeAt() //26460

'abbb' >'b' //false
'1000' > 2 // true
'1000' >'2' // false

--------------------------------------------
字符串的截取:substring(下标)
var str='花朵,以它鲜艳的色彩、婀娜多姿的体态和芳香的气味吸引着人们';
str.substring(n1)--> 截取从n1开始~最后的字符串,n1如果不写就和0的效果一样,从0位找到最后
str.substring(n1,n2)--> 截取n1到 n2的字符串,不包括n2,可以检测两个数,大的往后面扔,小的往前面扔,不接受负数,负数当0处理

str.substring(0,2) -->花朵
str.substring(2,0) -->花朵 | 大的往后面扔,小的往前面扔,最后交换位置 (0,2)
str.substring(-3,2) -->花朵 |-3当成0处理
str.substring(2,-3) -->花朵 | 交换位置,-3当成0处理

-----------------
slice(下标) 也是字符串的截取,跟substring()有些区别:
1.不交换位置
2.负数从最后一位开始,eg:(-3,2)往右找不到下标2,返回空字符串
var str1='唐代刘禹锡有诗曰:“庭前芍药妖无格,池上芙蕖净少情。唯有牡丹真国色,花开时节动京城。”';
console.log(str1.slice(0,2)); //唐代
console.log(str1.slice(2,0)); //空字符串 | 不交换位置,返回空的字符串
console.log(str1.slice(-3,2)); //空字符串 | 负数从最后一位开始,往前数,往右找不到下标2,返回空字符串
console.log(str1.slice(2,-3)); //刘禹锡有诗曰:“庭前芍药妖无格,池上芙蕖净少情。唯有牡丹真国色,花开时节动京

-----------------
字符串大小写转换,分割字符串:toUpperCase(字符串) toLowerCase(字符串) split(分隔符)
split(分隔符) 处理的结果是一个数组,如果 不写 分隔符,那么它会把整个 字符串当做一个分隔符,并将这个字符串 放到数组中,这时候数组中就这一个字符串元素

var str="www.TVDRUPAL.com";
小写转大写 :str.toUpperCase() -->WWW.TVDRUPAL.COM
大写转小写: str.toLowerCase() -->www.tvdrupal.com

str.split('.') -->['www','tvdrupal','com']

var str1='alice';
str1.split() --> ['alice']
str1.split('') -->['a','l','i','c','e'] //split会认为字符串之间有空格

split()特殊点:
var str2='/alice/';
str2.split('/') --> [,'alice',] | /左边没东西了但是它还是会认为有,右边同理

split(分隔符,数组长度) 第二个参数为可选参数,限制输出的数组长度,如果不写,则全部分割
var str3='2014-11-17-15-40';
str3.split('-',3) -->['2014','11','17']

----------------------------------------
数组元素拼接:join(分隔符) 如果不写分隔符,则结果是默认用','隔开的字符串
var arr=['aa','bb','cc'];
arr.join() --> 'aa,bb,cc'

-----------------------------数组 json------------------------------------------------------------
json 可以跨平台,适合服务器和javascript之间进行交互
var json={a:'张三',b:'李四'} -->a b 都是自己定义的,后面的是数据格式,可以是字符串,也可以是 数组,json等等
也可以写成:
var json={'a':'张三','b':'李四'} --> 推荐这种写法,这种写法更稳定,更安全,更多的js库解析的时候方便些,不会出现什么问题

访问方法: json.a / json.b
也可以是: json['a'] / json['b']

json 可以读也可以写
改写: json.a='abc'

json中可以包数组,数组中也可以包json var arr=[{'name':'alice','age':23},{'name':'mary','age':13}]

扩展:用json 代替两个数组
var url=['1.jpg','2.jpg','3.jpg'];
var txt=['图片一','图片二','图片三'];
var imageDate={
url:['1.jpg','2.jpg','3.jpg'],
txt:['图片一','图片二','图片三']
}

---------------------------------------------------------
知识点:json的读取,上面提到的 json.a / json['a']只能单一读取, 如果要全部读取json的信息,则需要遍历来读取 for in
eg1:
var json={'name':'alice','age':23,'fun':function(){alert()}}
for(var attr in json){
alert(json[attr]) //注意如果 attr 写成 'attr',那么就会是undefined,加了''就是找单个的属性只值
}

eg2:
var json2={
url:['1.jpg','2.jpg','3.jpg'],
txt:['图片一','图片二','图片三']
}
for(var attr in json2){
for(var i=0;i<json2[attr].length;i++){
alert(json2[attr][i])
}
}

知识点:json 用 for in,数组用 for 循环,也可以用 for in,数组用for in的时候 attr变成数组的下标
for in除了可以对json进行遍历操作,也可以对对象进行遍历操作 window document等

eg3:
//查看window对象下的所有,每个浏览器的属性名不相同
window.onload = function() {
var str='';
for(var attr in window){
str+=attr+':'+window[attr]+'<br/>';
}
document.body.innerHTML=str;

}

eg4:
知识点:数组可以用for in,attr 变成数组下标
var arr=['a','b','c'];
for(var attr in arr){
alert(arr[attr]) // a , b ,c
}

知识点:json 没有 length 属性

知识点:数组有两种定义方法
var arr=['a','b','c'];
var arr1=new Array(1,2,3);
alert(arr1);

new Array()注意点:

//当数组写成对象的形式:var arr1=new Array(3);且只有一个数字元素的时候,弹出来的arr1.length 就是数字值 ,
//但是当接收的是字符串的时候,是多少个元素,长度就是多少
var arr2=new Array(3);
alert( arr2.length ) //3

var arr3=new Array('1');
alert( arr3.length ) //1

知识点:数组的长度 可读 也可以写 arr.length=0 清空数组 或者 arr=[]
var arr=['a','b','c'];
arr.length=1;
alert( arr.length ) //a

知识点:字符串的长度是不能写的
var str='aaaa';
str.length=1;
alert( str ) //aaaa
------------------数组方法------------------------------------

push() 往后塞,同时返回数组的长度,注意ie6 7不支持返回值
var arr=['a','b','c'];
console.log( arr.push('d') ); //4

unshift() 往前塞,同时返回数组的长度,注意ie6 7不支持返回值
arr.unshift('alice');
console.log( arr ); //["alice", "a", "b", "c", "d"]

pop() 删除,从最后删起,返回值是被删掉的那个-'d',pop()一次删一次
arr.pop();
console.log(arr)//["alice", "a", "b", "c"]

shift() 删除,从最开始删起,返回值是被删掉的那个 -'alice',shift()一次删一次
arr.shift()
console.log(arr)// ["a", "b", "c"]

//'d','a','b','c'
var arr=['a','b','c','d'];
arr.unshift(arr.pop());
console.log(arr);

//'polyna','joseph','melody','alice'
var arr2=['alice','polyna','joseph','melody'];
arr2.push( arr2.shift() )
console.log(arr2 )

-----------------------------------------------------------
splice() 返回值是被删掉的那一个或那几个
删除:splice(n1,n2) n1:从第几位开始 n2:干掉几个

var arr=['a','b','c','d'];
arr.splice(0,1) // 'b','c','d'

替换:splice(n1,n2,参数3..)

var arr=['a','b','c','d'];
arr.splice(0,2,'alice','joy') //删掉两个后 添加 'alice','joy'
alert(arr) //alice,joy,c,d

添加:splice(n1,0,参数3..)
var arr=['a','b','c','d'];
arr.splice(1,0,'alice','joy')
alert(arr) //a,alice,joy,b,c,d

数组去重:
var arr=[1,2,2,3,4,5,6,5];
// 将i 和 i+1 位进行比较,如果相同 去掉i+1位
for (var i = 0; i < arr.length; i++) {
for (var j = i + 1; j < arr.length; j++) {
if (arr[i] == arr[j]) {
arr.splice(j, 1);
j--; //j-- 是因为去掉了一位,少了一位
}
}
}

alert(arr) //1,2,3,4,5,6

-----------数组排序--------------------------------------
sort()遵循unic编码值原理
var arr=['f','a','d','h','b'];
arr.sort();
alert(arr); //a,b,d,f,h

sort() 在默认机制下 是将数组中的元素 当成字符串 来排序
var arr2=[1,3,2,3,5,56,67,8,7]
arr2.sort();
console.log(arr2);//[1, 2, 3, 3, 5, 56, 67, 7, 8]

针对数字排序:sort(fn) 提供了一个内部参数
原理:a和b是随机的。a-b>0 正数就会交换位置排序,负数不会交换

var arr3=[1,3,2,3,5,56,67,8,7];

arr3.sort(function(a,b){
return a-b //返回出去的是数字,由小到大 | b-a 从大到小
})
console.log(arr3); //[1, 2, 3, 3, 5, 7, 8, 56, 67]

var arr4=['1000px','23px','10px','55px','500px'];
arr4.sort(function(a,b){
return parseInt(a)-parseInt(b) //返回出去的虽然是数字,但改变的只是位置,并不会改数据类型
})
console.log(arr4)//["10px", "23px", "55px", "500px", "1000px"]

Math.random() 返回0-1之间任意的随机值
数组 sort()随机排序
//根据sort内部函数返回值是正数还是负数来实现随机排序,正数交换位置,负数不交换,这里一会正数一会负数,所以随机
var arr=[1,2,3,4,5];
arr.sort(function(){
return Math.random()-0.5
})
console.log(arr)// [2, 3, 1, 5, 4]

----------------------------------------------------------------
Math.random() 0-1 之间的随机数
Math.round() 四舍五入
Math.round(Math.random()) // 随机数 0 或 1

0-10 之间的随机数: Math.round(Math.random()*10)
5-10 之间的随机数: Math.round(Math.random()*5+5)
10-20之间的随机数: Math.round(Math.random()*10+10)
20-100之间的随机数: Math.round(Math.random()*80+20)

x为任意值:
0-x之间的随机数(包含0 和 x的): Math.round(Math.random()*x)
1-x之间的随机数(包含0 和 x的): Math.ceil(Math.random()*x)
x-y之间的随机数(包含0 和 x的): Math.round(Math.random()*(y-x)+x)

-----------------------------------------------
concat(这里可以放很多数组) 连接数组,变成一个新的数组
var arr1=[1,2,3];
var arr2=[4,5,6];
var arr3=[7,8,9];
arr1.concat(arr2) //1,2,3,4,5,6
arr1.concat(arr2,arr3) //1,2,3,4,5,6,7,8,9

reverse() 颠倒数组中的位置,会改变数组
var arr1=[1,2,3];
console.log( arr1.reverse() ) //3,2,1
颠倒字符串:
var str='abcdefg';
console.log( str.split('').reverse().join('') ) //gfedcba

eg:随机产生100个 从0-1000的整数
var arr=[];
for(var i=0;i<100;i++){
arr.push( Math.round( Math.random()*(1000-i) )+i );
if(arr.length==100){
break
}
}

document.body.innerHTML=arr;
console.log(arr.length)

--------------------------DOM & BOM-------------------------------------------------------------
lesson1:DOM: document object model 文档 对象 模型
文档:html页面
文档对象: html页面中的元素
文档对象模型:是一套标准,准则,定义,w3c组织定义的,为了能够让程序(js) 去操作页面中的元素而定义出来的一套标准

DOM 会把整个文档看成一棵树,见图 树状图:

1.childNodes 属性 只读 子节点列表的集合,只包含一级子节点,不包含孙节点以下例如下面的<span>
obj.childNodes
obj.childNodes.length 可获取所有子节点的长度
在标准浏览器下:ff,chrom.ie9以上等 包含了文本节点和元素节点,也会包含非法嵌套的子节点 例如下面的<p>
在非标准浏览器下:ie8以下 只包含元素节点,ie7以下会包含非法嵌套的子节点 例如下面的<p>

<ul id="list" style="border:1px solid red">
<li>111<span></span></li>
<li>111</li>
<li>111</li>
<li>111</li>
<p>111</p>
</ul>

var oUl=document.getElementsByTagName('ul')[0];
alert(oUl.childNodes.length) //标准浏览器和非标准浏览器下 长度不一样

2.obj.nodeType 属性 只读 当前元素的节点类型
元素节点:1
文本节点:3

console.log(oUl.childNodes[0].nodeType);//3
console.log(oUl.childNodes[1].nodeType);//1

3.obj.attributes 属性 只读 属性列表集合 属性节点
console.log(typeof oUl.attributes); //object
console.log(oUl.attributes.length); //2 id 和 style
alert(oUl.attributes[0]);//[object Attr] 属性类型的对象
console.log(oUl.attributes[1].name); //style
console.log(oUl.attributes[0].value); //border:1px solid red
alert(oUl.attributes[0].nodeType); //2 属性节点

4.obj.children 属性 只读 子节点列表的集合 基本和childNodes差不多,但兼容性比childNodes好
标准和非标准下 只包含元素类型的节点

5.obj.firstChild 属性 只读 获取第一个子节点
在标准浏览器下:ff,chrom.ie9以上等 包含了文本节点和元素节点
在非标准浏览器下:ie8以下 只包含元素节点
标准浏览器和非标准浏览器都有 firstChild 熟悉

obj.firstElementChild 属性 只读 标准下获取第一个元素类型的子节点,非标准浏览器不支持这个属性

做兼容判断:
方法一:
if(obj.firstElementChild){
obj.firstElementChild.style.background="red"
}else{
obj.firstChild.style.background="red"
}

方法二:
var oFirst=obj.firstElementChild || obj.firstChild;
oFirst.style.background="red"

方法三:封装方法二
function oFirst(obj){
return obj.firstElementChild || obj.firstChild;
}
var oUl=document.getElementsByTagName('ul')[0];
oFirst(oUl).style.background="red"
-------------------------------------------------------------------------------------
上面的方法在 非正常的情况下还是会有问题,当oUl的子节点为空时 oFirst(oUl).style.background="red" 这个会报错

因此 获取第一个子节点可以用 obj.children[0]来获取
firstChild \ firstElementChild
lastChild \ lastElementChild
nextSibling \ nextElementSibling
获取指定元素的下一个兄弟节点
previousSibling \ previousElementSibling
获取指定元素的上一个兄弟节点

/**firstChild**/
var oFirst=oUl.firstElementChild || oUl.firstChild; //注意顺序,顺序颠倒则不行
oFirst.style.background="red";

/**lastChild**/
var oLast=oUl.lastElementChild || oUl.lastChild; //注意顺序,顺序颠倒则不行
oLast.style.background="blue";

/**nextSibling**/
var oNext= oFirst.nextElementSibling || oFirst.nextSibling; //注意顺序,顺序颠倒则不行
oNext.style.background="green";

/**previousSibling**/
var oPrev= oLast.previousElementSibling || oLast.previousSibling; //注意顺序,顺序颠倒则不行
oPrev.style.background="yellow";

<ul id="list" style="border:1px solid red">
<li>first</li>
<li>222</li>
<li>333</li>
<li>444</li>
<li>555</li>
<li>last</li>
</ul>

6.parentNode,当前节点的父级,一个元素的父节点只有一个,是单数,只读属性
eg:获取父节点,点击链接隐藏整个li

<ul>
<li>111111...<a href="javascript:;">点击隐藏</a></li>
<li>222222...<a href="javascript:;">点击隐藏</a></li>
<li>333333...<a href="javascript:;">点击隐藏</a></li>
<li>444444...<a href="javascript:;">点击隐藏</a></li>
<li>555555...<a href="javascript:;">点击隐藏</a></li>
<li>666666...<a href="javascript:;">点击隐藏</a></li>
</ul>

<script>
var aA=document.getElementsByTagName('a');
for(var i=0;i<aA.length;i++){
aA[i].onclick=function(){
this.parentNode.style.display='none'
}
}
</script>

parentNode&offsetParent区别

offsetParent 只读 属性 获取最近的有定位的父级(position:relative 或者 position:absolute),如果父级包括自身都没有定位,获取的是body
兼容性问题:如果只有当前元素 自身定位,id7下 获取的是 html,其他浏览器获取的是 body
#div3{background:red;position:absolute}
alert(oDiv3.offsetParent.tagName)

ie7以下,如果某个元素的父节点触发了layout属性,那么offsetParent就会指向到这个触发了layout特性的父节点上
ie7以下
#div2{background:orange;zoom:1 };
alert(oDiv2.currentStyle.hasLayout) //true,因为zoom为1
alert(oDiv3.offsetParent.id) //div2

其他浏览器不会受layout影响,offsetParent还是body

offsetLeft \ offsetTop 只读属性 当前元素到定位父级的距离/偏移值,也可以理解为当前元素到offsetParent的距离(当然不是所有的情况都这样):

情况:
1)都没定位:标准和非标准一样
offsetParent tagName:BODY
offsetParent id:body1
offsetParent offsetLeft:100

2)当前元素自身定位
ie7以下获取的是html,标准浏览器获取的是body
标准浏览器:
offsetParent tagName:BODY
offsetParent id:body1
offsetParent offsetLeft:100
非标准浏览器:
offsetParent tagName:HTML
offsetParent id:
offsetParent offsetLeft:100

3)父级div2定位:ie7以下的offsetLeft是到body的距离,标准浏览器是到父级的距离
标准浏览器:
offsetParent tagName:DIV
offsetParent id:div2
offsetParent offsetLeft:50
非标准浏览器ie7以下:
offsetParent tagName:DIV
offsetParent id:div2
offsetParent offsetLeft:100

4)div2 zoom:1:因为没有任何定位,标准offsetLeft是到body,ie7因为有layout特性,故是到div2
标准浏览器:
offsetParent tagName:BODY
offsetParent id:body1
offsetParent offsetLeft:100
非标准浏览器ie7以下:
offsetParent tagName:DIV
offsetParent id:div2
offsetParent offsetLeft:50
5)自身定位 父级定位:
标准和非标准相同:
offsetParent tagName:DIV
offsetParent id:div1
offsetParent offsetLeft:100

因此,解决ie7兼容性方法有两个:
1.当前元素的父级(或祖先节点中的某个)同时设置 定位 和 zoom:1
2.当前元素 和 父级(或祖先节点中的某个)同时设置 定位

--------------------------------------------------------------
offsetWidth \ clientWidth 没有兼容性问题
style.width:样式宽
clientWidth:样式宽+padding
offsetWidth:占位宽(可视区宽+边框) 样式宽+padding+border

---------------------------------------------------------------
有兼容性问题,标准下不能获取两层,就是不能获取width,只能是style
<input type="text" id="btn1" value="输入框" style="width:100px" />

方法一二:. []
方法三:
1.获取:getAttribute(属性名称) 是个方法,获取指定元素的指定属性值

obj.getAttribute('id')

2.设置:setAttribute(属性名称, 属性) 是个方法,设定指定元素的指定属性值
obj.setAttribute('id','hello') ;

<input type="text" id="btn1" value="输入框" />
<script>
var oInput=document.getElementsByTagName('input')[0];
console.log(oInput.getAttribute('id'));//btn1

oInput.setAttribute('id','hello') ;
console.log( oInput.getAttribute('id') ) //hello
</script>

3.删除:removeAttribute(属性名称) 是个方法,设定指定元素的指定属性值
obj.removeAttribute('id','btn1')

第三种方式的好处:自定义属性、相对网址

对于行间自定义属性,不能用之前学的obj.attr的方法获取,但是可以通过obj.getAttribute(属性名称)来获取 或者 obj.setAttribute('id','hello')来修改
oImg.getAttribute('src') -->'aa.jpg' //-->不再是绝对路径,但是ie7还是绝对路径,所以还是不要用路径做判断条件

------------------------------------------------------------------
创建DOM元素
createElement(标签名) 创建一个节点
appendChild(节点) 追加一个子节点

<input type="text" />
<input type="button" value="往后插">
<input type="button" value="往前插">
<ul></ul>
<script>
var aInput=document.getElementsByTagName('input');
var oUl=document.getElementsByTagName('ul')[0];

aInput[1].onclick=function(){
var oLi=document.createElement('li');
oLi.innerHTML=aInput[0].value;
oUl.appendChild(oLi);
}//往后插

aInput[2].onclick=function(){
var oLi=document.createElement('li');
oLi.innerHTML=aInput[0].value;
oUl.insertBefore(oLi,oUl.children[0]);
}//往前插

例子:留言板插入内容

插入元素 往前插
原有节点父级.insertBefore(节点, 原有节点) 在已有子元素元素前插入
兼容性问题:在ie7以下,如果原有节点不存在则会报错:
解决办法:
if(oUl.children[0]){
oUl.insertBefore(oLi,oUl.children[0]);
}else{
oUl.appendChild(oLi);
}
例子:倒序留言板插入内容

删除DOM元素
removeChild(节点) 删除一个节点
父级.removeChild(节点)
例子:删除留言
替换DOM元素

Child(节点, 已有节点) 替换节点
父级.replaceChild(新节点,原节点)

appendChild() insertBefore() replaceChild() 都可以操作动态创建的节点,也可以操作已有节点(剪切复制)

-------------------------------------------------------------------------------------------
lesson2:DOM&BOM 相关属性及方法:

1.通过class选取元素:返回的是 含有className的元素的集合,是个数组,如果要进行相关操作则要循环数组

function getByClassName(className){
var arr=[];
var als=document.getElementsByTagName('*');
for(var i=0;i<als.length;i++){
var a1=als[i].className.split(' ');
for(var j=0;j<a1.length;j++){
if(a1[j]==className){
arr.push(als[i])
}
}
}
return arr
}

-------------------------------
表格属性:
tBodies、表格内容,一个表格可以包含多个tBody
tHead、表头
tFoot、表尾
rows、 行
cells 列

oTab.tBody[0].row[0].cells[0].innerHTML;
获取表格的第一个表身的第一行 第一列的内容
这种方法比用children好多了,直观性和维护性都要好

---------------------------------
表单元素可以直接通过name的值来获取
<input type="text" name="text1" id="input1">
oForm.text1 就相当于document.getElementById('input1')

在表单提交中,表单域一定要有name值 不然表单提交不过去

方法onchange事件,当值发生改变的时候触发,text的表单 是blur的时候触发,并不是在输入过程中触发

var oForm=document.getElementById('form1');
oForm.text1.onchange=function(){
alert(this.value)
}

radio 单选 / checkbox 复选,有checked 属性
name要设置一样
判断是否被选中
if(oForm.sex[0].checked)

oForm.sex[0].onchange
标准下点击的时候只要值变了就触发
非标准下 焦点离开的时候如果值变了就会触发
触发的时间不同

<input type="radio" name="sex" value="男" />
<input type="radio" name="sex" value="女" />

select 它的value是option中有selected 属性的这一项的值
oForm.city.onchange=function(){
alert(this.value)
}
<select name="city">
<option value="">选择城市</option>
<option value="北京">北京</option>
<option value="上海">上海</option>
</select>

表单提交 onsubmit当表单提交的时候触发
oForm.onsubmit=function(){}
submit() 表单提交方法
也可以是oForm.submit()

阻止表单提交 return false

onreset 当表单重置的时候触发 return false 阻止重置

confirm('你确定要提交?') 返回值是true 或者 false
可以根据 return confirm('你确定要提交?') 来进行阻止提交或者 阻止重置

BOM方法
window.open(url,打开方法) 不传参即打开空页面
window.open('http://www.baidu.com','_self')
返回的是新的window对象 可以存起来 newWindow=window.open('http://www.baidu.com','_self');

window.close() 有兼容性问题
1.ff 默认无法关闭
2.chrome 直接关闭
3.ie 询问用户

浏览器信息 window.navigator.userAgent
判断浏览器是否是ie方法:
if(window.navigator.userAgent.indexOf('MSIE')!=-1){
alert('我是ie')
}else{
alert('我不是ie')
}

window.location 对象 浏览器地址栏地址信息
拥有 window.location.href属性,弹出来的值 和 window.location 的值是一样的
window.location.search,弹出来的是url?后面的内容
window.location.hash ,弹出来的是url#后面的内容
alert( window.location ) //http://127.0.0.1:8020/code/tast/DOM%26BOM/lesson2/6.BOM.html

----------------------------------
窗口的尺寸大小

1.可视区的宽高
document是一个对象,类似数组一样,没有宽高,只有文档元素有宽和高
document.documentElement.clientWidth
document.documentElement.clientHeight

如果是div的可视区那么就是 oDiv.clientWidth / oDiv.clientHeight

2.滚动距离:滚动条滚动的距离,可以理解为 可视区的顶部 距离 页面文档顶部的距离
document.documentElement.scrollTop
document.documentElement.scrollLeft
oDiv.scrollTop
oDiv.scrollLeft
兼容性:chrome 会认为滚动条是body的,而不是文档的,所以对documentElement不起作用
解决方法 var scrollTop=document.documentElement.scrollTop || document.body.scrollTop

3.内容高scrollHeight:div里面有内容,返回div的内容高 padding算在内,border不算

<div id="div1" style="width:100px;height:100px;border:1px solid black;padding:10px">
<div id="div2" style="width:100px;height:200px;background:yellow"></div>
</div>

var oDiv1=document.getElementById('div1');
document.onclick=function(){
alert(oDiv1.scrollHeight) //210 注意是div1的内容高
}

4.文档高:document.documentElement.offsetHeight || document.body.offsetHeight
注意 文档高是和文档内容以及样式相关,不是窗口高
当文档中没有内容的时候文档高是浏览器默认的margin值

兼容问题:ie下 认为document.documentElement.offsetHeight 是可视区的
解决方法还是 ||

5. window.onscroll 当滚动条滚动的时候触发,按时间来算
window.onscroll=function(){}

6. window.onresize 当窗口大小发生改变的时候,按时间来算

----------------------------------------------
事件详解:
1.焦点事件:onfocus 当元素获取焦点的时候触发
焦点:使浏览器能够区分用户输入的对象,当一个元素有焦点的时候,那么他就可以接收用户的输入

<input type="text" value="请输入内容">
<script>
var oInt=document.getElementsByTagName('input')[0];
var v=oInt.value;

oInt.onfocus=function(){
if(this.value===v) this.value='';
}

oInt.onblur=function(){
if(this.value==='') this.value=v
}
</script>

给元素设置焦点方式: 点击 tab键 js

能够响应用户操作的元素才有焦点:input button select textarea a标签 表单

1).obj.focus() 方法 给指定的元素设置焦点,可用于页面加载完就给元素设置焦点
var oTxt=document.getElementById('oText');
oTxt.focus();

2).obj.blur() 方法,取消元素的焦点
3).obj.select() 选择指定的元素的文本内容

eg:输入框全选
<input type="text" id="oText" value="">
<input id="btn" type="button" value="全选">

var oTxt=document.getElementById('oText');
var oBtn=document.getElementById('btn');
oBtn.onclick=function(){
oTxt.select()
}
-------------------------------
event: 事件对象 ,当一个事件发生的时候,和当前这个对象发生的 对这个事件有关的一些向西的信息都会临时保存到一个指定的地方-event对象,供我们在需要的时候调用
事件对象必须在一个事件调用的函数内使用才有内容,类似于obj.onclick=function(){}
事件函数:事件调用的函数

兼容:
ie/chrome: 内置 全局 浏览器帮我们定义好了一个event变量,类似window
传参方法,标准下:事件对象是通过时间函数的第一个参数传入,如果一个函数是 被事件 调用的,那么函数的第一个参数就是 事件对象event,非标准下:undefined
document.onclick=function(ev){
alert(ev)// 标准:object MouseEvent 非标准下:undefined
}
解决兼容方法:var ev=ev || event

没有事件的情况下:alert(event)
ie:null
chrome:undefined
ff:报错

有事件的情况下,事件函数 没传参:alert(event)
document.onclick=function(){
alert(event)//
}
chrome:object MouseEvent
ie:object PointerEvent
ff:报错

clientX:当事件发生的时候,鼠标距离可视区页面左边的距离
ev.clientX
经验:但凡用到clientX或clientY 就要用到scrollTop scrollLeft
onmousemove:触发频率是间隔时间

eg:跟随鼠标移动的div
var oDiv=document.getElementById('div1');
document.onmousemove=function(ev){
var ev=ev||event;
var scrollTop=document.documentElement.scrollTop || document.body.scrollTop;

oDiv.style.left=ev.clientX +'px';
oDiv.style.top=ev.clientY +scrollTop+'px';
}
-------------------------------------------------
事件冒泡:
多出现在 子集 和父级都有事件的时候
取消冒泡:ev.cancelBubble=true;

事件捕获:事件绑定的第二种形式,对于同一个对象,可以绑定多个事件

ie:obj.attachEvent(事件名,事件函数)
标准:obj.addEventListner(事件名,事件函数,是否捕获默认false) false:冒泡 true:捕获

标准下绑定一个不存在的事件不会报错

/**ie7,8,9,10支持这个attachEvent
* 并且 ie7,8 执行顺序是反的,ie9,10是按顺序执行**/
ie:obj.attachEvent(事件名称,事件函数);
1.没有捕获
2.事件名称有on
3.事件函数执行的顺序:标准ie-》正序 非标准ie-》倒序
4.this指向window
标准:obj.addEventListener(事件名称,事件函数,是否捕获);
1.有捕获
2.事件名称没有on
3.事件执行的顺序是正序
4.this触发该事件的对象

function fn1()
{
alert(this);
}
function fn2()
{
alert(this);
}

/**ie7,8,9,10支持这个attachEvent
* 并且 ie7,8 执行顺序是反的,ie9,10是按顺序执行**/
document.attachEvent('onclick',fn1);
document.attachEvent('onclick',fn2);

//document.addEventListener('click',fn1,false);
// document.addEventListener('click',fn2,false);

call() 函数下的一个方法,call(参数一,参数二...) 参数一可以改变一个函数运行过程中的内部this的指向,参数二以后的就是原函数的参数a,b
如果 参数一是 null,那么ie下this还是会指向window
function fn1()
{
alert(this);
}

fn1.call() 和 fn1()相等
fn1.call(1) -->this--1

function fn1(a,b){
alert(this);
alert(a+b)
}

function fn2(){
fn1.call('new things',10,20);
}
document.attachEvent('onclick',fn2);

事件捕获第三个 设为true的时候,执行的顺序是反着的 true 和false 监控的是进来的还是出去的,类似拍3块砖头,div1砖块先破
冒泡的div1,div2,div3

---------------------
解除绑定:ie:obj.detachEvent(事件名,事件函数)
标准:obj.removeEventListener(事件名,事件函数,false/true) 也是按照事件流的顺序来,进来和出去的是两个,所以要说清楚是true 还是 false

document.attachEvent('onclick',fn1);
document.attachEvent('onclick',fn2);
document.detachEvent('onclick',fn1)

document.addEventListener('click',fn1,false);
document.addEventListener('click',fn2,false);
document.removeEventListener('click',fn2,false);

--------------------------
键盘事件:
obj.onkeydown=function(){}
obj.onkeyup=function(){}

event.keycode:数字类型 键值
var oEvent=ev || event;
alert(oEvent.keycode)

ctrlKey,shiftKey,altKey 布尔值
当一个事件发生的时候,如果 ctrl || shift || alt 是按下的状态, 返回 true , 否则返回false
document.onkeydown=function(ev){

var ev=ev || event;
alert( ev.keyCode );
alert(ev.ctrlKey) //按住ctrl 或者 shift 或者 alt的时候 弹出true,如果不按 弹出false

}

//不是所有元素都能够接收键盘事件,能够响应用户输入的元素,能够接收焦点的元素就能够接收键盘事件,document可以接收焦点

//onkeydown : 如果按下不抬起,那么会连续触发
//定时器
------------------------------------
事件默认行为:当一个事件发生的时候,浏览器默认会做的事 a连接跳转,鼠标右键菜单,表单提交等
阻止默认行为:当前这个行为是在什么事件中触发的,就在触发该事件的函数中应用return false

oncontextmenu事件:右键菜单事件,当右键菜单显示出来的时候触发
document.oncontextmenu=function(){
return false
}

------------------------------------
拖拽
/*
onmousedown : 选择元素
onmousemove : 移动元素
onmouseup : 释放元素
*/
知识点,清除事件 obj.事件名=null,通过赋值的方式

//拖拽的时候如果文字或图片被选中会有问题, div拖不动,鼠标放开了div会移动
//原因:当鼠标按下的时候,如果有文字被选中,会触发浏览器的默认拖拽行为,类似于百度的选中文字,然后就可以拖拽的效果
//解决方法:标准浏览器:鼠标按下的时候 return false
// 非标准:ie8以下 return false无效

兼容性解决方法:全局捕获

aInput[0].setCapture(); //设置全局捕获 ,当我们给一个元素设置全局捕获以后,那么这个元素就会监听后续发生的所有事件,
当有事件发生的时候,就会被当前设置了全局捕获的元素所触发,要有事件进来,不管是不是发生在他身上,他都会截过来,故本应该发生在其他元素的事件发生在了它的身上
释放捕获:releaseCapture()
/*
ie : 有,并且有效果
ff : 有,但是没效果
chrome : 没有
*/

----------------------------------------
鼠标滚轮事件:
鼠标滚轮事件
Ie/chrome :onmousewheel obj.onmousewheel=function(){}
firefox : DOMMouseScroll 必须用addEventListener进行绑定

兼容性解决方法:
<style>
#div1{width:100px;height:100px;background:red}
</style>
<script>
var oDiv1=document.getElementById('div1');
if(oDiv1.addEventListener){
oDiv1.addEventListener('DOMMouseScroll',fn1,false);
}

oDiv1.onmousewheel=fn1;
function fn1(){alert(1)}

</script>

获取鼠标是向上滚还是向下滚:

滚轮属性:(IE/chrome)wheelDelta \ (ff)detail 数字类型,代表鼠标滚轮的上或下

IE/chrome:滚轮滚动:onmousewheel
ev.wheelDelta
向上: 120
向下: -120

ff:滚轮滚动:addEventListener('DOMMouseScroll',fn,false)
ev.detail
向上:-3
向下: 3

var oDiv1=document.getElementById('div1');
oDiv1.onmousewheel=fn1;
if(oDiv1.addEventListener){
oDiv1.addEventListener('DOMMouseScroll',fn1,false)
}

function fn1(ev){
var ev=ev||event;
if(ev.wheelDelta) alert(ev.wheelDelta);
else alert(ev.detail)
}

鼠标滚轮的方向在chrome/ie (120/-120) 和ff (-3 3)中有较大的不同,数值不一样 而且方向 也是相反的,
为此,我们可以用布尔值来代表鼠标的滚轮是向上还是向下,向上就是true,向下就是false
<div id="div1"></div>
<script>
var oDiv1=document.getElementById('div1');

oDiv1.onmousewheel=fn1;

if(oDiv1.addEventListener){
oDiv1.addEventListener('DOMMouseScroll',fn1,false)
}

var b=true;

function fn1(ev){
var ev=ev||event;
if(ev.wheelDelta){
//alert(ev.wheelDelta); //IE / chrome 120、-120
b= ev.wheelDelta > 0 ? true :false;
}else{
//alert(ev.detail); //ff -3 3
b= ev.detail < 0 ? true :false;
}
alert(b);
}

div 高度根据鼠标滚轮滚动的方向来变:
if(b){
oDiv1.style.height=this.offsetHeight+10+'px';
}else{
oDiv1.style.height=this.offsetHeight-10+'px';
}

-----------------------------
当滚轮滚动的时候,页面的滚动条也在滚动,这就是触发了浏览器的默认行为
return false 阻止的是on开头的事件 所触发的默认行为
ff 通过addEventListener这种绑定的事件必须通过 一个方法来阻止 preventDefault ev.preventDefault()

阻止方法:
IE/chrome:在调用的函数里加上 return false
ff:ev.preventDefault()

故前面的fn1函数中加入来阻止默认事件:
if(ev.preventDefault){
ev.preventDefault()
}

return false;

阻止默认事件:绑定写法:preventDefault

---------------------------------------
cookie:存储数据的,类似变量,但是变量是临时存放,只有开启浏览器的时候才会启用,cookie可以长期保存
cookie可以存储数据并且可以设置存储时间

当用户访问了某个网页的时候,可以通过cookie向访问者的电脑上存储数据。
1.不同浏览器存放的cookie位置是不一样的,也不能通用,每个浏览器都有自己的cookie
2.cookie的存储是以域名的形式进行区分
3.cookie的数据是可以设置名字的,类似json可以取名
4.一个域名下存放的cookie的数量是有限的,但不同的浏览器不同的版本 数量是不一样的
5.每个cookie存放的内容大小也是有限制的,不同的浏览器存放的大小不一样

1).cookie的存储方式:
document.cookie="名字=值";

eg:document.cookie='username=miya';
有些浏览器chrome不允许本地cookie存储读写操作,但ff和ie可以,通过ff 选项-隐私-清除cookie中可以查看cookie

2).cookie的读法:document.cookie 由此可见 cookie是可读可写的
alert(document.cookie) -->弹出 username=miya

3).我们通过document.cookie获取当前网站下的cookie,得到的是一个字符串形式的值,包含了当前网站下所有的cookie。
它会把 所有的cookie 用 分号+空格 的形式串联起来。

如果有多条cookie:
document.cookie='username=miya';
document.cookie='age=28';
alert(document.cookie) //username=miya; age=28

4).cookie默认是临时存储的,当浏览器关闭,自动销毁。
如果想长时间存放cookie,需要在设置cookie的时候同时设置过期时间,不然删掉页面的cookie设置代码后,关闭浏览器,cookie就自动过期,cookie自动销毁:
document.cookie="名字=值;expires="+字符串类型的时间;

oDate=new Date()是以毫秒计算的:document.cookie='username=miya;expires='+oDate;这个代码会立马删掉username这个cookie
设置日期:oDate.setDate(oDate(7)) 设置时间为当天的7天后
oDate.setDate(oDate.getDate()+7) 设置时间为访问者访问的当天的7天后
document.cookie='username=miya;expires='+oDate;

eg:
//先存储cookie,然后删除cookie代码和过期日,关闭浏览器,再开启浏览器,看cookie是否存在
//设置过期时间
oDate=new Date();
oDate.setDate(oDate.getDate()+7);
//alert(oDate);
//document.cookie='username=miya;expires='+oDate;
//document.cookie='age=28;expires='+oDate;
alert(document.cookie);

该写法遗留的问题,ie不认,仍然自动销毁,原因是oDate是对象,不是字符串
转换方法:把上面的expires中的oDate 换成oDate.toGMTString()
oDate.toGMTString() //string
//document.cookie='username=miya;expires='+oDate.toGMTString();
//document.cookie='age=28;expires='+oDate.toGMTString();

5).内容编码存放 encodeURI,解码:decodeURI
当存放特殊字符的时候,被过滤掉了document.cookie='username=miya\n你好;expires='+oDate; -->cookie中还是miya,后面的\n你好被过滤了

alert(encodeURI('你好')); //%E4%BD%A0%E5%A5%BD
alert(decodeURI('%E4%BD%A0%E5%A5%BD'))//你好

下面代码可以完整的读出:miya\n你好
var oDate=new Date();
oDate.setDate(oDate.getDate()+7);
document.cookie='username='+encodeURI('miya\n你好')+';expires='+oDate.toGMTString();
alert( decodeURI(document.cookie) )

cookie的作用:
页面用来保存信息
同一个网站中所有页面共享一套cookie

cookie的使用
设置cookie 过期时间expires
读取cookie 字符串分割
删除cookie 已经过期
例子:
Cookie登录后删除信息

-------------------------------------------
面向对象:系统自带的对象 叫系统对象 array Date
我们一直都在使用对象
数组 Array 时间 Date

面向对象就是在对象的基础上进行操作 new...,对象自己有方法oDate.push()等等
例如要写一个面向对象的选项卡:oTab=new Tab(),还可以给它加方法 oTab.over(),oTab.autoPlay() 等等

面向对象是一种代码的写法
之前学的是面向过程式的 ,a() 之类

面向对象:oop 也可以说是oop编程

1.面向对象编程(OOP)的特点:
抽象:抓住核心问题
封装:只能通过对象来访问方法 要访问push() 必须是arr.push()
继承:从已有对象上继承出新的对象 复用代码
多态:多对象的不同形态 复用的一种形式

2.对象的组成
方法(行为、操作)——函数:过程、动态的
属性:对象下的变量:状态、静态的

var arr=[];
arr.number=10;//对象下的变量,叫做对象的属性
//alert(arr.number) //10

arr.test=function(){//对象下的函数,叫做对象的方法
alert(123)
}
//arr.test() //123

判断是属性还是方法的 办法:看后面加不加(),加了()就是方法,不加()就是属性

var json={} 的完整写法 是 var json=new Object() // json的类型是 object,即使用$.type()来判断

创建第一个面向对象:
var obj=new Object();//创建一个空对象,空对象:里面没有自己的属性和方法, 跟数组的区别 数组有自己的属性和方法
obj.name="小米"; //创建对象的属性
obj.showName=function(){ //创建对象的方法
alert('小米,这是方法')
}
obj.showName()

面向对象的难点在于this,函数里面的this属于函数,函数被谁调用 this就指向谁,上面的例子this指向obj,如果没被任何人调用 this指向window
var obj=new Object();//创建一个空对象
obj.name="小米"; //创建对象的属性
obj.showName=function(){ //创建对象的方法
alert(this.name) //this指向obj
}

obj.showName()

3.工厂方式 与构造函数:
工厂方式就是 面向对象的代码封装,步骤还是创建属性,创建方法,然后在外面调用方法
原料,加工,出厂

function createPerson(name){
//1.原料
var obj=new Object();
//2.加工
obj.name=name; //创建属性
obj.showName=function(){ //创建方法
alert(this.name)
}
//出厂
return obj //将obj返回出去,好在外面使用
}

var p1=createPerson('alice');
p1.showName();//调用方法

var p2=createPerson('asher');
p2.showName()

我们自己写的面向对象 跟系统自带的还是有些区别:我们要把new 拿出来
var oDate=new Date();
var p1=createPerson('alice');

4.当new 去调用一个函数,这个时候函数中的this就是创建出来的对象,而且函数的返回值直接就是this了,隐式返回
正常的函数没有返回 那是undefined,但是new 的这种不用写也行,默认返回this

function CreatePerson(name){ //默认返回this
this.name=name;//this指向的是新创建的对象,相当于原来的Obj
this.showName=function(){
alert(this.name)
}
}

var p1=new CreatePerson('张');
p1.showName()

var p2=new CreatePerson('王');
p2.showName()

new 后面的函数就叫构造函数CreatePerson / Array / Date

5.对象的引用:
基本类型(数字,字符串等) 的赋值只是值的复制
对象类型赋值的时候,不仅是值得复制,也是地址引用的传递(相当于男女从各自的家,住在一个地方了),只要是赋值就会生成一个新的地址来存放值,但是修改不会

alert( p1.showName == p2.showName ) //false

/*
var a=[1,2,3];
var b=[1,2,3];
alert( a == b ) //false
/*
基本类型(数字,字符串等) 的赋值只是值的复制
var a=5;
var b=a;
b+=3;
alert(b); //8
alert(a) //5

/*

对象类型赋值的时候,不仅是值得复制,也是引用的传递,相当于a 从自己家 搬到了b家
var a=[1,2,3];
var b=a;
b.push(4);
alert(b); //1,2,3,4
alert(a) //1,2,3,4

/*

只要是赋值就会生成一个新的地址来存放值,这时候b相当于从a的家搬出去了,和a没有关系,但是修改不会
var a=[1,2,3];
var b=a;
b=[1,2,3,4]
alert(b); //1,2,3,4
alert(a) //1,2,3
*/

比较:
/*
基本类型的比较:只要值相同
var a=5;
var b=5;
alert( a==b ) //true

*/
/*
对象类型:值和引用都要相同才相等
var a=[1,2,3];
var b=[1,2,3];
alert( a==b ) //false
*/

/*
对象类型:值和引用都要相同才相等
var a=[1,2,3];
var b=a; //把值和引用都毙掉,两个就相等了
alert( a==b ) //true
*/

---------------------------------------
原型:
p1和p2都是 new 赋值得来的,每次赋值都会有一个新的地址
所以alert( p1.showName == p2.showName ) //false
但是 showName这个方法,如果被调用了2000次,那么内存就会存储2000条,极大的消耗内容,怎样让他们为true呢?这就是接下来要学习的 原型:

原型:去改写对象下面公用的方法或属性,让公用的方法或属性在内存中存在一份,好处就是提高性能

通过类比的方法来了解原型:
原型: css中的 class
普通方法:css中的style

style的优先级比class高
style 不可以复用, class可以,例如给div 和 span 加样式

var arr1=[1,2,3,4];
var arr2=[2,3];
Array.prototype.sum=function(){
var num=0;
for(var i=0;i<this.length;i++){
num+=this[i];
}
alert(num);
return num
}
arr1.sum();
arr2.sum()

原型 prototype 要写在 构造函数的后边

知识点:new 后面调用的函数叫做构造函数 function createPerson(){}
把普通方法showName()变成原型下面的方法
原型写法:属性放在构造函数中,方法放在原型中
function 构造函数(){
对象的属性
}
构造函数.prototype.方法=function(){}

使用:var 对象1=new 构造函数();
对象1.方法()

/*
写法1,没有用new的方法,工厂模式
function createPerson(name){
var obj=new Object();
obj.name=name;
obj.showName=function(){
alert(obj.name)
}
return obj
}
createPerson('aa').showName()
*/

/*
写法2:用 new的方法,此时this指的就是obj,新创建的对象,默认返回this
function CreatePerson(name){
this.name=name;
this.showName=function(){
alert(this.name)
}
}

var p1=new CreatePerson('alice');
p1.showName();

var p2=new CreatePerson('jack');
p2.showName();
*/

//写法3:原型的方法
function CreatePerson(name){
this.name=name;
}
CreatePerson.prototype.showName=function(){
alert(this.name)
}

var p1=new CreatePerson('jack');
p1.showName();

var p2=new CreatePerson('alice');
p2.showName();

---------------------------------------------
面向对象选项卡:

原则:
先写出普通的写法,然后改成面向对象写法
普通方法变型
尽量不要出现函数嵌套函数
可以有全局变量
把onload中不是赋值的语句放到单独函数中

改成面向对象
全局变量就是属性
函数就是方法
Onload中创建对象
改this指向问题

this指向问题:在事件或者定时器的时候容易被修改,尽量让面向对象中的this指向对象

var oDiv=document.getElementById('div');

//case1:
oDiv.onclick=function(){
this:指的是 oDiv
}

//case2:
oDiv.onclick=show;
function show(){
this:指的还是oDiv,因为是oDiv调用的
}

//case3:
oDiv.onclick=function(){
show()
}
function show(){
this:指的是window
}

面向对象选项卡:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>12.选项卡 面向对象</title>
<meta name="author" content="Administrator" />
<!-- Date: 2014-12-01 -->
<style>
.tab div{display: none;}
div.active{display: block}
.select{background:red}
</style>
<script>
/*
var oTab=null;
var aInput=null;
var aDiv=null;

window.onload=function(){

普通方法变型
尽量不要出现函数嵌套函数
可以有全局变量
把onload中不是赋值的语句放到单独函数中

oTab=document.getElementById('tab1')
aInput=oTab.getElementsByTagName('input');
aDiv=oTab.getElementsByTagName('div');
init()

}
*/

/*
function init(){
for(var i=0;i<aInput.length;i++){
aInput[i].index=i;
aInput[i].onclick=change
}
}

function change(){
for(var i=0;i<aInput.length;i++){
aInput[i].className='';
aDiv[i].style.display='none';
}
this.className='select';
aDiv[this.index].style.display='block';
}
*/

/**改成面向对象
全局变量就是属性
函数就是方法
Onload中创建对象
改this指向问题**/

window.onload=function(){
var tab1=new Tab('tab1');
tab1.init();
tab1.autoplay();
var tab2=new Tab('tab2');
tab2.init();
}

function Tab(id){//this指向对象 tab1
this.oTab=document.getElementById(id)
this.aInput=this.oTab.getElementsByTagName('input');
this.aDiv=this.oTab.getElementsByTagName('div');
this.iNow=0;
}

Tab.prototype.init=function(){//this指向对象 tab1
var This=this;//把对象存进This中
for(var i=0;i<this.aInput.length;i++){
this.aInput[i].index=i;
this.aInput[i].onclick=function(){
This.change(this); //这里括号中的this指的是按钮

}
}
}

Tab.prototype.change=function(obj){//this指的是按钮,就不对了,应该指的是对象,可以根据change()的调用来修正指向,然后利用把对象this存进This,obj指的是当前按钮
for(var i=0;i<this.aInput.length;i++){
this.aInput[i].className='';
this.aDiv[i].style.display='none';
}
obj.className='select';
this.aDiv[obj.index].style.display='block';
}

Tab.prototype.autoplay=function(){//this指的是按钮,就不对了,应该指的是对象,可以根据change()的调用来修正指向,然后利用把对象this存进This,obj指的是当前按钮
var This=this;
setInterval(function(){
for(var i=0;i<This.aInput.length;i++){
This.aInput[i].className='';
This.aDiv[i].style.display='none';
}
if(This.iNow==This.aInput.length-1){
This.iNow=0
}else{
This.iNow++
}
This.aInput[This.iNow].className='select';
This.aDiv[This.iNow].style.display='block';

},1000)
}

</script>
</head>
<body>

<div id="tab1" class='tab'>
<input type="button" value="时事" class='select'/>
<input type="button" value="政治" />
<input type="button" value="新闻" />
<div class="active">时事时事时事</div>
<div>政治政治政治</div>
<div>新闻新闻新闻</div>
</div>

<div id="tab2" class='tab'>
<input type="button" value="时事" class='select'/>
<input type="button" value="政治" />
<input type="button" value="新闻" />
<div class="active">时事时事时事</div>
<div>政治政治政治</div>
<div>新闻新闻新闻</div>
</div>
</body>
</html>

-------------------------------------
高级面向对象:

在js源码,系统对象也是基于原型的程序,所以一般不要去 修改 或者 添加 系统对象的 方法 和 属性 ,要不然会影响操作

包装对象:
基本类型除了 undefined 和 null 都有自己的包装对象:字符串,数字,字符串
原型下的方法是共享的

var str=new String('aaa');
typeof str // object

var str='hello'; //字符串
str.charAt(0); //基本类型会找到对应的包装对象类型,然后包装对象把所有的属性和方法给了基本类型,然后包装对象消失

/*给包装对象String写一个方法
var str='hello'; //字符串
String.prototype.lastValue=function(){
return this.charAt(this.length-1)
}
alert( str.lastValue() )
*/

/*
var str='hello'; //字符串
str.number=10;
alert(str.number) //undefined 没有number方法没有写在原型下,
// 当 str.number=10执行完后,number就消失了,当要弹出str.number的时候,
// 相当于重新创建了一个属性number,但是在原型中找不到包装对象,所以是undefined
*/

/*数组的push方法
var arr=[1,2,3];
Array.prototype.push=function(){
for(var i=0;i<arguments.length;i++){
this[this.length]=arguments[i]
}
return this.length
}
arr.push(4,5,6);
alert( arr ); //1,2,3,4,5,6
*/

---------------------------------
原型链:
原型链
实例对象与原型之间的连接,叫做原型链
function Aaa(){}
Aaa.prototype.number=10; //原型
var a1=new Aaa(); //实例对象
alert( a1.number ) //10 实例对象与原型之间有原型链,-通过 实例对象- 去 找 -原型-

__proto__( 隐式连接 )

function Aaa(){this.number=20} // 构造函数相当于 style
Aaa.prototype.number=10; //原型 相当于class
var a1=new Aaa(); //实例对象
alert( a1.number ) //20 style的优先级高于class. 先找实例对象 , 找到了 就不再往外找了.

Object对象类型是原型链的最外层 Object.prototype
function Aaa(){} //
Object.prototype.number=10; //Object对象类型是原型链的最外层 Object.prototype
var a1=new Aaa(); //实例对象
alert( a1.number ) //10

----------------------------
面向对象的一些属性和方法:

hasOwnProperty() : 看是不是对象自身下面的属性,这是最外层Object.prototype下的方法
var arr=[];
arr.num=10;
Array.prototype.num2=20;
// alert(arr.hasOwnProperty('num')); //true

//prototype下的方法 都是公用的,并不独立,所以不是自身的,为false
alert(arr.hasOwnProperty('num2')) //false

constructor : 查看对象的构造函数
function Aaa(){}
var a1=new Aaa();
alert( a1.constructor ) // Aaa这个函数, constructor的作用是为了查看 -哪一个函数- 构造了a1

var a1=[];
alert( a1.constructor ) // Array

每个原型都会自动添加constructor属性
Aaa.prototype.constructor=Aaa

For in 的时候有些属性是找不到的,系统自带的属性都是循环不到的
自己添加的可以找到:
var a1 = new Aaa();
function Aaa(){}
Aaa.prototype.name='jack';
Aaa.prototype.age=22;
for(var attr in Aaa.prototype){
alert( attr )
}
但是系统生成的是找不到的
for(var attr in Array){
alert(attr) //什么也没弹出来
}

避免修改construtor属性
var a1 = new Aaa();
function Aaa(){}
Aaa.prototype.name='jack';
Aaa.prototype.age=22;

alert( a1.constructor ) //Aaa

赋值的形式,把json赋值给了Aaa,所以是Object
var a1 = new Aaa();
function Aaa(){}
Aaa.prototype={
name:'jack',
age:22
}
alert( a1.constructor ) // Object

var a1 = new Aaa();
function Aaa(){}
Aaa.prototype={
constructor:Aaa,
name:'jack',
age:22
}
alert( a1.constructor ) // Aaa

----------------------------------------------
instanceof : 运算符
-实例对象- 与 -构造函数- 在原型链上是否有关系
function Aaa () {}
Aaa.prototype.name='alice';
var a1=new Aaa()
alert( a1 instanceof Aaa ) //true
alert( a1 instanceof Object ) //true

如何区分一个变量是不是数组?
方法1:变量.constructor
方法2: 变量 instanceOf Array
方法3:toString()

var arr=[];
alert( arr.toString == Object.prototype.toString ) //false

function Aaa(){}
Aaa.prototype.name='alice';
var a1=new Aaa();
alert( a1.toString == Object.prototype.toString ) //true

toString() : 判断是不是数组的最完美的方法。 object上的方法,把对象转成字符串,可以判断对象 是不是 数组,是不是日期对象,是不是正则,json是object,可以把数字转为16进制
所有的对象都有toString()方法,不管是自己写的 还是系统对象,toString位置系统对象下面都是自带的,而自己写的都是通过原型链找的
var arr=[1,2,3];
alert( arr.toString() ) //'1,2,3'

alert( Object.prototype.toString.call(arr) ) // [object Array]

---------------------------------------------------------
面向对象的继承:

什么是继承
在原有对象的基础上,略作修改,得到一个新的对象
不影响原有对象的功能
继承是复用代码的一个形式,子类不影响父类,子类可以继承父类的一些功能

如何添加继承
属性:call 调用父类的构造函数,采用call 改变this的指向为 对象
方法: 子类的 原型 赋给 子类的原型 子类.原型=父类.原型
缺点:子类会影响父类,解决方法,对象属性的拷贝,而不是引用,用for in 拷贝继承

//父类
function CreatePerson(name,sex){
this.name=name;
this.sex=sex
}
CreatePerson.prototype.showName=function(){
alert( this.name )
}

var a1=new CreatePerson('小明','男');
//a1.showName();

//子类

function CreateStar(name,sex,job){
CreatePerson.call(this,name,sex);//CreatePerson前面没有任何东西调用它,指向window,属性的继承,通过call,this指向star1
this.job=job
}

CreateStar.prototype=CreatePerson.prototype;//把父类的原型 付给子类的原型,方法继承,这样会改变 引用的地址,子类改了,父类也会改,父类本来没有showJob的方法,但是现在有了

CreateStar.prototype.showJob=function(){
alert( this.job )
}

var star1=new CreateStar('黄晓明','男','演员')
star1.showName();

for in 方法 解决 对象的复制
/*
var a='555';
var b=a;
b='666';
alert(a);//555
alert(b);//666
*/

var a={
name:'alice',
age:22
}

var b={}

//通过 for in 的形式 把 a 的子元素 赋值给 b 的 子元素,然后再改变 b 的值 对a 没有影响,也是一种继承
for(var attr in a){
b[attr]=a[attr]
}
b.name='小强'
alert( a.name ); //alice

//封装函数 extend,把父级的属性复制给子类的属性

obj1子类, obj2父级
function extend(obj1,obj2){
for(var attr in obj2){
obj1[attr]=obj2[attr]
}
}

var a1={name:'alice',age:23};
var a2={};
extend(a2,a1);
a2.name='xiaoqiang';

alert(a1.name); //alice
alert(a2.name) //xiaoqiang

例子 : 继承的拖拽

------------------------------------------------
继承的其他形式
类式继承
利用构造函数(类)继承的方式
属性和方法各自继承:属性继承还是用call,方法继承利用一个空的函数F 把
function F(){}
F.prototype=Aaa.prototype;
Bbb.prototype=new F();
Bbb.prototype.constructor=Bbb

js中没有 类 的概念,可以把js中的构造函数看做是 类
//js中没有 类 的概念,可以把js中的构造函数看做是 类
function Aaa(){
this.name=[1,2,3]
}
Aaa.prototype.showName=function(){
alert( this.name )
}

function Bbb(){
Aaa.call(this)
}
//类式继承的四句话
function F(){};
F.prototype=Aaa.prototype;
Bbb.prototype=new F();
Bbb.prototype.constructor=Bbb;//修正指向到Bbb

var a1=new Aaa();
var b1=new Bbb();
b1.name.push(4);

b1.showName();//[1,2,3,4]
a1.showName();//[1,2,3]
原型继承
借助原型来实现对象继承对象
//没有用new的情况
var a1={name:'小明'};
var a2=clone(a1);
a2.name='小强';
alert( a1.name +'-'+ a2.name ); //小明 小强
function clone(obj){
function F(){};
F.prototype=obj;
return new F()
}
总结:继承:
1)拷贝继承:通用型,有new和无new都可以
2)类式继承:有new的情况
3)原型继承:无new的情况

/******************拖拽的组件开发*********************************************/

组件开发:多组对象,像兄弟之间的关系(代码复用的一种形式)

什么是组件?
对面向对象的深入应用(UI组件,功能组件)
将 配置参数、方法、事件,三者进行分离

创建自定义事件:主要跟函数有关,让函数能具备事件的某些特性(事件覆盖,事件流,默认事件等)
绑定函数,即使是相同的函数名,但是不会再覆盖
有利于多人协作开发代码
如何去挂载自定义事件与事件函数

mouseenter 和 mouseleave 子集不会影响父级

/********************缓冲运动******************************/
css 有小数,
js中的offsetWidth等是经过内部运算的值, 小数会四舍五入
100.4 -->100
100.5 -->101

<!--通过放大可以看到 div1 比 div2 要宽一点,多出0.4,也就是说 css认小数点-->
<div id="div1" style="width:100.5px;height:100px;background:red;"></div>
<div id="div2" style="width:100px;height:100px;background:black;"></div>
<script>
var oDiv1=document.getElementById('div1');
var oDiv2=document.getElementById('div2');

//js中的offsetWidth是经过计算的,小数按四舍五入
//当div 宽为100.4
alert( oDiv1.offsetWidth ) //100

//当div 宽为100.5
//alert( oDiv1.offsetWidth ) //101

</script>

style.width 设置是多少就为多少,认小数

缓冲运动解决小数问题 把 速度 正的方向 向上取整 , 负的方向 向下取整
摩擦运动
逐渐变慢,最后停止

缓冲运动
与摩擦力的区别:可以精确的停到指定目标点
距离越远速度越大
速度由距离决定
速度=(目标值-当前值)/缩放系数
Bug:速度取整
值取整
-------------------------------------
定位由 relative 变为absolute

<style>
*{margin:0;padding:0;}
ul{position:relative;width:330px;}
li{list-style:none;float:left;margin:10px 0 0 10px;width: 100px;height:100px;background:red}
</style>
<script>
window.onload=function(){
var oUl=document.getElementsByTagName('ul')[0];
var aLi=oUl.getElementsByTagName('li');
for(var i=0;i<aLi.length;i++){
aLi[i].style.left= aLi[i].offsetLeft +'px';
aLi[i].style.top= aLi[i].offsetTop +'px';

//在同一个代码块中,有些css的优先级要高于js,如果这一句写在这里, 程序会先走这一句,然后再走上面两句,
//因为offsetLeft/offsetTop是经过计算后的值,所以这一句要放在下面。offsetLeft/offsetTop 不管有没有margin,就是到父级的边距
// aLi[i].style.position='absolute';
}
document.title= aLi[0].offsetLeft;

for( var i=0;i<aLi.length;i++ ){
aLi[i].style.position='absolute';

//margin值没有清掉,定位后会在现有的位置上还是加上margin值,偏移的是20px,所以这里要清掉margin值
aLi[i].style.margin='0'
}

}
</script>
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
-------------------------------------------------------------
图片预加载
/*
我们经常会用下载软件下载电视剧,一个电视剧可以能有N集。
1.先把所所有的集数全部下载完成,然后一个个开开心心的看。你真的开心吗?
2.我们先下一集,然后看完,看完以后再去下下一集,然后再看。

3.我们先下第一集,下载完成以后,再看第一集的时候去下载后面的内容,这样,我们可以在看前面的内容的时候,把后面的下完了,节约了很多的时间

在页面刚打开的时候,我们去加载第一张图片,然后页面加载完成以后,在用户看的时间内,去加载后面的内容,那么我们必须有个工具(迅雷) -> Image对象
*/

window.onload=function(){
/*
属性:
src : 当我们给Image对象的src属性赋值一个url的时候,这个Image对象就去会加载url资源,加载完成以后的资源被保存到了浏览器的缓存文件夹里面,下次如果我们要去调用这个url地址的时候,直接是从缓存文件夹读取到的,所以速度很快。
onload : 当资源加载完成的时候触发
onerror : 当资源加载失败的时候触发
*/
var oImg1=document.getElementsByTagName('img')[0];
var oImage= new Image();
oImage.src='http://gb.cri.cn/mmsource/images/2014/08/11/0/5240451376502243632.jpg';
oImage.onload=function(){
alert('下载完成');
};

oImage.onerror=function(){
alert('下载出错')
}

document.onclick=function(){
oImg1.src='http://gb.cri.cn/mmsource/images/2014/08/11/0/5240451376502243632.jpg';
}
}
</script>
</head>
<body>
<img src=''/ style="width:400px;">
</body>
----------------------------------------------------
高级运动
弹性运动:obj围绕一个目标点弹两下停下来
碰撞运动:obj不过目标点,例子:小球从高处落下,与地面相碰

加减速运动
速度不断增加或减少
速度减小到负值,会向反方向运动

弹性运动与缓冲运动区别:

弹性运动:
速度在全局定义
iSpeed += (目标点-当前位置)/系数 -->系数范围:6,7,8
iSpeed*=摩擦系数 -->摩擦系数 0.7 0.75

缓冲运动:
速度定义在定时器里边
iSpeed=(目标点-当前位置)/系数
速度取整

前面学的抖动和这个弹性运动差不多,抖动是将速度放在数组里,弹性运动的速度是全局变量,然后在定时器中运算
抖动的最终位置就是起始位置,而弹性菜单的最终位置是目标点的位置

宽高出现负值在ie低版本中会有问题,但是top值和left值不会,弹性过界问题,解决方法是先存起来再赋值

多物体弹性运动框架:开关,for in,弹性公式
给每个属性都赋一个speed

碰撞运动:首先找到碰撞的临界点,再确定运动的方向,去改对应的速度,速度取反

自由落体 是加速运动
抛物线 跟自由落体差不多 ,就是left值不一样

-------------------------------
运动框架时间版
jq animate

oDate.getTime() 是到1970年的时间戳,毫秒为单位
----------------------------------

浏览器的前后箭头
html5的历史管理

-----------------------------------
Ajax
什么是Ajax:javascript 通过异步的形式操作xml文档

ajax 唯一能做的事情就是数据交互,获取数据,传输数据

Asynchronous JavaScript and XML(异步JavaScript和XML)
-节省用户操作,时间,提高用户体验,减少数据请求
-传输获取数据
应用:
数据获取,表单验证

eg1:获取1.txt的内容
/**ie6下 window没有XMLHttpRequest**/
var xhr=null;
if(window.XMLHttpRequest){
xhr=new XMLHttpRequest();//打开浏览器
}else{
xhr=new ActiveXObject('Microsoft.XHRHTTP');//打开浏览器
}

//也可以用 try catch
/*
try{
xhr=new XMLHttpRequest();
}catch(e){
xhr=new ActiveXObject('Microsoft.XHRHTTP');
}
*/
xhr.open('get','1.txt',true); //地址栏输入地址
xhr.send();// 回车 提交
xhr.onreadystatechange=function(){ //等到服务器返回内容
if(xhr.readyState==4){
alert( xhr.responseText )
}
}

抛异常
try{
//代码尝试执行这里的代码内容,如果有错误,会执行catch,并传入错误信息,不会报错
alert(a)
}catch(e){
alert(2)
}
alert('到这里了')

兼容:XMLHttpRequest 不兼容ie6
ie6用的是 ActiveXObject
new ActiveXObject('Microsoft.XMLHTTP')

表单:数据的提交(在没有用ajax的时候,form提交的原理)
action:数据提交的地址, 默认是当前页面
method:数据提交方式 get post 默认是get
get方式 和post方式的传递方式不一样
1. get: 数据的名称 和 数据对应的值用=连接,传递多个数据的时候 以 & 隔开,然后把数据放在url?后面,
url长度限制的原因,我们不要通过url传递过多的数据,每个浏览器对长度的限定不一样 ie(2000多个字符)
get 只能传字符串类型的值

2.post:方式是通过请求头header来传递数据的,头部信息,数据的串联格式是一样的(数据的名称 和 数据对应的值用=连接,传递多个数据的时候 以 & 隔开)
理论上传递数据大小无限制,实际上在php.ini中有限制
post传递的数据类型要多一些

get方式不安全,历史记录,或者直接在地址栏暴露用户隐私,同时也可以手动改数据

enctype:提交的数据的格式
http://127.0.0.1:8020/code/tast/AJAX/1.get.php?username=aaa&age=22
<form action="1.get.php">
<input type="text" name="username" />
<input type="text" name="age" />
<input type="submit" value="提交"/>
</form>

注意:本地测试ajax 一定要用localhost 不能用127.0.0.1

前端 以 post方式提交,后端就必须以 post方式接收,像下面这种 前端post,后端get 是接收不到数据内容的
<form action="1.get.php" method="post" enctype="application/x-www-form-urlencoded">
<input type="text" name="username" />
<input type="text" name="age" />
<input type="submit" value="提交" />
</form>

后端的接收注意点:
1.接收的方式必须和前端对应
2.接收的数据必须和前端对应,name中的内容

xhr.open('get','1.txt',true);
open方法
参数
1.打开方式
2.地址
3.是否异步
异步:非阻塞 前面的代码不会影响后面代码的执行
同步:阻塞 前面的代码会影响后面代码的执行,例如 加载jquery,当jquery没有加载完的时候,就不能用$,$在页面中无效

/**同步 阻塞**/
$(function(){}) //当jquery没有加载完的时候,就不能用$,$在页面中无效,阻塞模式,同步

/**异步 费阻塞**/
setTimeout(function(){
alert(1)
},2000)

alert(2); //前面的代码未执行 不会影响下面的代码执行 异步 非阻塞

同步:一个工作未完成,不会进行后续代码的执行

//什么时候用同步:当后面的代码执行的时候 需要获取到前面的数据的时候,可以用同步(前面代码走完了,才能获取到相关的数据的时候,这时候再走后面的代码)
打比方:要有食材 才能做饭,没有食材 做不了饭

大部分情况用异步,用异步才能体现ajax的好处,大部分情况不可能数据请求没成功,后面的代码就不执行了

// xhr.open('get','1.txt',true); //异步
xhr.open('get','1.txt',false);//同步
xhr.send();

/**什么时候用 同步**/
alert( xhr.responseText ); //异步 弹出来的是空,因为页面一开始请求,就开始alert
//同步出来 是具体内容

Ajax属性:
Ajax也是一个对象,它下面有很多属性

1.readyState: ajax工作状态,有5个值
onreadystatechange事件:当状态值发生改变时发生的事件
readyState属性:请求状态
0 (初始化)还没有调用open()方法
1 (载入)已调用send()方法,正在发送请求
2 (载入完成)send()方法完成,已收到全部响应内容
3 (解析)正在解析响应内容
4 (完成)响应内容解析完成,可以在客户端调用了

2.responseText: ajax请求返回的内容存放在这个属性下面,类型是 字符串 类型
3.status: 服务器状态,http状态码,数字类型,用以表示网页服务器HTTP响应状态的3位数字代码
消息(1字头)
成功(2字头)
重定向(3字头)
请求错误(4字头)
服务器错误(5字头)
xhr.onreadystatechange=function(){ //等待服务器返回内容
if(xhr.readyState==4){
if(xhr.status==200){
alert( xhr.responseText )
}else{
alert('错误'+xhr.status)
}

}
}

--------------------------------
JSON 是一个对象,注意是大写,不是小写,ie7下 不支持,需要到json.org的官网下一个文件 json2.js,页面引入,这样ie7才能支持

JSON 下有一个方法 stringify:可以把对象转化为 字符串

JSON 下还有一个方法 parse:把 字符串 转为 对应的 对象

<script>
alert( JSON );
var arr=[1,2,3];
var j={name:'alice',age:23};
alert( JSON.stringify(arr) ); // [1,2,3],字符串类型,如果是数组不会有[]
alert( JSON.stringify(j) ); //{"name":"alice","age":23}
alert( typeof JSON.stringify(arr)); //string

var s1='[1,2,3]';
alert( typeof JSON.parse(s1) +'-'+JSON.parse(s1) ); //object-1,2,3

//注意 类json的字符串 的key值必须是 双引号,后端返回来的key 也一定要是 双引号 的
var s2='{"name":"alice","age":23}';
alert( JSON.parse(s2).name ); //alice

</script>
------------------------------
ajax封装
/**
* @author Administrator
*/
function ajax(method,url,data,success){
var xhr=null;
if(window.XMLHttpRequest){
xhr=new XMLHttpRequest()
}else{
xhr=new ActiveXObject('Microsoft.XMLHTTP')
}

if( method=='get' && data ){
url=url+'?'+data;
}

xhr.open(method,url,true);
if( method == 'get' ){
xhr.send();
}else{//设置请求头
xhr.setRequestHeader();
xhr.send(data)
}

xhr.onreadystatechange=function(){
if(xhr.readyState==4){
if(xhr.status==200){
success && success(xhr.responseText)
}else{
alert('错误'+'-'+xhr.status)
}
}
}
}

--------------------------------------
ajax的get方式和post方式
ajax的get方式
1. 数据传参是 跟在 url?后面,如果更改后端输出(改为,你好你的名字),
因为缓存问题,会影响前端展示的效果,后端改了,前端还是没改,所以要做缓存处理,在url?后面链接一个随机数或者时间戳,这个自己没有测出来
2. 传递的数据如果 没有进行编码,输出的时候可能会乱码,用endodeURI进行编码
<script>
document.onclick=function(){
var xhr=null;
try{
xhr=new XMLHttpRequest()
}catch(e){
xhr=new ActiveXObject('Microsoft.XHRHTTP')
}
xhr.open('get','1.get.php?username='+encodeURI('李伟')+'&age=32&'+(new Date()).getTime(),true);
xhr.send();
xhr.onreadystatechange=function(){
if(xhr.readyState==4){
if(xhr.status==200){
alert( xhr.responseText )
}
}
}
}
</script>

ajax post方式:
1. post 方式 数据传输 ,数据放在send()中 作为参数传过去, 表单中是放在请求头里面,不可以放在url ?后面.
2. 要设置请求头 setRequestHeader(),告诉后端 提交的数据类型是编码的,后端要进行解码才能显示,如果不设置,后端就不会处理
3. post方式没有缓存问题
<script>
document.onclick=function(){
var xhr=null;
try{
xhr=new XMLHttpRequest()
}catch(e){
xhr=new ActiveXObject('Microsoft.XHRHTTP')
}
xhr.open('get','1.post.php',true);
setRequestHeader('content','application/x-www-form-urlencoded');//告诉后端发送数据类型 提交的数据类型是编码的
xhr.send('username='+encodeURI('李伟')+'&age=32&');
xhr.onreadystatechange=function(){
if(xhr.readyState==4){
if(xhr.status==200){
alert( xhr.responseText )
}
}
}
}
</script>

------------------------------------
Ajax瀑布流 有固定列 和非固定列
此处学的是 固定列

判断元素 是否到达可视区 元素到达页面的top +自身高 <document.documentElement.scrollTop+document.documentElement.clientHeight

--------------------------------------
ajax 跨域 jsonp
全称:json with padding

跨域:跨域名
一个域名下的文件去请求了和他不一样的域名下的资源文件,那么就会产生跨域请求
一个域名下请求另一个域名下的文件,会产生跨域的问题

解决方法:
1.php代理中转:用本地的php文件请求资源,html访问本地php文件
2.jsonp

JSONP : JSON with Padding
1.script标签
2.用script标签加载资源是没有跨域问题的

在资源加载进来之前定义好一个函数,这个函数接收一个参数(数据),函数里面利用这个参数做一些事情
然后需要的时候通过script标签加载对应远程文件资源,当远程的文件资源被加载进来的时候,就会去执行我们前面定义好的函数,并且把数据当作这个函数的参数传入进去

注意:在window.onload之前 要写好 fn1,fn2...,不然会引起作用域的问题,这些函数是用来取数据的,函数名后端做成动态,以便做不同的用途,函数里面不能定义函数,实在要用可以写成这样window.fn1=fuction(){}
这个案例没有涉及到ajax

豆瓣 api
http://www.douban.com/service/apidoc/reference/ http://api.douban.com/book/subjects?q=javascript&alt=json&max-results=1

使用jsonp必须遵照这样的一个规则,我们拿过来的数据作为参数 在一个函数里面 fn1([1,2,3])这种形式

百度下拉框:看控制台的请求的javascript 或者all中查看 http://suggestion.baidu.com/su?wd=a&json=1&p=3&sid=1438_9992_10496_10753_10646_10218_10686_7477_10356_10667_10096_10658_10442_10403_9950_10617&req=2&cb=jQuery1102048231458893604984_1419323278596&_=1419323278599
百度下拉框:可以不用后端,直接从百度接口提数据 :
wd是 搜索关键字 cb是回调
接口格式 http://suggestion.baidu.com/su?wd=a&cb=fn1
------------------------------------------------------
正则:
规则:让计算机能够读懂人类的规则
正则都是操作字符串的

eg:找出字符串中的所有数字
//通过正则的方法找出所有的数字
var str="sdf562ggg258ggg54rr963";
console.log(findNum(str));
function findNum(str){
return str.match(/\d+/g);
}

正则也是一个对象,写法跟数字 json类似

数组的写法:
var arr=[]; //简写
var arr=new Array(); //全称

var obj={}; //简写
var obj=new Object(); //全称

var re=//; //简写
var re=RegExp(); //全称

RegExp 是由两个单词合成 Regulation 和 Expression
建议用简写,特殊情况下用全称。

正则的简写 // 系统会认为是 注释,我们可以在里面加个a, 正则中的内容不全是字符串,如果是字符串要加引号
var re=/a/;
var re=RegExp('a');

1.test()方法:正则去匹配字符串,如果匹配成功,返回真,如果匹配失败,返回假
字符串判断:返回真假
写法:正则.test(字符串)
例子:是否有不是数字的字符
var str="abcdef";
var re=/b/;
alert(re.test(str)) //true

re=/bc/ alert(re.test(str)) //true
re=/bd/ alert(re.test(str)) //false

转义字符:
\s: 空格
\S: 非空格
\d: 数字
\D: 非数字
\w: 字符 (字符:字母,数字,下划线)
\W: 非字符

var str="2222222222222222222";
var re=/\D/;
if(re.test(str)){
alert('不全是数字')
}else{
alert('全是数字')
}

2.search()

字符串搜索:返回出现的位置,类似indexOf()
写法:字符串.search(正则)
忽略大小写:i——ignore
正则中默认是区分大小写的,如果不区分大小写,在正则的最后价格标识 i /a/i

var str="sadfsdf";
var re=/df/;
alert( str.search(re) ) //2

//不区分大小写
var re=/A/i;
alert( str.search(re) ) //1

全称不分大小写的方法:
var re=new RegExp('A','i') //i 作为第二个参数,要用引号

3.match() 正则匹配字符串,如果匹配成功,返回匹配成功的数组,如果不成功,返回null
获取匹配的项目:返回数组 或null
写法:字符串.match(正则)
量词:+ 匹配不确定的位数
全局匹配:g——global
例子:找出所有数字

正则默认:匹配成功就会结束,不会继续匹配
var str="sdf56sdfeer56rt t22gdrtret123ertert986";
var re=/\d/;
alert(str.match(re)) //5
如果想全部查找,就要加标识 g 全局匹配

var re=/\d/g; // \d 每次匹配的是一位
alert(str.match(re)) // 5,6,5,6,2,2,1,2,3,9,8,6

如果要想 数字根据 位数来匹配 就要用到量词
量词:+ 至少出现一次>=1 匹配不确定的位数
/\d+/g 匹配数字类型至少一位

var re=/\d+/g;
alert(str.match(re)) // 56,56,22,123,986

4.replace() 正则去匹配字符串,匹配成功的字符 替换成 新的字符串
替换所有匹配
返回替换后的字符串
写法:字符串.replace(正则,想替换的)
例子:敏感词过滤

replace 第二个参数可以是字符串 也可以是一个函数,函数的第一个参数就是匹配成功的字符
replace(re,function(str){})

var str="aaa";
var re=/a/;
alert(str.replace(re,'b')) //baa

var re=/a/g; //g是全局匹配,匹配所有的,不是第一个匹配成功就结束
alert(str.replace(re,'b')) //bbb

var re=/a+/g; //+至少匹配一次 aaa连在一起的,看做是一个
alert(str.replace(re,'b')) //b

|:或

匹配子项
例子:日期格式化
var str="2014-12-24";
/*
var re=/\d+/g;
str.replace(re,function($0){
alert($0) //弹三次 分别是 2014 12 24
})
*/

/*var re=/\d+-/g; //数字加-
str.replace(re,function($0){
alert($0) //弹两次 分别是 2014- 12-
})*/

/* var re=/\d-+/g; //一个数字加一个-
str.replace(re,function($0){
alert($0) //弹两次 分别是 4- 2-
})*/

//把正则的整体叫做(母亲)
//然后把左边第一个小括号里面的正则,叫做这个第一个子项(母亲的第一个孩子)
//第二个小括号就是第二个孩子

var re = /(\d+)(-)/g;
str=str.replace(re,function($0,$1,$2){
//第一个参数:$0(母亲),第二个参数 : $1(第一个孩子)
//,第二个参数 : $1(第二个孩子)
return $1+'.' //弹两次 分别是 4- 2-
})

alert(str); //2014.12.24
match 也有匹配子项
var str="abcdef";
var re=/(a)(b)(c)/;
alert( str.match(re));//abc,a,b,c 当不是全局的时候

-------------------------------------------------
字符类:一组相似的元素 [] 一个[] 整体代表一个字符
var str="abc";
var re=/a[bcd]e/; //[]中的是或的意思,[bcd]代表的是str中的第二位,只要str中的第二位能够与中括号中的字符匹配成功,就是true
console.log( re.test(str) ) //true

var str1="abde";
var re1=/a[bcd]e/;//e对应的是str的d,对应不上
console.log( re1.test(str) ) //false

^ 如果写在[]中代表的是排除的意思
var str2="abc";
var re2=/a[^bcd]c/; //^相当于! ,意思是str2的第二位不能出现bcd,如果出现了就是false
console.log( re2.test(str2) ) //false

var str3="awc";
var re3=/a[^bcd]c/; //^相当于! ,意思是str2的第二位不能出现bcd,如果出现了就是false
console.log( re3.test(str3) ) //true

范围:范围的顺序 从小到大
[a-z]、[0-9]
例子:id[0-9]——id0、id5

var str="abc";
var re=/a[a-z]c/;
console.log( re.test(str) ) //true

范围不一定要从a-z 0-9 也可以是[e-z]这样

同样[] 中间还是或的关系,整体代表一位,还可以这样写[a-z0-9A-z]
如果想针对多位,用[]+,+针对的是字符类

var str2="a56b";
var re2=/a[0-9]+b/; //[0-9]+ 代表的是至少一位
console.log( re2.test(str2) ) //true

过滤html标签
<textarea id="text1" style="border:1px solid black" cols=40 rows="20"></textarea>
<input type="button" value="过滤html标签" />
<textarea id="text2" style="border:1px solid black" cols=40 rows="20"></textarea>
<script>
var text1=document.getElementById('text1');
var text2=document.getElementById('text2');
var oBtn=document.getElementsByTagName('input')[0];

var re=/<[^>]+>/g;// 过滤掉<...> 只要<>中间不是> 全都过滤掉 全局
//第二种写法 <> 中间的 字符 非字符都包括了 可以写成 /<[\w\W]>/
oBtn.onclick=function(){
text2.value=text1.value.replace(re, '')
}
</script>
--------------------------------------
正则中的转义字符

.(点)——任意字符
\. 代表真正的.
\d、\w、\s 、\b
\D、\W、\S 、\B
\1 重复子项
例子
获取class元素
找重复项最多的字符和个数

\b 独立的部分 (起始,结束,空格)
\B 非独立的部分

/*var str="abc";
var re=/a.c/;//. 任意字符 \.真正的点
console.log( re.test(str) ) //true*/

// \b独立部分
var str="onetwo";
var re=/\bone/; //one的前面是 起始 位置
console.log( re.test(str) ) //true

var str="onetwo";
var re=/one\b/; //one的后面不是 起始 位置
console.log( re.test(str) ) //false

var str="one two";
var re=/one\b/; //one的后面是 空格 true
console.log( re.test(str) )

当正则需要传参的时候,一定要用全称的写法
var re=new RegExp(变量)

eg:正则选取class
window.onload=function(){
var oUl=document.getElementsByTagName('ul')[0];
var aLi=oUl.getElementsByTagName('li');

var aLi1=getByClass(oUl,'box');
for(var i=0;i<aLi1.length;i++){
aLi1[i].style.background="blue"
}

function getByClass(oParent,className){
var aS=oParent.getElementsByTagName('*');
var arr=[];
for(var i=0;i<aS.length;i++){
var s=aS[i].className;
// /\b+className+\b/
var re=new RegExp('\\b'+className+'\\b' );
if(re.test(s)) arr.push( aS[i] );
break
}
return arr
}
}

<ul>
<li>111</li>
<li class="box box3">111</li>
<li>111</li>
<li class="boxbox1">111</li>
<li class="box">111</li>
</ul>

-------------------
\1 重复的第一个子项
\2 重复的第二个子项,其他以此类推

var str="abca";
var re=/(a)(b)(c)\1/;// \1代表第一个子项a,与str的最后一个字符匹配成功 true
//var re=/(a)(b)(c)\2/;// \1代表第二个子项b,与str的最后一个字符匹配不成功 false
console.log( re.test(str) )

eg:找重复项最多的字符和出现的个数
var str="sdfsdfsewssssssfdffdfseeegvaaaadjl;kjlkss";
//先给str进行排序,让相同的字符在一起
str=str.split('').sort().join('');
//alert(str);//;aaaadddddeeeeffffffgjjkkllssssssssssssvw
var re=/(\w)\1+/g; //多位重复的子项
var value='';
var index=0;
str.replace(re,function($0,$1){
//alert($0) //aaaa,ddddd,eeee,ffffff,g,jj,kk,ll,ssssssssssss,vw
if(index < $0.length){
index=$0.length;
value=$1 //s
}
})

alert('重复最多的子项是:'+value+'.出现的个数是:'+index)

--------------------------------
量词:不确定的正则的个数 {}
{4,7} 最少出现4次,最多出现7次
{4,} 最少出现4次
{4} 正好出现4次
+ 至少出现一次,{1,}的简写

+ : {1,} //\d{1,}
? : {0,1} : 出现0次或者1次
* : {0,} : 至少出现0次*/

什么是量词
出现的次数
{n,m},至少出现n次,最多m次
例子:查找QQ号

常用量词
{n,} 至少n次
*: {0,} 至少出现0次
?:{0,1} 零次或一次
+: {1,} 一次或任意次
{n} 正好 n次

\d{4,9} 至少4个任意数字 最多9个任意数字

eg:
//* 和 + 的区别 re.test(str)
var str="ab";
var re=/ab+/; //true
var re=/ac+/;//false
var re=/ac*/;//true

//^ : 正则的最开始位置,就代笔起始的意思
//$ : 正则的最后位置 , 就代笔结束的意思

eg:判断是不是QQ号:
//^ : 正则的最开始位置,就代笔起始的意思
//$ : 正则的最后位置 , 就代笔结束的意思
如果在验证的时候不加 首尾验证,那么首和尾就可能是别的东西

var aInput=document.getElementsByTagName('input');
//必须是数字,至少5位,第一位不能为0
var re=/^[1-9]\d{4,11}$/; // \d{4,11} 第二位开始必须是数字,并且最少4个任意数字,最多11个数字
aInput[1].onclick=function(){
if(re.test(aInput[0].value)){
alert('是QQ号')
}else{
alert('不是QQ号')
}
}

eg:去掉空格
var str=" abc d e f ";
alert( '('+trim(str)+')' );//(abcdef)
function trim(str){
var re=/^\s+|\s+|\s+$/g;
return str.replace(re,'')
}

高级表单校验
匹配中文:[\u4e00-\u9fa5]
行首行尾空格:^\s*|\s*$
Email:^\w+@[a-z0-9]+(\.[a-z]+){1,3}$
网址:[a-zA-z]+://[^\s]*
QQ号:[1-9][0-9]{4,9}
邮政编码:[1-9]\d{5}
身份证:[1-9]\d{14}|[1-9]\d{17}|[1-9]\d{16}x

// 身份证号码为15位或者18位,15位时全为数字,18位前17位为数字,最后一位是校验位,可能为数字或字符X
var reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
或者 [1-9]\d{14}|[1-9]\d{17}|[1-9]\d{16}x

----------------------------------------
1.字符串操作包括哪些?举例说明
-split,indexOf,substring,slice,charAt()

2.什么是正则表达式?如何创建正则对象?
-是一种规则,让计算机能够读懂人类的规则,用来操作字符串的
var re=//;
var re=new RegExp()

正则有几种选项?分别是什么意思?

Test,search、match、replace是做什么的?怎么用?
-re.test(str) 返回真假
str.search(re) 返回下标
str.match(re) 返回匹配的数组
str.replace(re,替换的东西) 返回匹配的替换

字符类([])包括几种情况?
-字符类 [] 一种相似的元素 []中的代表或的意思
[^abc] []中的^代表排除的意思,此处的意思是不是a 也不是b 也不是c

正则有哪些转义字符?分别是什么意思?
- \d : 数字 \D : 非数字
\s :空格 \S : 非空格
\w :字符 \W : 非字符
\b :独立部分 \B : 非独立部分
\1 : 重复的子项

什么是量词?各个量词分别有什么作用?
-量词代表至少出现一次 或者 一位数字

举几个正则表达式的例子,比如:邮件、中文等
-邮件 /^\w+@(.[a-z1-9])+{1,3}$/
-中文

什么叫“命名空间”,有什么作用?

作业:
1.检查字符串是否含有字符a
var str="bacdef";
var re=/a/;
if(re.test(str)){
alert('有字母a')
}else{
alert('没有字母a')
}

2.检查是否有数字
var str="bacdef22";
var re=/\d/;
if(re.test(str)){
alert('有数字')
}else{
alert('没有数字')
}

3.找出字符串中所有的数字
var str="bac343def22dsf567";
alert( findNum(str) ) //343,22,567
function findNum(str){
var re=/\d+/g;
return str.match(re)
}

4.把字符串中所有的数字 替换成 *
var str="bac343def22dsf567";
var re=/\d+/g;
str=str.replace(re,function(str){ //str指的是匹配的正则
var value='';
for(var i=0;i<str.length;i++){
value+='*'
}
return value
})

alert(str)

"^\d+$"  //非负整数(正整数 + 0)
"^[0-9]*[1-9][0-9]*$"  //正整数
"^((-\d+)|(0+))$"  //非正整数(负整数 + 0)
"^-[0-9]*[1-9][0-9]*$"  //负整数
"^-?\d+$"    //整数
"^\d+(\.\d+)?$"  //非负浮点数(正浮点数 + 0)
"^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$"  //正浮点数
"^((-\d+(\.\d+)?)|(0+(\.0+)?))$"  //非正浮点数(负浮点数 + 0)
"^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$"  //负浮点数
"^(-?\d+)(\.\d+)?$"  //浮点数
"^[A-Za-z]+$"  //由26个英文字母组成的字符串
"^[A-Z]+$"  //由26个英文字母的大写组成的字符串
"^[a-z]+$"  //由26个英文字母的小写组成的字符串
"^[A-Za-z0-9]+$"  //由数字和26个英文字母组成的字符串
"^\w+$"  //由数字、26个英文字母或者下划线组成的字符串
"^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$"    //email地址
"^[a-zA-z]+://(\w+(-\w+)*)(\.(\w+(-\w+)*))*(\?\S*)?$"  //url
"^[A-Za-z0-9_]*$"

------------------------------
cloneNode() 如果参数是true,就一起复制里面的子节点,如果是false,就只复制当前节点

淡入淡出焦点图的li都是定位为absolute的
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: