[TOC]

JavaScript负责页面中的的行为。它是一门运行在浏览器端的脚本语言。

0o.参考资料

01.网课内容

00.JS的简介与历史

https://zh.javascript.info/intro

01.JS的编写的位置

1.可以编写在html和属性中 (onclick事件超链接href中) 不推荐 代码耦合

<button onclick="alert('hello');">我是按钮button>
<a href="javascript:alert('aaa');">超链接a>

2.可以编写到script标签中

<script type="text/javascript">script>//不写type也会默认装填

3.可以将代码编写到外部的js文件中,然后通过标签将其引入

script标签一旦用于引入外部文件了,就不能在编写代码了,即使编写了浏览器也会忽略 ,如果需要则可以在创建一个新的script标签用于编写内部代码(如果已经引入外部标签 就不能编写代码了 写了也会忽略)

<script type="text/javascript" src="js/script.js">script>

03.JS基本的输出语句

alert("要输出的内容");

该语句会在浏览器窗口中弹出一个警告框

document.write("要输出的内容");

该内容将会被写到body标签中,并在页面中显示

console.log("要输出的内容");

该内容会被写到开发者工具的控制台中

04.JS基础语法

js函数声明不需要;分号,但是赋值语句要加;分号 实际上不加也不会报错 加上最好 符合规范

function functionName(arg0,arg1,arg2){
}
var functionName=function(arg0,arg1,arg2){
};(注意分号)

单行注释

//注释内容

多行注释

/*
注释内容
/*

JS严格区分大小写

JS中每条语句以分号(;)结尾如果不写分号,浏览器会自动添加,但是会消耗一些系统资源, 而且有些时候,浏览器会加错分号,所以在开发中分号必须写

JS中会自动忽略多个空格和换行,所以我们可以利用空格和换行对代码进行格式化。

05.JS字面量和变量

01.字面量

字面量实际上就是一些固定的值,比如 1 2 3 4 true false null NaN “hello”
字面量都是不可以改变的。—————-和常量概念类似

由于字面量不是很方便使用,所以在JS中很少直接使用字面量

02.变量

变量可以用来保存字面量,并且可以保存任意的字面量

一般都是通过变量来使用字面量,而不直接使用字面量,而且也可以通过变量来对字面量进行一个描述

声明变量

使用var关键字来声明一个变量

var a;

为变量赋值

a = 1;

声明和赋值同时进行

var a = 456;

06.JS标识符

在JS中所有的可以自主命名的内容,都可以认为是一个标识符,
是标识符就应该遵守标识符的规范。

比如:变量名、函数名、属性名

规范:
1.标识符中可以含有字母、数字、_、$
2.标识符不能以数字开头
3.标识符不能是JS中的关键字和保留字

4.标识符一般采用驼峰命名法

  • 首字母小写,每个单词的开头字母大写,其余字母小写
  • xxxYyyZzz
  • helloWorld

07.JS六种数据类型

数据类型就是自面临的类型,JS中一共分成六种数据类型 5个基本数据类型+object

  1. String 字符串
  2. Number 数值
  3. Boolean 布尔值
  4. Null 空值
  5. Undefined 未定义
  6. Object 对象

其中基本数据类型有 5个

typeof运算符检查数据类型 注意无大写

var b =123
console.log(typeofnum b)//number

01.string字符串类型

JS中的字符串需要使用引号引起来双引号或单引号都行
在字符串中使用\作为转义字符

\'  ==> '
\"  ==> "
\n  ==> 换行
\t  ==> 制表符
\\  ==> \

使用typeof运算符检查字符串时,会返回”string”

字符串方法

1、charCodeAt方法返回一个整数,代表指定位置字符的Unicode编码。

strObj.charCodeAt(index)
说明:
index将被处理字符的从零开始计数的编号。有效值为0到字符串长度减1的数字。
如果指定位置没有字符,将返回NaN。
例如:
var str = "ABC";
str.charCodeAt(0);
结果:65

2、fromCharCode方法从一些Unicode字符串中返回一个字符串。

String.fromCharCode([code1[,code2...]])
说明:
code1,code2...是要转换为字符串的Unicode字符串序列。如果没有参数,结果为空字符串。
例如:
String.fromCharCode(65,66,112);
结果:ABp

3、charAt方法返回指定索引位置处的字符。如果超出有效范围的索引值返回空字符串。

strObj.charAt(index)
说明:
index想得到的字符的基于零的索引。有效值是0与字符串长度减一之间的值。
例如:
var str = "ABC";
str.charAt(1);
结果:B

4、slice方法返回字符串的片段。

strObj.slice(start[,end])
说明:
start下标从0开始的strObj指定部分其实索引。如果start为负,将它作为length+start处理(倒着来),此处length为字符串的长度。
end小标从0开始的strObj指定部分结束索引。如果end为负,将它作为length+end处理,此处length为字符串的长度。
例如:
012345
var str = "ABCDEF";
str.slice(2,4);
结果:CD

5、substring方法返回位于String对象中指定位置的子字符串。

strObj.substring(start,end)
说明:
start指明子字符串的起始位置,该索引从0开始起算。
end指明子字符串的结束位置,该索引从0开始起算。
substring方法使用start和end两者中的较小值作为子字符串的起始点。如果start或end为NaN或者为负数,那么将其替换为0。
例如:
012345
var str = "ABCDEF";
str.substring(2,4); // 或 str.substring(4,2);
结果:CD

6、substr方法返回一个从指定位置开始的指定长度的子字符串。

strObj.substr(start[,length])
说明:
start所需的子字符串的起始位置。字符串中的第一个字符的索引为0。
length在返回的子字符串中应包括的字符个数。
例如:
012345
var str = "ABCDEF";
str.substr(2,4);
结果:CDEF

7、indexOf方法放回String对象内第一次出现子字符串位置。如果没有找到子字符串,则返回-1。

strObj.indexOf(substr[,startIndex])
说明:
substr要在String对象中查找的子字符串。
startIndex该整数值指出在String对象内开始查找的索引。如果省略,则从字符串的开始处查找。
例如:
01234567
var str = "ABCDECDF";
str.indexOf("CD",1); // 由1位置从左向右查找 123...
结果:2

8、lastIndexOf方法返回String对象中字符串最后出现的位置。如果没有匹配到子字符串,则返回-1。

strObj.lastIndexOf(substr[,startindex])
说明:
substr要在String对象内查找的子字符串。
startindex该整数值指出在String对象内进行查找的开始索引位置。如果省略,则查找从字符串的末尾开始。
例如:
01234567
var str = "ABCDECDF";
str.lastIndexOf("CD",6); // 由6位置从右向左查找 ...456
结果:5

9、search方法返回与正则表达式查找内容匹配的第一个字符串的位置。

strObj.search(reExp)
说明:
reExp包含正则表达式模式和可用标志的正则表达式对象。
例如:
var str = "ABCDECDF";
str.search("CD"); // 或 str.search(/CD/i);
结果:2

10、concat方法返回字符串值,该值包含了两个或多个提供的字符串的连接。

str.concat([string1[,string2...]])
说明:
string1,string2要和所有其他指定的字符串进行连接的String对象或文字。
例如:
var str = "ABCDEF";
str.concat("ABCDEF","ABC");
结果:ABCDEFABCDEFABC

11、将一个字符串分割为子字符串,然后将结果作为字符串数组返回。

strObj.split([separator[,limit]])
说明:
separator字符串或 正则表达式 对象,它标识了分隔字符串时使用的是一个还是多个字符。如果忽略该选项,返回包含整个字符串的单一元素数组。
limit该值用来限制返回数组中的元素个数。
例如:
var str = "AA BB CC DD EE FF";
alert(str.split(" ",3));
结果:
AA,BB,CC

12、toLowerCase方法返回一个字符串,该字符串中的字母被转换成小写。

例如:
var str = "ABCabc";
str.toLowerCase();
结果:abcabc

13、toUpperCase方法返回一个字符串,该字符串中的所有字母都被转换为大写字母。

例如:
var str = "ABCabc";
str.toUpperCase();
结果:ABCABC

14、字符串翻转

var name = "My city is WH";
var resultStr = name.split('').reverse().join(''); 
console.log(resultStr);  // HW si ytic yM

15、去除空格trim()

```javascript var str = “ Runoob “; alert(str.trim()); //“Runoob”

//替换 function myTrim(x) { return x.replace(/^\s+|\s+$/gm,’’); }

function myFunction() { var str = myTrim(“ Runoob “); alert(str); }




<a name="3101bdeb"></a>
### 02.number数值类型

**JS中所有的整数和浮点数都是Number类型**

最大能表示的值:Number.MAX_VALUE = 1.7976931348623157e+308

最小能表示的值:Number.MIN_VALUE = 5e-324

特殊的数字:能赋值给变量<br />
Infinity 正无穷 a = Infinity ,能赋值<br />
-Infinity 负无穷 使用typeof 检查Infinity 也会返回number<br />
NaN 非法数字(Not A Number)  使用typeof 检查NaN也会返回number<br />
其他进制的数字的表示:<br />
0b 开头表示二进制,但是不是所有的浏览器都支持<br />
0 开头表示八进制<br />
0x 开头表示十六进制

使用typeof检查一个Number类型的数据时,会返回"number"<br />
(包括NaN 和 Infinity)

<a name="82c62b02"></a>
### 03.boolean数据类型

布尔值主要用来进行逻辑判断,布尔值只有两个<br />
true 逻辑的真<br />
false 逻辑的假<br />
使用typeof检查一个布尔值时,会返回"boolean"

```javascript
//注意 -1在js中为true
while(-1){

}//---->死循环

04.null数据类型

null专门用来表示为空的对象,Null类型的值只有一个
null
使用typeof检查一个Null类型的值时会返回”object”

05.undefine数据类型

如果声明一个变量但是没有为变量赋值此时变量的值就是undefined
该类型的值只有一个 undefined
使用typeof检查一个Undefined类型的值时,会返回”undefined”

var b
console.log(b)//undefine

06.判断数据类型

1: typeof

返回数据类型,包含这7种: number、boolean、symbol、string、object、undefined、function。

typeof null 返回类型错误,返回object

引用类型,除了function返回function类型外,其他均返回object。

其中,null 有属于自己的数据类型 Null , 引用类型中的 数组、日期、正则 也都有属于自己的具体类型,而 typeof 对于这些类型的处理,只返回了处于其原型链最顶端的 Object 类型,没有错,但不是我们想要的结果。

2:toString 这个是最完美的

toString() 是 Object 的原型方法,调用该方法,默认返回当前对象的 [[Class]] 。这是一个内部属性,其格式为 [object Xxx] ,其中 Xxx 就是对象的类型。

对于 Object 对象,直接调用 toString() 就能返回 [object Object] 。而对于其他对象,则需要通过 call / apply 来调用才能返回正确的类型信息。

判断类型举例:

Object.prototype.toString.call('') ;   // [object String]
Object.prototype.toString.call(1) ;    // [object Number]
Object.prototype.toString.call(true) ; // [object Boolean]
Object.prototype.toString.call(Symbol()); //[object Symbol]
Object.prototype.toString.call(undefined) ; // [object Undefined]
Object.prototype.toString.call(null) ; // [object Null]
Object.prototype.toString.call(new Function()) ; // [object Function]
Object.prototype.toString.call(new Date()) ; // [object Date]
Object.prototype.toString.call([]) ; // [object Array]
Object.prototype.toString.call(new RegExp()) ; // [object RegExp]
Object.prototype.toString.call(new Error()) ; // [object Error]
Object.prototype.toString.call(document) ; // [object HTMLDocument]
Object.prototype.toString.call(window) ; //[object global] window 是全局对象 global 的引用

3:constructor

constructor是原型prototype的一个属性,当函数被定义时候,js引擎会为函数添加原型prototype,并且这个prototype中constructor属性指向函数引用, 因此重写prototype会丢失原来的constructor。

不过这种方法有问题:

1:null 和 undefined 无constructor,这种方法判断不了。

2:还有,如果自定义对象,开发者重写prototype之后,原有的constructor会丢失,因此,为了规范开发,在重写对象原型时一般都需要重新给 constructor 赋值,以保证对象实例的类型不被篡改。

00.JavaScript基础 - 图1

4:instanceof

instanceof 是用来判断 A 是否为 B 的实例,表达式为:A instanceof B,如果 A 是 B 的实例,则返回 true,否则返回 false。 在这里需要特别注意的是:instanceof 检测的是原型

00.JavaScript基础 - 图2 由上图可以看出[]的原型指向Array.prototype,间接指向Object.prototype, 因此 [] instanceof Array 返回true, [] instanceof Object 也返回true。

instanceof 只能用来判断两个对象是否属于实例关系, 而不能判断一个对象实例具体属于哪种类型。

08.JS强制类型转化

类型转换就是指将其他的数据类型,转换为 String Number 或 Boolean

01.转换为字符

01.调用被转换数据的toString()方法

例子:

var a = 123;
a = a.toString();

注意: 这个方法不适用于null和undefined
由于这两个类型的数据中没有方法,所以调用toString()时会报错

02.调用String()函数 优先

例子:

var a = 123;
a = String(a);
console.log(a)//string

原理: 对于Number Boolean String都会调用他们的toString()方法来将其转换为字符串,对于null值,直接转换为字符串”null”。对于undefined直接转换为字符串”undefined” 适应性更好

03.为任意的数据类型 +” “ 隐式的类型转换

例子:

var a = true;
a = a + "";

原理:和String()函数一样

02.转换为数字

01.调用Number()函数

例子:

var s = "123";
s = Number(s);

转换的情况:

1.字符串 > 数字
  如果字符串是一个合法的数字,则直接转换为对应的数字
  如果字符串是一个非法的数字,则转换为NaN
  如果是一个空串或纯空格的字符串,则转换为0
2.布尔值 > 数字
  true转换为1
  false转换为0
3.空值 > 数字
  null转换为0
4.未定义 > 数字
  undefined 转换为NaN

02.调用parseInt()或parseFloat()

这两个函数专门用来将一个字符串转换为数字的

如果对非String使用parseInt()或parseFloat(),它会 先将其转换为String然后在操作 parseInt()
可以将 一个字符串中的有效的整数位提取出来,并转换为Number
例子:

var a = "123.456px";
a = parseInt(a);
console.log(a)//123

//注意 如果123在字符后面则提取不出
var a = "px123.456";
a = parseInt(a);
console.log(a)//NaN

如果需要可以在parseInt()中指定一个第二个参数,来指定进制parseFloat()可以将一个 字符串中的有效的小数位提取出来,并转换为Number
例子:

var a = "123.456px";
a = parseFloat(a);
console.log(a)//123.456

注意:对于非String使用parseInt()或parseFloat() ,它会先将其先转换为String,然后再操作

var a = true;
a = parseInt(a)
console.log(a);//"Nan"

使用一元的+来进行隐式的类型转换
例子:

var a = "123";
a = +a;

原理:和Number()函数一样

03.转换为boolean数值

01.使用Boolean()函数

例子:

var s = "false";
s = Boolean(s);
console,log(s)//false

转换的情况
字符串 > 布尔
除了空串其余全是true

数值 > 布尔
除了0和NaN其余的全是true

null、undefined > 布尔
都是false

对象 > 布尔
都是true

为任意的数据类型做两次非运算,即可将其转换为布尔值
例子:

var a = "hello";
a = !!a;

09.JS进制

01.16进制 0x开头

var a = 0x10;//16

02.8进制 0开头

var a = 070;//56

03.2进制 0b开头

var a = ob10;//2 不是所有浏览器都支持  ie不支持

像“070”这种字符串,有些浏览器按8进制解析,有些按10进制解析

a = parseInt(a,10)//可以使用方法转换,指定进制

10.JS运算符

运算符也称为操作符
通过运算符可以对一个或多个值进行运算或操作

01.typeof运算符

用来检查一个变量的数据类型

typeof也属于运算符

语法:typeof 变量
它会返回一个用于描述类型的字符串作为结果

套娃的话 返回的是string

var a;
typeof(typeof a) //string

02.算数运算符

+对两个值进行加法运算并返回结果

-对两个值进行减法运算并返回结果

*对两个值进行乘法运算并返回结果
/ 对两个值进行除法运算并返回结果
% 对两个值进行取余运算并返回结果

除了加法以外,对非Number类型的值进行运算时,都会先转换为Number然后在做运算。
而做加法运算时,如果是两个字符串进行相加,则会做拼串操作,将两个字符连接为一个字符串。
任何值和字符串做加法,都会先转换为字符串,然后再拼串

03.1元运算符

一元运算符只需要一个操作数

+就是正号,不会对值产生任何影响,但是可以将一个非数字转换为数字
例子:

var a = 123;
a = +a;//123

注意,1元运算符会将数据类型转换为数字 然后再参与运算

var result = 1 + + “2” + 3;//6

-就是负号,可以对一个数字进行符号位取反
例子:

var a = 10;
a = -a;//-10

04.自增和自减

01.自增

自增可以使变量在原值的基础上自增1
自增使用 ++
自增可以使用 前++(a)后(a++)
无论是a 还是 a都会立即使原变量自增1
不同的是a和a的值是不同的,
++a的值是变量的新值(自增后的值)

var a = 1;
console.log(++a);//2

a++的值是变量的原值(自增前的值)

var a = 1;
console.log(a++);//1
console.log(a);//2

综合测试

var d =20
var result = d++ + ++d + d//20+22+22
console.log(result)//64

02自减

自减可以使变量在原值的基础上自减1
自减使用
自减可以使用 前(a)后(a)
无论是a 还是 a都会立即使原变量自减1
不同的是a和a的值是不同的,
a的值是变量的新值(自减后的值)
a的值是变量的原值(自减前的值)

05.逻辑运算符

01.非运算符 !

  • 非运算可以对一个布尔值进行取反,true变false false边true
  • 当对非布尔值使用!时,会先将其转换为布尔值然后再取反
  • 我们可以利用!来将其他的数据类型转换为布尔值
  • 为任意的数据类型做两次非运算,即可将其转换为布尔值
var a = true
a = !a;
console.log(a)//false
var a = 0;
a = !a;
console.log(a)//true 当对非布尔值使用!时,会先将其转换为布尔值然后再取反
var a = 'hello'
a = !!a;
console.log(a)//true 为任意的数据类型做两次非运算,即可将其转换为布尔值

02.与运算符 &&

  • &&可以对符号两侧的值进行与运算

  • 只有两端的值都为true时,才会返回true。只要有一个false就会返回false。

  • 与是一个短路的与,如果第一个值是false,则不再检查第二个值

  • 对于非布尔值,它会将其转换为布尔值然后做运算,并返回原值
    本质规则:
    1.如果第一个值为false,则返回第一个值
    2.如果第一个值为true,则返回第二个值

  • 短路规则

    false&&alert("我不会执行")//后面的被短路
    

03.或运算符 ||

  • ||可以对符号两侧的值进行或运算

  • 只有两端都是false时,才会返回false。只要有一个true,就会返回true。

  • 或是一个短路的或,如果第一个值是true,则不再检查第二个值

  • 对于非布尔值,它会将其转换为布尔值然后做运算,并返回原值
    本质规则:
    1.如果第一个值为true,则返回第一个值
    2.如果第一个值为false,则返回第二个值

  • 短路规则

    true||alert("我不会执行")//后面的被短路
    
result = 2 || 1;//2 第一个为true直接返回第一个值
result = -1 || "你好"//-1 第一个为true直接返回第一个值

06.赋值运算符

01.等于号 =

可以将符号右侧的值赋值给左侧变量

a += 5 相当于 a = a+5
a -= 5  相当于 a = a-5
a *= 5 相当于 a = a*5
a /= 5 相当于 a = a/5
a %= 5 相当于 a = a%5
var str = "hello";  str += "world";

07.关系运算符

关系运算符用来比较两个值之间的大小关系的

>

=

<

<=

  • 关系运算符的规则和数学中一致,用来比较两个值之间的关系,
  • 如果关系成立则返回true,关系不成立则返回false。
  • 如果比较的两个值是非数值,会将其转换为Number然后再比较。
  • 如果比较的两个值都是字符串,此时会比较字符串的Unicode编码,而不会转换为Number。

08.相等运算符 ==

  • 相等,判断左右两个值是否相等,如果相等返回true,如果不等返回false

  • 相等会自动对两个值进行类型转换,如果 对不同的类型进行比较,会将其转换为相同的类型然后再比较,转换后相等它也会返回true,null == undifined

    console.log(null == 0);//false
    console.log(undefined ==null)//true undefined衍生自null
    console.log(NaN == NaN)//false NaN不与任何值相等
    

09.不相等运算符 !=

不等,判断左右两个值是否不等,如果不等则返回true,如果相等则返回false
不等也会做自动的类型转换。

10.全等运算符 ===


全等,判断左右两个值是否全等,它和相等类似,只不过它不会进行自动的类型转换,
如果两个值的类型不同,则直接返回false

console.log("123" == 123)//true
console.log("123" === 123)//false
console.log(null == undefined)//true
console.log(null === undefined)//false

11.不全等运算符 !==

不全等,和不等类似,但是它不会进行自动的类型转换,如果两个值的类型不同,它会直接返回true

特殊的值:
null和undefined
由于undefined衍生自null,所以 null == undefined 会返回true。
但是 null === undefined 会返回false。
NaN
NaN不与任何值相等,报告它自身 NaN == NaN //false

判断一个值是否是NaN
使用isNaN()函数

12.JS条件运算符(三元运算符)

语法:条件表达式?语句1:语句2;
执行流程:

  • 先对条件表达式求值判断,

  • 如果判断结果为true,则执行语句1,并返回执行结果

  • 如果判断结果为false,则执行语句2,并返回执行结果

    var a = 10;
    var b =20;
    a>b ? alert('a大'):alert('b大');//执行后面的
    

13.JS优先级

01.js变量可以同时赋值

var a,b,c;
var a=0,b=1,c=0;

02.js优先级:

和数学中一样,JS中的运算符也是具有优先级的,
比如 先乘除 后加减 先与 后或
具体的优先级可以参考优先级的表格,在表格中越靠上的优先级越高,
优先级越高的越优先计算,优先级相同的,从左往右计算。
优先级不需要记忆,如果越到拿不准的,使用()来改变优先级。

11.JS流程控制语句

程序都是自上向下的顺序执行的,
通过流程控制语句可以改变程序执行的顺序,或者反复的执行某一段的程序。

01.if语句

条件判断语句也称为if语句
语法一:

 if(条件表达式){
     语句...
 }
执行流程:  
if语句执行时,会先对条件表达式进行求值判断,  
如果值为true,则执行if后的语句  
如果值为false,则不执行

语法二:

if(条件表达式){
    语句...
}else{
    语句...

}
执行流程:  
if...else语句执行时,会对条件表达式进行求值判断,  
    如果值为true,则执行if后的语句  
    如果值为false,则执行else后的语句

语法三:

if(条件表达式){
    语句...

}else if(条件表达式){
    语句...

}else if(条件表达式){
    语句...

}else if(条件表达式){
    语句...

}else{
    语句...

}
执行流程  
 if...else if...else语句执行时,会自上至下依次对条件表达式进行求值判断,  
    如果判断结果为true,则执行当前if后的语句,执行完成后语句结束。  
    如果判断结果为false,则继续向下判断,直到找到为true的为止。  
    如果所有的条件表达式都是false,则执行else后的语句

02条件分支语句(switch语句)

语法:

switch(条件表达式){
    case 表达式:
        语句...;
        break;
    case 表达式:
        语句...;
        break;
    case 表达式:
        语句...;
        break;
    default:
        语句...;
        break;
}

执行流程:
switch…case…语句在执行时,会依次将case后的表达式的值和switch后的表达式的值进行全等比较,
如果比较结果为false,则继续向下比较。如果比较结果为true,则从当前case处开始向下执行代码。
如果所有的case判断结果都为false,则从default处开始执行代码。

通过循环语句可以反复执行某些语句多次

03.while循环

语法:

while(条件表达式){
    语句...

}

执行流程:
while语句在执行时,会先对条件表达式进行求值判断,
如果判断结果为false,则终止循环
如果判断结果为true,则执行循环体
循环体执行完毕,继续对条件表达式进行求值判断,依此类推

do…while循环
语法:

do{
语句...

}while(条件表达式)

执行流程
do…while在执行时,会先执行do后的循环体,然后在对条件表达式进行判断,
如果判断判断结果为false,则终止循环。
如果判断结果为true,则继续执行循环体,依此类推

和while的区别:
while:先判断后执行
do…while: 先执行后判断
do…while可以确保循环体至少执行一次。

04.for循环

01.基础使用

语法:

for(①初始化表达式 ; ②条件表达式 ; ④更新表达式){
    ③语句...
}

执行流程:

  • 首先执行①初始化表达式,初始化一个变量,
  • 然后对②条件表达式进行求值判断,如果为false则终止循环
    如果判断结果为true,则执行③循环体
  • 循环体执行完毕,执行④更新表达式,对变量进行更新。
  • 更新表达式执行完毕重复②

死循环

while(true){
}
for(;;){
}

02.for循环增强使用

.01.for in

  • 对象 in obj

    • let obj={'name':'programmer','age':'22','height':'180'};
      for(let i in obj){
      console.log(i,obj[i])//i:键 obj[i]:值
      /*
      name programmer        
      age 22
      height 180
      */
      }
      
  • 数组 in arr

    • var arr = ['a', 'b', 'c', 'd'];
      for (let a in arr) {
      console.log(a); // 0 1 2 3
      }
      
  • 使用for-in可以遍历数组,但是会存在以下问题:

    • 1.index索引为字符串型数字(注意,非数字),不能直接进行几何运算。
    • 2.遍历顺序有可能不是按照实际数组的内部顺序(可能按照随机顺序)。
    • 3.使用for-in会遍历数组所有的可枚举属性,包括原型。原型方法method和name属性都会被遍历出来,通常需要配合hasOwnProperty()方法判断某个属性是否该对象的实例属性,来将原型对象从循环中剔除。
  • 所以for-in更适合遍历对象,通常是建议不要使用for-in遍历数组

02.for of

  • JavaScript 原有的for-in循环,针对对象 只能获得对象的键名,不能直接获取键值。ES6 提供for…of循环,允许遍历获得键值

    • 对象 (不可以用于直接遍历对象 对象不属于可迭代对象)

      • let obj={'name':'programmer','age':'22','height':'180'};
        for(let i of obj){
        console.log(i)//obj is not iterable
        }
        
  - 

ES6 中引入了 Iterator,只有提供了 Iterator 接口的数据类型才可以使用 for-of 来循环遍历,而 ArraySetMap、某些类数组如 arguments 等数据类型都默认提供了 Iterator 接口,所以它们可以使用 for-of 来进行遍历

  - 

https://juejin.cn/post/6844903933605838862 修改方式

 for (let [key,value] of Object.entries(obj)) {
     console.log(key,value); 
 }
  - 

修改方式2

     - 
let obj={'name':'programmer','age':'22','height':'180'};
for(let i of Object.keys(obj)){
    console.log(i,obj[i])//i:键
    //name programmer
    //age 22        
    //height 180
}
  • 数组操作

    • var arr = ['a', 'b', 'c', 'd'];
      //对比
      for (let a in arr) {
      console.log(a); // 0 1 2 3
      }
      for (let a of arr) {
      console.log(a); // a b c d
      }
      
  • 另外还可以用于遍历Map和Set

    • ```javascript var set = new Set(); set.add(“a”).add(“b”).add(“d”).add(“c”); // 遍历Set for (let s of set) { console.log(s); }
      // a // b // d // c

var map = new Map(); map.set(“a”, 1).set(“b”, 2).set(999, 3);

// 遍历Map for(let [k, v] of map) { console.log(k, v); } // a 1 // b 2 // 999 3




<a name="8c3b0914"></a>
### 05.break 和continue

<a name="01.break"></a>
#### 01.break

break用于退出switch或者循环语句(注意if语句不可以)

```javascript
for(var i=0 ; i<5 ; i++){
    console.log(i);
    break;
}//0

02.continue

continue用于跳过当此循环

for(var i=0 ; i<5 ; i++){
    if(i==2) {
        continue;
    }
    console.log(i);

}//0 1  3 4

12.JS对象

对象是JS中的引用数据类型
对象是一种复合数据类型,在对象中可以保存多个不同数据类型的属性
使用typeof检查一个对象时,会返回object

01.对象的分类

1.内建对象

  • 由ES标准中定义的对象,在任何的ES的实现中都可以使用
  • 比如:Math String Number Boolean Function Object…

2.宿主对象

  • 由JS的运行环境提供的对象,目前来讲主要指由浏览器提供的对象
  • 比如 BOM DOM

3.自定义对象

由开发人员自己创建的对象

02.创建对象的方式

01.方式一: new object方式创建对象
var obj = new Object();

02.方式二:使用对象字面量来创建对象
var obj = {};

03.方式三:利用构造函数创建对象

构造函数︰是一种特殊的函数,主要用来初始化对象,即为对象成员变主赋初始值,它总与new运算符一起使用。我们可以把对象中一些公共的属性和方法抽取出来,,然后封装到这个函数里面。(本质上实际上还是一个函数)

  • 构造函数的应用场景

    • 00.JavaScript基础 - 图3
  • 构造函数的配置方式

    -

  • 构造函数的使用实例

    -

  • 构造函数与对象的关系

    -

  • 内存上构造函数创建对象时发生的事

03.对象中的属性

01.添加对象中属性

语法:

  • 对象.属性名 = 属性值;
  • 对象[“属性名”] = 属性值; //这种方式能够使用特殊的属性名

对象的属性名没有任何要求,不需要遵守标识符的规范,但是在开发中,尽量按照标识符的要求去写。
属性值也可以任意的数据类型。

/*
*使用对象字面量,可以在创建对象时,直接指定对象中的属性
*语法:{属性名∶属性值,属性名∶属性值....}
*对象字面量的属性名可以加引号也可以不加,建议不加,
*如果要使用—些特殊的名字,则必须加引号
*属性名和属性值是一组一组的名值对结构,
*名和值之间使用:连接,多个名值对之间使用,隔开
*如果一个属性之后没有其他的属性了,就不要写,*/
var obj2 = {
name: "猪八戒",age: 28,
gender: "男",
test : {name: "沙和尚"}
};
console.log(obj2.test);

读取对象中的属性
语法:
对象.属性名
对象[“属性名”] //“属性名”可以使字符串常量,也可以是字符串变量
如果读取一个对象中没有的属性,它不会报错,而是返回一个undefined

02.删除对象中的属性

语法:

delete 对象.属性名
delete 对象["属性名"]

03.对象与基本数据类型区别

  • 浅拷贝差异

基本数据类型的直接赋值

var a=3;
var b=a;
a=4;//此时b依旧为3

对象数据类型的赋值—————-变量仅仅保存对象的内存地址

var obj = new Object();
obj.name = '孙悟空'
var obj2 = obj;
obj.name = '猪八戒'
console.log(obj.name)//猪八戒
console.log(obj2.name)//猪八戒

究其原因:空间存储关系:

  • 基本数据类型在栈内存中存储,修改一个变量不会影响其他变量;

    -

  • 对象是保存到堆内存中的,每创建一个新的对象,就会在堆内存中开辟出一个新的空间,而变量保存的是对象的内存地址(对象的引用),如果两个变量保存的是同一个对象引用,当一个通过一个变量修改属性时,另一个也会受到影响(地址类似于巫毒娃娃)

    • 00.JavaScript基础 - 图4
  • 注意特殊情况——当其中一个变量赋值为nulll 切断“巫毒娃娃”的联系

    • var obj = new Object();
      obj.name = '孙悟空'
      var obj2 = obj;
      obj2=null
      console.log(obj)//{name:孙悟空}
      console.log(obj2)//null
      


00.JavaScript基础 - 图5

  • 对象的等价判别是判别指针地址是否相同

    • 00.JavaScript基础 - 图6

04.hasOwnProperty

var map = {}
map[value] =123
console.log(this.map.hasOwnProperty(value))//true

05.获取对象中所有值

var map = {}
map[value] =123    
Object.keys(map)

04.对象的遍历

in 运算符

  • 使用in检查对象中是否含有指定属性

语法:

  • “属性名” in 对象

如果在对象中含有该属性,则返回true
如果没有则返回false

//循环遍历对象自身的和继承的可枚举属性(不含Symbol属性).
var obj = {'0':'a','1':'b','2':'c'};
for(var i in obj) {
     console.log(i,":",obj[i]);
}

补充

使用对象字面量,在创建对象时直接向对象中添加属性
语法:

var obj = {
    属性名:属性值,
    属性名:属性值,
    属性名:属性值,
    属性名:属性值
}

基本数据类型和引用数据类型
基本数据类型
String Number Boolean Null Undefined
引用数据类型
Object
基本数据类型的数据,变量是直接保存的它的值。
变量与变量之间是互相独立的,修改一个变量不会影响其他的变量。
引用数据类型的数据,变量是保存的对象的引用(内存地址)。
如果多个变量指向的是同一个对象,此时修改一个变量的属性,会影响其他的变量。
比较两个变量时,对于基本数据类型,比较的就是值,
对于引用数据类型比较的是地址,地址相同才相同

12+.JS函数(Function)

函数也是一个对象,也具有普通对象的功能(能有属性)
函数中可以封装一些代码,在需要的时候可以去调用函数来执行这些代码
使用typeof检查一个函数时会返回function
创建函数

function 函数名([形参1,形参2...形参N]){
语句...
}

函数表达式

var 函数名 = function([形参1,形参2...形参N]){
语句...
};

调用函数
语法:函数对象([实参1,实参2…实参N]);
fun() sum() alert() Number() parseInt()
当我们调用函数时,函数中封装的代码会按照编写的顺序执行

立即执行函数
函数定义完,立即被调用,这种函数叫做立即执行函数
立即执行函数往往只会执行一次

//直接调用
(function(a,b){
    console.log("a = "+a);
    console.log("b = "+b);
})()
//调用的同时传递参数
(function(a,b){
    console.log("a = "+a);
    console.log("b = "+b);
})(123,456);

遍历对象

  1. 对象中有几个属性 循环体就会执行几次
  2. 每次执行时,会将对象中的一个属性的名字赋值给变量
  3. 注意,如果想访问属性值,不能使用obj.v的方式,会返回undefine 可以使用obj[n]的方式来调用变量
for(var v in obj){
    document.write("property:name ="+v+"value="+obj[v]+"" );
}

形参和实参
形参:形式参数
定义函数时,可以在()中定义一个或多个形参,形参之间使用,隔开
定义形参就相当于在函数内声明了对应的变量但是并不赋值,
形参会在调用时才赋值。

实参:传递的实际参数
调用函数时,可以在()传递实参,传递的实参会赋值给对应的形参,
调用函数时JS解析器不会检查实参的类型和个数,可以传递任意数据类型的值。
如果实参的数量大于形参,多余实参将不会赋值,
如果实参的数量小于形参,则没有对应实参的形参将会赋值undefined

返回值,就是函数执行的结果。
使用return 来设置函数的返回值。
语法:return 值;
该值就会成为函数的返回值,可以通过一个变量来接收返回值
return后边的代码都不会执行,一旦执行到return语句时,函数将会立刻退出。
return后可以跟任意类型的值,可以是基本数据类型,也可以是一个对象。
如果return后不跟值,或者是不写return则函数默认返回undefined。
break、continue和return
break
退出循环
continue
跳过当次循环
return
退出函数

参数,函数的实参也可以是任意的数据类型。

方法(method)
可以将一个函数设置为一个对象的属性,
当一个对象的属性是一个函数时,
我们称这个函数是该对象的方法。
对象.方法名();
函数名()

call()
apply()
这两个方法都是函数对象的方法需要通过函数对象来调用
通过两个方法可以直接调用函数,并且 可以通过第一个实参来指定函数中this
不同的是call是直接传递函数的实参而apply需要将实参封装到一个数组中传递
arguments
arguments和this类似,都是函数中的隐含的参数
arguments是一个类数组元素,它用来封装函数执行过程中的实参
所以即使不定义形参,也可以通过arguments来使用实参
arguments中有一个属性callee表示当前执行的函数对象

13.JS作用域

作用域简单来说就是一个变量的作用范围。
在JS中作用域分成两种:

01.全局作用域

  • 直接在script标签中编写的代码都运行在全局作用域中

  • 全局作用域在打开页面时创建,在页面关闭时销毁。

  • 全局作用域中有一个全局对象window,window对象由浏览器提供,

  • 可以在页面中直接使用,它代表的是整个的浏览器的窗口。

  • 在全局作用域中创建的变量都会作为window对象的属性保存

  • 在全局作用域中创建的函数都会作为window对象的方法保存 (windows是最大的口袋)

  • 在全局作用域中创建的变量和函数可以在页面的任意位置访问。 对函数而言,需要以 function函数创建的关键词才会生效(使用函数表达式创建的函数,不会被声明提前,调用会报错)

    fun//我是一个fun函数
    fun2();//error
    function fun(){
      console.log("我是一个fun函数");
    }
    var fun2 = function(){//仅仅对fun2进行了变量提升 后面的并没有调用 所以会报错
      console.log("我是fun2函数");
    };
    
  • 在函数作用域中也可以访问到全局作用域的变量。

  • 尽量不要在全局中创建变量

02.函数作用域 (小全局)

  • 函数作用域是函数执行时创建的作用域,每次调用函数都会创建一个新的函数作用域。
  • 函数作用域在函数执行时创建,在函数执行结束时销毁。
  • 在函数作用域中创建的变量,不能在全局中访问。
  • 当在函数作用域中使用一个变量时,它会先在自身作用域中寻找,
    如果找到了则直接使用,如果没有找到则到上一级作用域中寻找,
    如果找到了则使用,找不到则继续向上找,一直会找到全局作用域
    如果全局作用域依旧没有找到,则会报ReferenceError
  • 在函数内部想要访问全局的变量 添加windows.前缀即可

03.变量的声明提前**

在全局作用域中,使用 var关键字声明的变量会在所有的代码执行之前被声明,但是不会赋值。 直接打印会报undefined
所以我们可以在变量声明前使用变量。但是不使用var关键字声明的变量不会被声明提前。
在函数作用域中,也具有该特性,使用var关键字声明的变量会在函数所有的代码执行前被声明,
如果没有使用var关键字声明变量,则变量会变成全局变量00.JavaScript基础 - 图7

函数中的变量参数相当于提前声明

04.函数的声明提前

在全局作用域中,使用 函数声明创建的函数(function fun(){}),会在所有的代码执行之前被创建
也就是我们可以在函数声明前去调用函数,但是使用函数表达式(var fun = function(){})创建的函数没有该特性
在函数作用域中,使用函数声明创建的函数,会在所有的函数中的代码执行之前就被创建好了。

14.JS Debug

右键点击脚本(google是source)

右键变量可以添加监控

15.JS this(上下文对象)

我们每次调用函数时,解析器都会将一个上下文对象作为隐含的参数传递进函数==————————————this==。
使用this来引用上下文对象,根据函数的调用形式不同,this的值也不同。

this(调用函数的那个对象)
this是函数的上下文对象,根据函数的调用方式不同会执向不同的对象(和创建方式无关)
1.以函数的形式调用时,this是window
2.以方法的形式调用时,this是调用方法的对象

function fun () {
   console.log(this)
}
var obj= {
name: "孙悟空",sayName : fun
};
var obj2 = {
name : "沙和尚",sayName : fun
};

//console.log(obj.sayName == fun);
obj2.sayName();//obj 沙和尚 以方法的形式调用时,this是调用方法的对象
fun();//windows 以函数的形式调用时,this是window

3.以构造函数的形式调用时,this是新建的那个对象
4.使用call和apply调用时,this是指定的那个对象
5.在全局作用域中this代表window

指向当前对象

this的不同的情况:
1.以函数的形式调用时,this是window
2.以方法的形式调用时,this就是调用方法的对象
3.以构造函数的形式调用时,this就是新创建的对象

16.JS构造函数

01.使用工厂方法创建对象

利用传参的方式进行简化代码 工厂:传递属性,返回对象

使用工厂方法创建的对象,使用的构造函数都是Object所以创建的对象都是Object这个类型,
就导致我们无法区分出多种不同类型的对象|

/*
*使用工厂方法创建对象
*通过该方法可以大批量的创建对象*/
function createPerson( name , age ,gender){
//创建一个新的对象
var obj = new Object( );
//向对象中添加属性
obj.name = name;
obj.age = age;
obj.gender = gender;
obj.sayName = function(){
    alert(this.name) ;
};
//将新的对象返回
    return obj;
}
var obj2 = createPerson("猪八戒",28,"男");
var obj3 = createPerson( "白骨精",16,"安");
var obj4 = createPerson("蜘蛛精",18,"女");
console.log(obj2);

02.构造函数方式创建

构造函数是专门用来创建对象的函数
一个构造函数我们也可以称为一个类
通过一个构造函数创建的对象,我们称该对象时这个构造函数的实例
通过同一个构造函数创建的对象,我们称为一类对象
构造函数就是一个普通的函数,只是他的调用方式不同 调用时需要添加new关键字(不加new就是普通函数的赋值),
如果直接调用,它就是一个普通函数
如果使用new来调用,则它就是一个构造函数

当以构造函数的形式调用时,this就是新创建的那个对象|

例子:

/*
*创建一个构造函数,专门用来创建Person对象的
*构诰函数就是一个普通的函数,创建方式和普通函数没有区别,
*不同的是构造函数习惯上首字母大写

this的情况:
1.当以函数的形式调用时,this是window
2.当以方法的形式调用时,谁调用方法this就是谁
3.当以构造函数的形式调用时,this就是新创建的那个对象|

*/
function Person(name , age , gender){
    this.name = name;
    this.age = age;
    this.gender = gender;
    this.sayName = function(){
        alert(this.name);
    };
}
var per1 = new Person("玉兔精",16,"女")

构造函数的执行流程:
1.创建一个新的对象
2.将新的对象作为函数的上下文对象(this)
3.执行函数中的代码
4.将新建的对象返回

instanceof 用来检查一个对象是否是一个类的实例 验证构造韩式
语法:对象 instanceof 构造函数
如果该对象时构造函数的实例,则返回true,否则返回false
Object是所有对象的祖先,所以任何对象和Object做instanceof都会返回true

枚举对象中的属性
for…in
语法:

for(var 属性名 in 对象){

}

for…in语句的循环体会执行多次,对象中有几个属性就会执行几次,
每次讲一个属性名赋值给我们定义的变量,我们可以通过它来获取对象中的属性

提高构造函数的执行效率,先前是每次执行一次方法,方法都会被重新创建 做一个提取可以提高效率

function Person(name , age , gender){
this.name = name;
this.age = age;
this.gender = gender;//向对象中添加一个方法
this.sayName = fun;
}
//将sayName方法在全局作用域中定义
/*
*
缺陷
*将函教定义在全局作用域,污染了全局作用域的命名空间
*而且定义在全局作用域中也很不安全
*/

function fun(){
alert( "He1lo大家好,我是:"+this.name) ;
};

缺陷
将函教定义在全局作用域,污染了全局作用域的命名空间
而且定义在全局作用域中也很不安全

17.JS原型(prototype)

创建一个函数以后, 解析器都会默认在函数中添加一个数prototype
prototype属性指向的是一个对象,这个对象我们称为原型对象。
当函数作为构造函数使用, 它所创建的对象中都会有一个隐含的属性执行该原型对象。

/*
*
*原型prototype*
*我们所创建的每一个函数,解析器都会向函数中添加一个属性prototype
*这个属性对应着一个对象,这个对象就是我们所谓的原型对象
*如果函数作为普通函数调用prototype没有任何作用
*当函数以构造函数的形式调用时,它所创建的对象中都会有一个隐含的属性,
*指向该构造函数的原型对象,我们可以通过__proto__来访问该属性

*原型对象就相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象,
*    我们可以将对象中共有的内容,统一设置到原型对象中

*/
function MyClass(){
}
var mc = new MyClass();
console.log(MyClass.prototype);// [object Object]  我们所创建的每一个函数,解析器都会向函数中添加一个属性prototype
console.log(mc.__proto__);// [object Object]  和上面的指向同一个原型对象
console.log(mc .__proto__ ==MyClass.prototype);//true
//向MyClass的原型中添加属性a  会被添加到公共区域 其实例对象也可访问 且不会污染全局作用域 原型里面的函数优先级低于实例自己创建的函数
/*
*以后我们创建构造函数时,可以将这些对象共有的属性和方法,统一添加到构造函数的原型对象
*这样不用分别为每一个对象添加,也不会影响到全局作用域,就可以使每个对象都具有这些军性和方法了|.
*/
MyClass.prototype.a = 123;
console.log(mc.a);//123
//向MyClass的原型中添加一个方法
MyClass.prototype.sayHello = function(){
    alert( "he11o");
};
mc. sayHello();//hello

原型对象就相当于一个公共的区域,凡是通过同一个构造函数创建的对象他们通常都可以访问到相同的原型对象。
我们可以将对象中共有的属性和方法统一添加到原型对象中,
这样我们只需要添加一次,就可以使所有的对象都可以使用。
当我们去访问对象的一个属性或调用对象的一个方法时,它会先自身中寻找,
如果在自身中找到了,则直接使用。
如果没有找到,则去原型对象中寻找,如果找到了则使用,
如果没有找到,则去原型的原型中寻找, 依此类推。直到找到Object的原型为止,Object的原型的原型为null,

** 如果依然没有找到则返回undefined

hasOwnProperty()

这个方法可以用来检查 对象自身中**是否含有某个属性 (如果使用name in mc 则会自动查找原型链)

语法:对象.hasOwnProperty(“属性名”)

18.JS toString方法

function Person(name , age , gender){
    this.name = name;
    this.age = age;
    this.gender = gender;
}
//创建一个Person实例
var per =new Person("孙悟空",18,"男");
console.log(per);//[object Object]
//当我们直接在页面中打印一个对象时,事件上是输出的对象的toString()方法的返回值
console.log(per.toString());//[object Object]

当我们直接在页面中打印一个对象时,事件上是输出的对象的toString()方法的返回值

如果我们希望在输出对象时不输出[object Object],可以为对象添加一个toString()方法 重写tostring方法


Person.prototype.toString = function(){
    return "Person[name="+this.name+",age="+this.age+",gender="+this.gender+"]";
};

19.JS 垃圾回收(GC)

就像人生活的时间长了会产生垃圾一样,程序运行过程中也会产生垃圾
这些垃圾积攒过多以后,会导致程序运行的速度过慢,
所以我们需要一个垃圾回收的机制,来处理程序运行过程中产生垃圾
当一个对象没有任何的变量或属性对它进行引用,此时我们将永远无法操作该对象,
此时这种对象就是一个垃圾,这种对象过多会占用大量的内存空间,导致程序运行变慢,
所以这种垃圾必须进行清理。
在JS中拥有自动的垃圾回收机制,会自动将这些垃圾对象从内存中销毁,
我们不需要也不能进行垃圾回收的操作
我们需要做的只是要将不再使用的对象设置null即可

00.JavaScript基础 - 图8

20. JS数组

数组也是一个对象,是一个用来存储数据的对象和Object类似,但是它的存储效率比普通对象要高
数组中保存的内容我们称为元素
数组使用索引(index)来操作元素
索引指由0开始的整数

/*
*内建对象
*宿主对象
*自定义对象*
*数组(Array)
*   -数组也是一个对象
*   -它和我们普通对象功能类似,也是用来存储一些值的
*   -不同的是普通对象是使用字符串作为属性名的,
*   -而数组时使用数字来作为索引操作元素
*   -索引:
*      从0开始的整数就是索引
*   -数组的存储性能比普通对象要好,在开发中我们经常使用数组来存储一些数据
*/
//创建数组
var arr = new Array();
//var arr = [];
//使用typeof检查一个数组时,会返回object
console.log(typeof arr);//object

01.数组的操作:

创建数组

//使用构造函数方式创建
var arr = new Array();
//字面量方式创建
var arr = [];
//使用字面量创建数组时,可以在创建时就指定数组中的元素var arr = [1,2,3,4,5,10];
// console.log( arr[3]);
//使用构造函数创建数组时,也可以同时添加元素,将要添加的元素作文构造函数的参数传递
//元素之间使用,隔开
var arr2 =new Array( 10,20,30);
// console.log( arr2);

//创建一个长度为10的数组
arr2 = new Array ( 10);
//console.log( arr2.length);
//数组中的元素可以是任意的数据类型
arr = ["he1lo",1,true,null,undefined];
//也可以是对象
var obj = {name : "孙悟空"};
arr[arr.length] = obj;

向数组中添加元素
语法;
数组对象[索引] = 值;

arr[0] = 123;
arr[1] = "hello";

创建数组时直接添加元素
语法:

 var arr = [元素1,元素2....元素N];

例子:

 var arr = [123,"hello",true,null];

获取和修改数组的长度
使用length属性来操作数组的长度
获取长度:
数组.length
length获取到的是数组的最大索引+1
对于连续的数组,length获取到的就是数组中元素的个数
修改数组的长度
数组.length = 新长度
如果修改后的length大于原长度,则多出的部分会空出来
如果修改后的length小于原长度,则原数组中多出的元素会被删除
向数组的最后添加元素
数组[数组.length] = 值;

02.数组的方法

01.push

  • 该方法可以向数组的末尾添加一个或多个元素
  • 返回数组的新的长度
  • 可以将要添加的元素作为方法的参数传递,
    这样这些元素将会自动添加到数组的末尾
//创建一个数组
var arr = ["孙悟空","猪八戒","沙和尚"];
/*
* push()
* -该方法可以向数组的末尾添加一个或多个元素,并返回数组的新的长度
* -可以将要添加的元素作为方法的参数传递,
*      这样这些元素将会自动添加到数组的末尾
*/

var result = arr.push("唐僧","蜘蛛精","白骨精");
console.log( arr);//"孙悟空","猪八戒","沙和尚" ,"唐僧","蜘蛛精"","白骨精"
console. log("result = "+result);// result = 6

02.pop

  • 该方法可以册除数组的最后一个元素
  • 并将被册删除的元素作为返回值返回
/*
* pop()
* -该方法可以册除数组的最后一个元素
*/
arr.pop();//"孙悟空,猪八戒,沙和尚,唐僧,蜘蛛精,白骨精,玉兔精"
arr.pop();//"孙悟空,猪八戒,沙和尚,唐僧,蜘蛛精"
result = arr.pop();// 蜘蛛精
console.log(arr);

03.unshift

  • 向数组开头添加一个或多个元素,并返回新的数组长度
  • 返回新的长度
/*
* unshift()
* -向数组开头添加一个或多个元素,并返回新的数组长度
*/
console.log(arr);//"孙悟空,猪八戒,沙和尚,唐僧,蜘蛛精,白骨精"
arr.unshift("牛魔王");
console.log( arr);//"牛魔王,孙悟空,猪八戒,沙和尚,唐僧,蜘蛛精,白骨精"

04.shift

  • 删除数组的开头的一个元素,并
  • 返回被删除的元素删除数组的开头的一个元素,并返回被删除的元素
console.log( arr);//"牛魔王,二郎神,孙悟空,猪八戒,沙和尚,唐僧,蜘蛛精,白骨精"
/*
*
* shift()
* -可以删除数组的第一个元素,并将被删除的元素作为返回值返回
*/
result = arr.shift();
console.log(arr);//"二郎神,孙悟空,猪八戒,沙和尚,唐僧,蜘蛛精,白骨精"
console. log("result ="+result);//"result =牛魔王"
functionNamefunctionName functionfunction usageusage
push()push() 用来向数组的末尾添加一个或多个元素,并返回数组新的长度用来向数组的末尾添加一个或多个元素,并返回数组新的长度 语法:数组.push(元素1,元素2,元素N)pop()语法:数组.push(元素1,元素2,元素N)pop()
pop()pop() 用来删除数组的最后一个元素,并返回被删除的元素用来删除数组的最后一个元素,并返回被删除的元素
unshift()unshift() 向数组的开头添加一个或多个元素,并返回数组的新的长度向数组的开头添加一个或多个元素,并返回数组的新的长度
shift()shift() 删除数组的开头的一个元素,并返回被删除的元素删除数组的开头的一个元素,并返回被删除的元素
reverse()reverse() 可以用来反转一个数组,它会对原数组产生影响可以用来反转一个数组,它会对原数组产生影响
concat() 可以连接两个或多个数组,它不会影响原数组,而是新数组作为返回值返回

05.slice(start,end)

截取元素

该方法不会影响原数组,而是将截取到的内容封装为一个新的数组并返回

第二个参数可以省略不写,如果不写则一直截取到最后

//可以从一个数组中截取指定的元素  
//该方法不会影响原数组,而是将截取到的内容封装为一个新的数组并返回  
//参数:  
 //  1.截取开始位置的索引(包括开始位置)  
 //  2.截取结束位置的索引(不包括结束位置)  
 //      -第二个参数可以省略不写,如果不写则一直截取到最后  
 //  -参数可以传递一个负值,如果是负值,则从后往前数  
//            -1代表倒数第一个 -2代表倒数第二个
var arr = ["孙悟空","猪八戒","沙和尚","唐僧","白骨精"];
var result =arr.slice(0,2);//不包含最后一个
console.1og(result);//孙悟空 猪八戒

06. splice() 更常用

删除素组的指定元素 会影响到原数组

可以删除的同时替换元素 索引从0开始

  • 删除
  • 替换
  • 插入(插入元素是在索引指向的元素前插入)
//可以用来删除数组中指定元素,并使用新的元素替换  
//   使用splice()会影响到原数组,会将指定元素从原数组中册除
//   并将被册除的元素作为返回值返回

//参数:  
//   1.删除开始位置的索引  
//   2.删除的个数  
//   3.第三个及以后,都是替换的元素,这些元素将会插入到开始位置索引的前边  

//01.删除元素 删除索引第0个元素后面两个元素
var arr = ['猪八戒','沙和尚','孙悟空','唐僧','白骨精']
var delect = arr.splice(0,2);
console.log(arr);//"沙和尚,唐僧,白骨精" 数组被删除了前两个
console.log(delect);//“猪八戒,沙和尚 返回的被删除的值

//02.替换元素 将索引为第一个的元素删除 并替换为-------
arr = ["孙悟空","猪八戒","沙和尚","唐僧","白骨精"];
var result = arr.splice(1,"牛魔王","铁扇公主","红孩儿");
console.log(arr);//"孙悟空,牛魔王,铁扇公主,红孩儿,沙和尚,唐僧,白骨精"

//03.增添元素 将索引为第一个的元素的后面增添指定元素(注意和02的区别只在于是否指定删除的个数 指定删除的个数为零即为增添元素)
arr = ["孙悟空","猪八戒","沙和尚","唐僧","白骨精"];
var result = arr.splice(1,0,"牛魔王","铁扇公主","红孩儿");
console.log(arr);//"孙悟空,牛魔王,铁扇公主,红孩儿,'猪八戒',沙和尚,唐僧,白骨精"

07.concat()

连接两个或多个数组,并将新的数组返回

不会对原数组产生影响

var arr = ["孙悟空","猪八戒","沙和尚"];
var arr2 =["白骨精","玉兔精",""蜘蛛精"];
var arr3 =["二郎神"","太上老君","玉皇大帝"];

/*
* concat()可以连接两个或多个数组,并将新的数组返回
* -该方法不会对原数组产生影响
*/
var result =arr.concat(arr2);//"孙悟空,猪八戒,沙和尚,白骨精,玉兔精,蜘蛛精"
var result = arr.concat(arr2,arr3);//孙悟空,猪八戒,沙和尚,白骨精,玉兔精,蜘蛛精,二郎神,太上老君,玉皇大帝

console.log(result)

08.join([splitor])

该方法可以将数组转换为一个字符串

//可以将一个数组转换为一个字符串
//参数:
//需要一个字符串作为参数,这个字符串将会作为连接符来连接数组中的元素
//如果不指定连接符则默认使用,(逗号)
arr = ["孙悟空","猪八戒","沙和尚"];
result = arr.join();
console.log(typeof result);//string

result = arr.join("-");
console. log(result);// "孙悟空–猪八戒-沙和尚"

09.reverse

翻转数组

该方法会直接修改原数组

/*
*reverse()
* -该方法用来反转数组(前边的去后边,后边的去前边)
* -该方法会直接修改原数组
*/
arr = ["孙悟空","猪八戒","沙和尚","唐僧"];
arr.reverse();
console.log(arr);//"唐僧,沙和尚,猪八戒,孙悟空"

10.sort()

对数组进行排序

  • 直接修改原数组
/*
   可以对一个数组中的内容进行排序,默认是按照Unicode编码进行排序
   调用以后,会直接修改原数组。
   可以自己指定排序的规则,需要一个回调函数作为参数:

我们可以自己来指定排序的规则
我们可以在sort()添加一个回调函数,来指定排序规则,
回调函数中需要定义两个形参,
浏览器将会分别使用数组中的元素作为实参去调用回调函数
使用哪个元素调用不确定,但是肯定的是在数组中a一定在b前边

* 浏览器会根据回调函数的返回值来决定元素的顺序,
  如果返回一个大于0的值,则元素会交换位置
  如果返回一个小于0的值,则元素位置不变
  如果返回一个0,则认为两个元素相等,也不交换位置
* 如果需要升序排列,则返回 a-b
  如果需要降序排列,则返回b-a
 */



//01基础排序
arr = ["b", "d" , "e", "a" , "c"];
/*
* sort( )
*  -可以用来对数组中的元素进行排序
*  -也会影响原数组,默认会按照Unicode编码进行排序
*/
arr.sort();//a,b,c,d ,e
arr.reverse();//e,d,c,b, a

//排序大于10会出现问题
//即使对于纯数字的数组,使用sort()排序时,也会按照Unicode编码来排序,所以对数字进排序时,可能会得到错误的结果

arr =[3,4,11,2,5];
arr.sort( );
console.log( arr);//"11,2,3,4,5"

//02添加回掉函数排序
/*
*我们可以自己来指定排序的规则
*  我们可以在sort()添加一个回调函数,来指定排序规则,
*        回调函数中需要定义两个形参,T
*       浏览器将会分别使用数组中的元素作为实参去调用回调函数
*       使用哪个元素调用不确定,但是肯定的是在数组中a一定在b前边
*  -浏览器会根据回调函数的返回值来决定元素的顺序,
*     如果返回一个大于0的值,则元素会交换位置
*      如果返回一个小于0的值,则元素位置不变
*     如果返回一个日,则认为两个元素相等,也不交换位置



*/
//解析1
arr = [5,4];
arr.sort( function(a,b){
    console.log( "a = "+a);// a=5
    console.log( "b = "+b);// b=4
});

//解析2
arr = [5,4,3];
arr.sort( function(a,b){
    console.log( "a = "+a);
    console.log( "b = "+b);
/*
a=5;b=4;
a=4;b=3
*/    
});
//应用 升序排列
arr =5,4,2,1,3,6,8,7];
arr .sort( function(a,b){
    //前边的大 交换位置
    if(a > b){
        return 1;
    }else if(a < b){//小于不变
        return -1;
    }else{//等于不变
            return 0;
    }
});
//"1,2,3,4,5,6,7,8"

//应用 降序排列
arr =5,4,2,1,3,6,8,7];
arr .sort( function(a,b){
    //前边的大 不变
    if(a > b){
        return -1;
    }else if(a < b){//小于 交换位置
        return 1;
    }else{//等于不变
            return 0;
    }
});
//"8,7,6,5,4,3,2,1"

//简化  
//如果需要升序排列,则返回a-b
//如果需要降序排列,则返回b-a

升序
    return a - b;
降序
    return b - a;
function(a,b){
    return b-a;
}

11.indexOf

//indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。
/如果没有找到匹配的字符串则返回 -1。
/**
 * @param {string[]} list1
 * @param {string[]} list2
 * @return {string[]}
 */
var findRestaurant = function(list1, list2) {

    var min = 5000; result = []
    for(var i = 0; i<list1.length; i++){
        var t = list2.indexOf(list1[i])
        if(t != -1){
            if(t+i < min){
                result = [];
                result.push(list1[i])
                min = t+i
            }else if(t+i == min){
                result.push(list1[i])
            }
        }
    }
    return result
};

12.include

1、Array.prototype.includes

概述:

Includes 方法用来检测数组中是否包含某个元素,返回布尔类型值;
判断数组中是否包含某元素,语法:arr.includes(元素值);

代码实现:

```html <!DOCTYPE html>


> > <a name="d3ca7e34"></a>
### 运行结果:

> ![](image-20210812102859726.png#alt=image-20210812102859726)




<a name="9702c6fc"></a>
### 03.遍历数组

<a name="0105e2c3"></a>
#### 01.for循环

遍历数组就是将数组中元素都获取到<br />
一般情况我们都是使用for循环来遍历数组

```javascript
//伪代码
for(var i=0 ; i<数组.length ; i++){
}

//实际代码
//创建一个数组
var arr = ["孙悟空","猪八戒","沙和尚","唐僧","玉兔精"籽;
//所谓的遍历数组,就是将数组中所有的元素都取出来
/*console.log( arr[e]);
console.log( arr[1]);console.log( arr[2]);console.log( arr[3]);*/
for(var i=0 ; i<arr.length; i++){
    console.log(arr[i]);//孙悟空""猪八戒"沙和尚“,唐僧,白骨情
}

02.forEach()方法

使用forEach()方法来遍历数组(不兼容IE8)

/*
* JS中还为我们提供了—个方法,用来遍历数组
*     forEach()
* -这个方法只支持IE8以上的浏览器
* forEach()方法需要一个函数作为参数
    -像这种函数,由我们创建但是不由我们调用的,我们称为回调函数(由浏览器调用)
    -数组中有几个元素函数就会执行几次
    -每次执行时,浏览器会将遍历到的元素以实参的形式传递进来  我们可以来定义形参,来读取这些内容
    -浏览器会在回调函数中传递三个参数;
        第一个参数,就是当前正在遍历的元素
        第二个参数,就是当前正在遍历的元素的索引
        第三个参数,就是正在遍历的数组    
*/

数组.forEach(function(value , index , obj){

});

forEach()方法需要一个回调函数作为参数,
数组中有几个元素,回调函数就会被调用几次,
每次调用时,都会将遍历到的信息以实参的形式传递进来,
我们可以定义形参来获取这些信息。
value:正在遍历的元素
index:正在遍历元素的索引
obj:被遍历对象

04.练习 数组去重

//创建一个数组
var arr = [1,2,3,2,1,3,4,2,5];
//去除数组中重复的数字
//获取数组中的每一个元素
for(var i= ; i<arr. length ; i++){
    // console.log(arr[i]);
    /*获取当前元素后的所有元素*/
    for(var j=i+1 ; j<arr.length ; j++){
        //console.log( "----> "+arr[j]);
         //判断两个元素的值是否相等
        if( arr[i] == arr[j]){
            //如果相等则证明出现了重复的元素,则册除j对应的元素
            arr.splice(j,1);
            //当册除了当前j所在的元素以后,后边的元素会自动补位
           //此时将不会在比较这个元素吧,我需要在比较一次j所在位置的元素//使j自减
           j--;

        }
    }
}
console.log(arr);//1 2 3 4 5

21.JS函数的方法

以——个函数为主体调用另—个函数里的方法

  • this的情况:
  • 1.以函数形式调用时, this永远都是window
  • 2.以方法的形式调用时, this是调用方法的对象
  • 3.以构造函数的形式稠用时,this是新创建的那个对象
  • 4.使用call和appty调用时,this是指定的那个对象|
function fun() {
    alert(this.name);
}
/*
* cal1()和apply()
*  -这两个方法都是函数对象的方法,需要通过函数对象来调用
*  -当对函数调用call()和apply()都会调用函数执行
*  -在调用call和apply()可以将一个对象指定为第一个参数
    此时这个对象将会成为函数执行时的this
*  - call()方法可以将实参在对象之后依次传递|
*  - apply()方法需要将实参封装到一个数组中统一传递
*
* - this的情况:
*     1.以函数形式调用时, this永远都是window
*     2.以方法的形式调用时, this是调用方法的对象
*     3.以构造函数的形式稠用时,this是新创建的那个对象
*     4.使用call和appty调用时,this是指定的那个对象|
*/
var obj= {
    name:'obj1'
    sayName : function(){
        alert(this.name);
    }

//基础         };
var obj2= {name:'obj2'};
fun();//[object Window] 直接调用 this是windows
fun.call(obj);//[object Object]  传入obj this是obj 
fun.apply(obj2);//[object Object] 传入obj2 this是obj2  
//应用  以——个函数为主体调用另—个函数里的方法
obj.sayName();//obj
obj.sayName.apply(obj2);//obj2

/*
*  - call()方法可以将实参在对象之后依次传递|
*  - apply()方法需要将实参封装到一个数组中统一传递
*/
function fun(a,b) {
    console.log("a ="+a);
    console. log("b = "+b);
}
fun.call(obj);//"a = undefined"  "b = undefined"
fun.call(obj,2,3);//"a = 2"  "b = 3"
fun.apply(obj,[2,3]);//"a = 2"  "b = 3"

22.JS函数的arguments

/*
*在调用函数时,浏览器每次都会传递进两个隐含的参数:
* 1.函数的上下文对象this
* 2.封装实参的对象arguments
    - arguments是一个类数组对象 它也可以通过索引来操作数据,也可以获取长度
    - 在调用函数时,我们所传递的实参都会在arguments中保存
    - arguments.length可以用来获取实参的长度
    -我们即使不定义形参,也可以通过arguments来使用实参,
        只不过比较麻烦
        arguments[0]表示第一个实参
        arguments[1]表示第二个实参        
    -它里边有一个属性叫做callee,
        这个属性对应一个函数对象,就是当前正在指向的函数的对象
*/
function fun( )i
    console.log(arguments);//"[object Arguments ]"
    console.log(arguments instanceof Array);//false 不是一个数组
    console.1og(arguments.length);//2
    console.1og(arguments[1]);//true

}
fun("hello",true);

23.JS Date

日期的对象,在JS中通过Date对象来表示一个时间
创建对象

 /*
* Date对象
*    -在JS中使用Date对象来表示一个时间
*/

//创建一个Date对象
//如果直接使用构造函数创建一个Date对象,则会封装为当前代码执行的时间
var d = new Date();
console.log(d);//Fri Dec 02 2016 11:04:03 GMT+080日(中国标准时间)

//01创建一个指定的时间对象
//需要在构造函数中传递一个表示时间的字符串作为参数
//日期的格式月份/日/年 时:分:秒
//年份请写完整的 避免歧义
var d2 = new Date("12/03/2016 11:10:30);
console.log(d2);//"Sat Dec 03 2016 11:10:30 GMT+080日(中国标准时间)"

//02.获取当前日期
var date = d.getDate();
console log( "date = "+date);//date =2

// 03获取当前日期对象是周几
// -会返回一个0-6的值
// 表示周日
// 1表示周一
var day = d2.getDay();
console. log( "day = "+day );//day = 3 周三

//04.获取月份
//-获取当前时间对象的月份
//回一个0-11的值
//示1月
//示2月
//表示12月
var month = d2.getMonth();
console.log("month = "+month+1);//11

//获取年份
//tFu11Year()
//-获取当前日期对象的年份*/
var year = d2.getFu11Year( );

//getTime( )
//-获取当前日期对象的时间戳
//-时间戳,指的是从格林威治标准时间的1970年1月1日,已时0分0秒
// 到当前日期所花费的毫秒数(1秒=1000ms)
//计算机底层保存时间都是以时间戳的形式保存的。Date.now()可以获取当前代码执行时的时间戳
var time = d2.getTime();
console.log(time) ;//"12979986300"

//利用时间戳来测试代码的执行的性能
//获取当前的时间戳
var start = Date.now();
for(var i=e ; i<100 ; i++){
    console.log(i);
}
var end = Date.now( );
console.log("执行了:"+(end - start)+"毫秒");

namegetDate()当前日期对

24.JS Math

Math属于一个工具类,它不需要我们创建对象,它里边封装了属性运算相关的常量和方法
我们可以直接使用它来进行数学运算相关的操作

方法:
Math.PI
常量,圆周率
Math.abs()
绝对值运算
Math.ceil()
向上取整
Math.floor()
向下取整
Math.round()
四舍五入取整
Math.random()
生成一个01之间的随机数
生成一个xy之间的随机数
Math.round(Math.random()*(y-x)+x);
Math.pow(x,y)
求x的y次幂
Math.sqrt()
对一个数进行开方
Math.max()
求多个数中最大值
Math.min()
求多个数中的最小值

00.JavaScript基础 - 图9

/*
Math
* - Math和其他的对象不同,它不是一个构造函数,
*    它属于一个工具类不用创建对象,它里边封装了数学运算相关的属性和方法
*/
console.log(Math.PI);//"3.141592653589793

/*
* abs( )可以用来计算一个数的绝对值
*/
console.log(Math.abs(-1));//1

/*
* Math.ceil()
*    -可以对一个数进行向上取整,小数位只有有值就自动进1
* Math.floor()
*    -可以对—个数进行向下取整,小数部分会被舍掉
* Math .round()
*    -可以对一个数进行四舍五入取整
*
*Math.random( )
*-可以用来生成一个0-1之间的随机数
*
* -生成一个1-10
* -生成一个x-y之间的随机数*
*  Math.round (Math.random( )*(y-x)+x)

*/
console.log(Math.ceil(1.1));//2

/*
*Math . pow(x,y)*
返回x的y次幂
*/
console.log(Math. pow(12,3));//1728

/*
Math.sqrt()*
用于对一个数进行开方运算
*/
console.log(Math.sqrt( 2));

25.JS 包装类

在JS中为我们提供了 三个包装类:
String() Boolean() Number()
通过这三个包装类可以创建基本数据类型的对象
例子:

/*
* 基本数据类型
    String Number Boolean Null Undefined
* 引用数据类型
*    object*

* 在JS中为我们提供了三个包装类,通过这三个包装类可以将基本数据类型的数据转换为对象
*    string()
*       -可以将基本数据类型字符串转换为String对象
*     Number()
*       -可以将基本数据类型的数字转换为Number对象
*    Boolean()
*       -可以将基本数据类型的布尔值转换为Boolean对象
*    但是注意:我们在实际应用中不会使用基本数据类型的对象,*
*        如果使用基本数据类型的对象,在做一些比较时可能会带来一些不可预期的结果

*/

var num = new Number(3);//3
var num2 =new Number(3);
console. log(typeof num);//object
console.log(num ==num2);//false


var str = new String("hello");//hello
console. log(typeof str);//object

var bool = new Boolean(true);//true
console. log(typeof bool);//object
//向num中添加一个属性
num.hello = "abcdefg" ;
console.log( num.hello);//abcdefg

但是在实际应用中千万不要这么干。

疑点

/*
*方法和属性之能添加给对象,不能添加给基本数据类型
*    当我们对—些基本数据类型的值去调用属性和方法时,
*        浏览器会临时使用包装类将其转换为对象,然后在调用对象的属性和方法
*        调用完以后,在将其转换为基本数据类型

*/
var s = 123;
s= s.toString();
console.log(s);//123
console.log(typeof s);//str  在此过程中基本数据类型调用了包装类

s.hello =“你好";//不会报错 这里是先调用包装类转换 然后将包装类销毁 虽然不报错 但是没啥用
console. log(s.hello);//undefine  这里的s.是转换后的 不是销毁的那个 所以是undefine

当我们去操作一个基本数据类型的属性和方法时,
解析器会临时将其转换为对应的包装类,然后再去操作属性和方法,
操作完成以后再将这个临时对象进行销毁。

26.字符串的相关的方法

//创建一个字符串
var str = "Hello Atguigu";
/*
*在底层字符串是以字符数组的形式保存的
*["H" , "e", "1"]
*/
console.log( str.length);//13
console.log(str[1]);//e

使用ES6中的字符串新方法

String.prototype.padStart(maxLength, fillString=’’)String.prototype.padEnd(maxLength, fillString=’’)来填充字符串;

01.length

获取字符串的长度

/*
*    length属性
*    -可以用来获取字符串的长度
*/
var str = "Hello Atguigu";
console.log(str.length);//13
console.log(str[5]);//e

02.charAt()

根据索引获取指定的字符

等价于下标获取

/*
*    charAt()
*    -可以返回字符串中指定位置的字符
    根据索引获取指定的字符

*/
str = "Hello Atguigu";
var result = str.charAt(0);//H
var result = str[0];//H
console.log(str);//"Hello Atguigu"

03.charCodeAt()

根据索引获取指定的字符编码 (Unicode编码)

/*
*    charCodeAt()
*    -获取指定位置字符的字符编码(Unicode编码
*/
str = "中Hello Atguigu";
result = str.chareodeAt(0);
console.log(result);//20013

04.String.fromCharCode()

根据字符编码获取字符

/*
*String.formCharCode( )*-可以根据字符编码去获取字符*/
result = String.fromCharCode(20013);
console.log(result);//中

实际上直接比较字母大小 比较的就是Unicode码

/**
 * @param {character[]} letters
 * @param {character} target
 * @return {character}
 */
var nextGreatestLetter = function(letters, target) {
    var res ='';
    try{
        letters.forEach(item=>{
            if(item>target){
                res = item
                throw new Error('找到数据')
        }
        })

    }catch{
        return res
    }
    res=letters[0]
    return res


};

05.concat()

连接两个或者多个字符串

/*
*    concat()
*    -可以用来连接两个或多个字符串
    作用和+—样
*/
result = str.concat("你好");
console.log( result);//"“中Hello Atguigu你好"

06.indexOf()

该方法可以检索一个字符串中是否含有指定内容

/*
*     indexof()
*    -该方法可以检索一个字符串中是否含有指定内容
    从一个字符串中检索指定内容
    需要一个字符串作为参数,这个字符串就是要检索的内容,
    如果找到该内容,则会返回其第一次出现的索引,如果没有找到则返回-1。
    可以指定一个第二个参数,来表示开始查找的位置
    indexOf()是从前向后找
*/
str = "he1lo atguigu";
result = str.indexof("a" );
console.log(result);//6

lastIndexOf()

/*
*lastIndexQf();
*-    该方法的用法和indexOf()一样,*
        不同的是indexOf是找第一个,
*        而lastIndexOf是找到最后一个 返回正常索引
*
    -也可以指定开始查找的位置
*/
result = str.lastIndexOf( "h" );
console.log(result);//6

07.slice(start,[end])

/*
slice()
*    -可以从字符串中截取指定的内容
*    -不会影响原字符串,而是将截取到内容返回
    -参数:
        第一个,开始位置的索引(包括开始位置)
        第二个,结束位置的索引(不包括结束位置)
            -如果省略第二个参数,则会截取到后边所有的
        -也可以传递—个负数作为参数,负数的话将会从后边计算
*/
str = "abcdefghijk";
result = str.slice(0,2);
console.1og(result);//ab

08.substring()

和slice()基本一致,不同的是它第二个参数不是索引,而是截取的数量

/*
substring()
丰-可以用来截取一个字符串,可以slice()类似*
-    参数:
    -第一个:开始截取位置的索引(包括开始位置)
    -第二个:结束位置的索引(不包括结束位置)
    -不同的是这个方法不能接受负值作为参数,
        如果传递了一个负值,则默认使用0
    -而且他还自动调整参数的位置,如果第二个参数小于第一个,则自动交换

*/
result = str.substring( 1,2;
console.log( result);

09.substr()

/*
*    substr()
*    -用来截取字符串*
    -参数:
        1.截取开始位置的索引
        2.截取的长度
*/
str = "abcdefg";
result = str.substr(3,2);
console.log(str);//de

10split()

可以将一个字符串拆分为一个数组

/*
*    split()
*    -可以将一个字符串拆分为一个数组工
    *-参数:
    *-需要一个字符串作为参数,将会根据该字符串去拆分数组
*/
str = "abc ,bcd ,efg,hij";
result = str.split( "," );
console.log(typeof result);//object
console.log(Array .isArray(result));//true
console.log(result.length) ;//4

/*
*如果传递一个空串作为参数,则会将每个字符都拆分为数组中的一个元素*/
result = str.split("");

11.toUpperCsae()

将一个字符串转换为大写并返回

/*
*toUpperCase()
*-将一个字符串转换为大写并返回*/
str = " abcdefg";
result = str.toUpperCase();//ABCDEFG
console.1og( result);

12.toLowerCase()

将—个字符串转换为小写并返回*

/*
*toLowerCase()
*-将—个字符串转换为小写并返回*/
result = str.toLowerCase();
console.log(result);

13.replace

JS如何去除指定字符串

两种方式可以实现

1:使用replace函数替换

       var  str="hello world!";

       str=str.replace("l","");

       即使用空串替换某一个字符串,则是可以实现去除指定字符串功能

2:使用字符串分割函数在聚合

    var str="hello world!"

    var items=str.split("o")

    会得到一个数组,数组中包括利用o分割后的多个字符串(不包括o)

    var newStr=items.join("");

     会得到一个新字符串,将数组中的数组使用空串连接成一个新字符串

可以根据指定内容将一个字符串拆分为一个数组
参数:
需要一个字符串作为参数,将会根据字符串去拆分数组
可以接收一个正则表达式,此时会根据正则表达式去拆分数组

match()
可以根据正则表达式,从一个字符串中将符合条件的内容提取出来
默认情况下我们的match只会找到第一个符合要求的内容,找到以后就停止检索
我们可以设置正则表达式为全局匹配模式,这样就会匹配到所有的内容
可以为一个正则表达式设置多个匹配模式,且顺序无所谓
match()会将匹配到的内容封装到一个数组中返回,即使只查询到一个结果

replace()
可以将字符串中指定内容替换为新的内容
参数:
1.被替换的内容,可以接受一个正则表达式作为参数
2.新的内容 空串则为删除””
默认只会替换第一个

search()
可以搜索字符串中是否含有指定内容
如果搜索到指定内容,则会返回第一次出现的索引,如果没有搜索到返回1
它可以接受一个正则表达式作为参数,然后会根据正则表达式去检索字符串
serach()只会查找第一个,即使设置全局匹配也没用

27.JS正则表达式

https://share.mubu.com/doc/Mc_8T6GUxR

正则用来定义一些字符串的规则,程序可以根据这些规则来判断一个字符串是否符合规则,
也可以将一个字符串中符合规则的内容提取出来。

01创建正则表达式并验证

//创建正则表达式的对象
/*
*语法:
*    var变量= new RegExp("正则表达式","匹配模式");
    使用typeof检查正则对象,会返回object
    *var reg = new RegExp("a" );这个正则表达式可以来检查一个字符串中是否含有a
    *在构造函数中可以传递一个匹配模式作为第二个参数,
        可以是*
            i忽略大小写
            g全局匹配模式

*/
var reg = new RegExp("a");
console.log(reg);// /a/
console.log(typeof reg);//object
/*
*正则表达式验证的方法:
    *test()
        *-使用这个方法可以用来检查一个字符串是否符合正则表达式的规则,
        *如果符合则返回true,否则返回false
*/
var str = "a";
var result = reg.test(str);
console.log(result);//true
console.1og(reg. test("abc"));//true

02.字面量方式创建

/*
使用字面量来创建正则表达式
*    语法:var变量=/正则表达式/匹配模式*
        使用字面量的方式创建更加简单*
        使用构造函数创建更加灵活
*/
// var reg = new RegExp( "a" , "i");
var reg = /a/i;
console.log(typeof reg);//object
console.log( reg.test( "abc" ));//true

03.逻辑或和取反 ·

  • []
  • |
  • [a-z]
//01.创建一个正则表达式,检查一个字符串中是否有a或b
/*
*    使用│表示或者的意思
*/
reg = /a|b/ ;
console.log(reg.test( "acd" ));//true

/*
*02.[]里的内容也是或的关系
    *[ab] == a|b
     [a-z]任意小写字母
     [A-Z]任意大写字母

*/
// []
reg = /[ab]/
console.log(reg.test( "bcdefg"));//true

// [A-Z]
reg = /[A-z]/
console.log( reg.test( "c"));//true

//03.检查一个字符串中是否含有abc或adc或aec
reg = /a[bde]c/
console.log( reg.test( "aeec"));//false

04..搭配方法使用

01.split()

var str ="1a2b3c4d5e6f7 ";
/*
*    split()
*-可以将—个字符串拆分为一个数组
*-方法中可以传递一个正则表达式作为参数,这样方法将会根据正则表达式去拆分字符串
    -这个方法即使不指定全局匹配,也会全都插分

*/

/*
*根据任意字母来将字符串拆分*/
var result = str.split(/[A-z]/);//A到z中任何字母
console.log(result);//['1', '2', '3', '4', '5', '6','7']

02.search()

/*
*search()
*-可以搜索字符串中是否含有指定内容
    -如果搜索到指定内容,则会返回第一次出现的索引,如果没有搜索到返回-1
    -它可以接受一个正则表达式作为参数,然后会根据正则表达式去检索字符串
        - serach()只会查找第一个,即使设置全局匹配也没用


*/
str ="he1lo abc hello abc";
//01.简单应用
result = str.search( "abc");//abc的第一个索引 6
result = str.search( "abcd") ;//-1

//02.扩大搜索范围
//搜索字符串中是否含有abc或aec或afc
result = str.search( / a[bef]c/ );
console.log( result);//5
//全局匹配貌似没用

03.match()

/*
match()
*  -可以根据正则表达式,从一个字符串中将符合条件的内容提取出来
   -默认情况下我们的match只会找到第一个符合要求的内容,找到以后就停止检索
     我们可以设置正则表达式为全局匹配模式,这样就会匹配到所有的内容
     可以为一个正则表达式设置多个匹配模式,且顺序无所谓
   -- match()会将匹配到的内容封装到一个数组中返回,即使只查询到一个结果
*/
str = "1a2b3c4d5e6f7A;
//全局匹配 并忽略大小写
result = str.match(/[a-z]/gi);//"a,b,c,d,e,f,A,B,c"
//['a', 'b', 'c','d', 'e', 'f','A']

04.replace()

/*
*replace()
*    -可以将字符串中指定内容替换为新的内容
    *-参数:
*        1.被替换的内容
*        2.新的内容
    默认只会替换第一个
*/
result = str.replace( "a" , "@_@");
console. log(result);//"1@_@2b3c4d5e6f7A8B9C"
//全局替换
result = str.replace(/[a-z]/gi , "@_@");
console.log(result);//"1@_@2@_@3@_@4@_@5@_@6@_@7@_@8@_@9@_@"

05.正则表达式语法

01.量词

/*
*量词
    -通过量词可以设置一个内容出现的次数
*     - {n}正好出现n次
    -量词只对它前边的一个内容起作用
    - {n}正好出现n次
      {m,n}出现m-n次
      {m, } m次以上

    +至少一个,相当于{1,}
    * 0个或多个,相当于{0,}
    ? 0个或1个,相当于{0,1}



*/
//01.基础应用
var reg = /a{3}/;
console.log(reg.test( "aaac" ));//true

//02. + 等价于{1,}  至少一个、
reg = /ab+c/ ;
console.log(reg.test( "abbbbc " ));

//03.* * 0个或多个,相当于{0,}
reg = /ab*c/ ;

//04. ? 0个或1个,相当于{0,1}
reg = /ab?c/ ;

02.以—-开头

/*
*检查一个字符串中是否以a开头*人表示开头
*/
reg = /^a/ ;
console.log(reg.test( "bcabc" ));//false

03.以——结尾

//$表示结尾
reg = /a$/ ; //匹配结尾的a
console.log(reg.test( "abcabc" ));//false


//注意 如果在正则装达式中同时使用^$则要求字符串必须完全符合正则表达式
reg = /^a$ / ;
console.log( reg.test('aa'));//false 只能有一个a
//以a开头或结尾
reg = / ^a | a$/ ;

//例题 创建一个正则,检查一个字符串是否是一个合法手机号
/*
手机号的规则:
1 3 567890123 (11位)
1.以1开头
2.第二位3-9任意数字3.三位以后任意数字9个
    ^1 [3-9][0-9]{9}$
    //$表示后续无其他内容了
*/
var phonestr = "13567890123";
var phoneReg = /^1[3-9][0-9]{9}$/;
console.log(phoneReg.test(phoneStr));//true

04.检测 .

/*
*检查一个字符串中是否含有﹒
*.表示任意字符
*在正则表达式中使用\作为转义字符
* \.来表示.
    \\表示\
  注意:使用构造函数时,由于它的参数是一个字符串,而\是字符串中转义字符,
  如果要使用\则需要使用\\来代替

*/
var reg = /\./ ;
console.log(reg.test( "b"));//false

//构造函数检测点
reg=new RegExp( "l 1." );

05.转义特殊写法

var reg = new RegExp('\w')
// var reg = /\w/ ;
console.log(reg.test(123));//false  why
/*
\w -任意字母、数字、_  [A-z0-9_]  小写

\w    -除了字母、数字、_     [^A-z0-9_] 大写

\d    -任意的数字   [0-9]
\D    除了数字  [^0-9]
\s    空格
\S    除了空格
\b  单词边界
\B  除了单词边界
*/
reg = /\w/ ;
reg =/\W/ ;

reg = /\d/ ;
reg = /D/ ;

reg = /s/ ;
reg = /S/

console.log(reg.test("123"));
/*
边界相关
* 创建一个正则表达式检查一个字符串中是否含有单词child
*/
reg = /child/ ;
console.log(reg.test( "hello children")) ;//true
//修正
reg = / \bchild\b/ ;
console.log(reg.test( "hello children" ));//false

/*
非边界相关
    去除字符串中的空格
        去除空格就是使用""来替换空格
*/
var str = "  hello ";  
str = str.replace( /\s/g , "");
console.log(str);//helllo

//去除开头的空格
str = str.replace( /^\s*,"");
console.log(str);//"hello "
//去除结尾的空格
//str = str.replace( /\s*$/,"");

//^\s*//\s*$/ 匹开头和结尾的空格
str = str.replace(/^\s*|\s*$/g,"");

06.电子邮件

/*
*电子邮件
*hello .nihao @ abc.com.cn
*
*任意字母数字下划线.任意字母数字下划线任意字母数字―.任意字母(2-5位) .任意字母(2-5位)
*
*    \w{3,}  (\.\w+)* @ [A-z0-9]+  (\.[A=z]{2,5}){1,2}
*/
var emailReg = /^\w{3,}(\.\w+)*@[A-z0-9]+(\.[A-z]{2,5}){1,2}$/;
var email = "abc.hello@163.com";
console.log(emailReg.test( email));//false

06.实用技巧

g: 全局匹配
i: 忽略大小写
gi: 以上组合

^ 匹配一个输入或一行的开头,/^a/匹配"an A",而不匹配"An a"
$ 匹配一个输入或一行的结尾,/a$/匹配"An a",而不匹配"an A"
* 匹配前面元字符0次或多次,/ba*/将匹配b,ba,baa,baaa
+ 匹配前面元字符1次或多次,/ba+/将匹配ba,baa,baaa
? 匹配前面元字符0次或1次,/ba?/将匹配b,ba
(x) 匹配x保存x在名为$1...$9的变量中
x|y 匹配x或y
{n} 精确匹配n次
{n,} 匹配n次以上
{n,m} 匹配n-m次
[xyz] 字符集(character set),匹配这个集合中的任一一个字符(或元字符)
[^xyz] 不匹配这个集合中的任何一个字符
[\b] 匹配一个退格符
\b 匹配一个单词的边界
\B 匹配一个单词的非边界
\cX 这儿,X是一个控制符,/\cM/匹配Ctrl-M
\d 匹配一个字数字符,/\d/ = /[0-9]/
\D 匹配一个非字数字符,/\D/ = /[^0-9]/
\n 匹配一个换行符
\r 匹配一个回车符
\s 匹配一个空白字符,包括\n,\r,\f,\t,\v等
\S 匹配一个非空白字符,等于/[^\n\f\r\t\v]/
\t 匹配一个制表符
\v 匹配一个重直制表符
\w 匹配一个可以组成单词的字符(alphanumeric,这是我的意译,含数字),包括下划线,如[\w]匹配"$5.98"中的5,等于[a-zA-Z0-9]
\W 匹配一个不可以组成单词的字符,如[\W]匹配"$5.98"中的$,等于[^a-zA-Z0-9]。

28.JS DOM

01.什么是dom

Document Object Model 文档对象模型,通过DOM可以来任意来修改网页中各个内容(随心所意操纵网页)
文档
文档指的是网页,一个网页就是一个文档
对象
对象指将网页中的每一个节点都转换为对象
转换完对象以后,就可以以一种纯面向对象的形式来操作网页了
模型
模型用来表示节点和节点之间的关系,方便操作页面

00.JavaScript基础 - 图10

节点(Node)
节点是构成网页的最基本的单元,网页中的每一个部分都可以称为是一个节点
虽然都是节点,但是节点的类型却是不同的
常用的节点
文档节点 (Document),代表整个网页
元素节点(Element),代表网页中的标签 h1 body
属性节点(Attribute),代表标签中的属性 id=”—-“
文本节点(Text),代表网页中的文本内容
文本

00.JavaScript基础 - 图11

02.JS DOM操作 三剑客

  1. getElementById
    <button id="btn">我是一个按钮</ button>
    //获取到button对象
    //直接通过id名
    var btn = document.getElementById ( "btn" );
    //修改按钮的文字
    console.log(btn.innerHTML);//我是一个按钮
    btn.innerHTML = "I'm Button";
    
  1. getElementsByName

    //查找name=gender的所有节点
    var inputs = document.getElementsByName( "gender");
    alert(inputs.length);//2
    for(var i=e ; i<inputs.length ; i++){
     /*
         *innerHTML用于获取元素内部的HTML代码的
         *对于自结束标签,这个属性没有意义
     */
     alert(inputs[i].innerHTML) ;//空值
     /*
         如果需要读取元素节点属性,|*
         直接使用元素.属性名
             例子:元素.id元素.name元素.value注意:class属性不能采用这种方式
             注意:class属性不能采用这种方式,
                 读取class属性时需要使用元素.className
    
      */
     alert(inputs[i].value);
    }
    
  1. getElementsByTagName
    //查找所有li节点
    //getElementsByTagName()可以根据标签名来获取一组元素节点对象
    //这个方法会给我们返回一个类数组对象,所有查询到的元素都会封装到对象中\
    //即使查询到的元素只有一个,也会封装到数组中返回
    var lis = document.getElementsByTagName( "li");
    //打印lis
    alert(1is.length)//11
    //变量lis
    for(var i=0 ; i<lis.length ; i++){
     alert(lis[i].innerHTML);
    }
    
  • 00.JavaScript基础 - 图12

DOM查询
在网页中浏览器已经为我们提供了 document对象
它代表的是整个网页,它是window对象的属性,可以在页面中直接使用。
document查询方法:
根据元素的id属性查询一个元素节点对象:
document.getElementById(“id属性值”);

<body>
<button id="btn">我是一个按钮</ button>
<script type="text/javascript">

    /*
    *浏览器已经为我们提供文档节点对象这个对象是window属性
        *可以在页面中直接使用,文档节点代表的是整个网页
    */    
    console.log(document) ;//"[object HTMLDocument]"

     <button id="btn">我是一个按钮</ button>
    //获取到button对象
    var btn = document.getElementById ( "btn" );
    //修改按钮的文字
    console.log(btn.innerHTML);//我是一个按钮
    btn.innerHTML = "I'm Button";
</script>
</body>

根据元素的name属性值查询一组元素节点对象:
document.getElementsByName(“name属性值”);
根据标签名来查询一组元素节点对象:
document.getElementsByTagName(“标签名”);

元素的属性:
读取元素的属性:
语法:元素.属性名
例子:
ele.name
ele.id
ele.value
ele.className
注意:class属性的读取不能采用class关键词,
读取class属性时需要使用 元素.className

修改元素的属性:
语法:元素.属性名 = 属性值

innerHTML
使用该属性可以获取或设置元素内部的HTML代码

03.JS事件(Event)

事件指的是用户和浏览器之间的交互行为。比如:点击按钮、关闭窗口、鼠标移动。。。
我们可以为事件来绑定回调函数来响应事件。
绑定事件的方式:

1.可以在标签的事件属性中设置相应的JS代码

例子:

//伪代码
<button onclick="js代码。。。">按钮</button>

/*我们可以在事件对应的属性中设置一些js代码,
    这样当事件被触发时,这些代码将会执行
  这种写法我们称为结构和行为耦合,不方便维护,不推荐使用
*/
/*
*事件,就是用户和浏览器之间的交互行为,*比如:点击按钮,鼠标移动、关团窗口。。。*
*/

<button id="btn" onmousemove="alert(‘讨厌,你点我干嘛!. );">我是一个按钮</button>
<script type="text/javascript">

2.可以通过为对象的指定事件属性设置回调函数的形式来处理事件

例子:

<button id="btn">按钮</button>
<script>
    /*
    *可以为按钮的对应事件绑定处理函数的形式来响应事件
    *这样当事件被触发时,其对应的函数将会被调用
    */
    //获取按钮
    var btn = document.getElementById("btn");
    //绑定函数
    btn.onclick = function(){
        alert(‘讨厌,你点我干嘛!. );
    };
</script>

04.JS文档的加载

js代码为什么一般写在下面

浏览器在加载一个页面时,是按照自上向下的顺序加载的,加载一行执行一行。
如果将script 代码编写到页面的上边,当代码执行时,页面中的DOM对象还没有加载,
此时将会无法正常获取到DOM对象,导致DOM操作失败。

01.解决方式一:

可以将js代码编写到body的下边

<body>
        <button id="btn">按钮</button>

    <script>
            var btn = document.getElementById("btn");
            btn.onclick = function(){
            };
    </script>
</body>

02.解决方式二:

将js代码编写到window.onload = function(){}中
window.onload 对应的回调函数会在整个页面加载完毕以后才执行,
所以可以确保代码执行时,DOM对象已经加载完毕了

<script>
    window.onload = function(){
        var btn = document.getElementById("btn");
        btn.onclick = function(){
        };
    };
</script>

05.JS DOM查询

通过具体的元素节点来查询
元素.getElementsByTagName()
通过标签名查询当前元素的指定后代元素

//应用实例


//01.为id为btn1的按钮绑定一个单击响应函数  getElementById
var btne1 = document.getElementById( "btne1" );
btne1.onclick = function(){
    //查找#bj节点
    var bj = document.getElementById( "bj");
    //打印bj
    // linnerHTML通过这个属性可以获取到元素内部的html代码
    alert(bj.innerHTML);
;

//02.为id为btne2的按钮绑定一个单击响应函数  getElementsByTagName
var btne2 = document.getElementById( "btn02");
btne2.onclick = function(){
    //查找所有li节点
    //getElementsByTagName()可以根据标签名来获取一组元素节点对象
    //这个方法会给我们返回一个类数组对象,所有查询到的元素都会封装到对象中\
    //即使查询到的元素只有一个,也会封装到数组中返回
    var lis = document.getElementsByTagName( "li");
    //打印lis
    alert(1is.length)//11
     //变量lis
    for(var i=0 ; i<lis.length ; i++){
        alert(lis[i].innerHTML);
    }
};

//03.为id为btn3的按钮绑定一个单击响应函数
var btne3 = document.getElementById( "btn03" );btne3.onclick = function( ){
    //查找name=gender的所有节点
    var inputs = document.getElementsByName( "gender");
    alert(inputs.length);//2
    for(var i=e ; i<inputs.length ; i++){
        /*
            *innerHTML用于获取元素内部的HTML代码的
            *对于自结束标签,这个属性没有意义
        */
        alert(inputs[i].innerHTML) ;//空值
        /*
        如果需要读取元素节点属性,|*
        直接使用元素.属性名
            例子:元素.id元素.name元素.value注意:class属性不能采用这种方式
            注意:class属性不能采用这种方式,
                读取class属性时需要使用元素.className

*/
        alert(inputs[i].value);
    }

};

06.DOM案例之切换图片

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">

            *{
                margin: 0;
                padding: 0;
            }

            #outer{
                width: 500px;
                margin: 50px auto;
                padding: 10px;
                background-color: greenyellow;
                /*设置文本居中*/
                text-align: center;
            }
        </style>

        <script type="text/javascript">

            window.onload = function(){
                /*
                 * 点击按钮切换图片
                 */

                //获取两个按钮
                var prev = document.getElementById("prev");
                var next = document.getElementById("next");

                /*
                 * 要切换图片就是要修改img标签的src属性
                 */

                //获取img标签
                var img = document.getElementsByTagName("img")[0];

                //创建一个数组,用来保存图片的路径
                var imgArr = ["img/1.jpg" , "img/2.jpg" , "img/3.jpg" , "img/4.jpg" ,"img/5.jpg"];

                //创建一个变量,来保存当前正在显示的图片的索引
                var index = 0;

                //获取id为info的p元素
                var info = document.getElementById("info");
                //设置提示文字
                info.innerHTML = "一共 "+imgArr.length+" 张图片,当前第 "+(index+1)+" 张";


                //分别为两个按钮绑定单击响应函数
                prev.onclick = function(){

                    /*
                     * 切换到上一张,索引自减
                     */
                    index--;

                    //判断index是否小于0
                    if(index < 0){
                        index = imgArr.length - 1;
                    }

                    img.src = imgArr[index];

                    //当点击按钮以后,重新设置信息
                    info.innerHTML = "一共 "+imgArr.length+" 张图片,当前第 "+(index+1)+" 张";
                };

                next.onclick = function(){

                    /*
                     * 切换到下一张是index自增
                     */
                    index++;

                    if(index > imgArr.length - 1){
                        index = 0;
                    }

                    //切换图片就是修改img的src属性
                    //要修改一个元素的属性 元素.属性 = 属性值
                    img.src = imgArr[index];

                    //当点击按钮以后,重新设置信息
                    info.innerHTML = "一共 "+imgArr.length+" 张图片,当前第 "+(index+1)+" 张";

                };


            };


        </script>
    </head>
    <body>
        <div id="outer">

            <p id="info"></p>

            <img src="img/1.jpg" alt="冰棍" />

            <button id="prev">上一张</button>
            <button id="next">下一张</button>

        </div>
    </body>
</html>

07JS操作子节点

//01.getElementsByTagName() 返回city下所有li节点
//为id为btn04的按钮绑定一个单击响应函数
var btn04 = document.getElementById("btn04");
btn04.onclick = function(){

    //获取id为city的元素
    var city = document.getElementById("city");

    //查找#city下所有li节点
    var lis = city.getElementsByTagName("li");

    for(var i=0 ; i<lis.length ; i++){
        alert(lis[i].innerHTML);
    }

};

//02. childNodes  children  返回#city的所有子节点
//为id为btn05的按钮绑定一个单击响应函数
var btn05 = document.getElementById("btn05");
btn05.onclick = function(){
    //获取id为city的节点
    var city = document.getElementById("city");
    //返回#city的所有子节点
    /*
    * childNodes属性会获取包括文本节点在呢的所有节点
    * 根据DOM标签标签间空白也会当成文本节点
    * 注意:在IE8及以下的浏览器中,不会将空白文本当成子节点,
    *     所以该属性在IE8中会返回4个子元素而其他浏览器是9个
                     */
    var cns = city.childNodes;

    //alert(cns.length);

    /*for(var i=0 ; i<cns.length ; i++){
                        alert(cns[i]);
                    }*/

    /*
    * children属性可以获取当前元素的所有子元素 推荐使用这个
                     */
    var cns2 = city.children;
    alert(cns2.length);
};

//03 返回#phone的第一个子节点
    //为id为btn06的按钮绑定一个单击响应函数
    var btn06 = document.getElementById("btn06");
    btn06.onclick = function(){
        //获取id为phone的元素
        var phone = document.getElementById("phone");
        //返回#phone的第一个子节点
        //phone.childNodes[0];
        //firstChild可以获取到当前元素的第一个子节点(包括空白文本节点)
        var fir = phone.firstChild;

        //firstElementChild获取当前元素的第一个子元素
        /*
        * firstElementChild不支持IE8及以下的浏览器,
        *     如果需要兼容他们尽量不要使用
        */
        //fir = phone.firstElementChild;

        alert(fir);
    };

08.JS操作父节点和兄弟节点

00.JavaScript基础 - 图13

封装函数的概念 回掉函数的最粗浅应用

  • 07 父节点 parentNode; ```javascript //获取id为bj的节点 var bj = document.getElementById(“bj”);

//返回#bj的父节点 var pn = bj.parentNode;



- 
08.前一个兄弟节点  previousSibling;
```javascript
//获取id为android的元素
var and = document.getElementById("android");

//返回#android的前一个兄弟节点(也可能获取到空白的文本)
var ps = and.previousSibling;
  • 获取前一个兄弟元素 previousElementSibling
    var and = document.getElementById("android");
    //previousElementSibling获取前一个兄弟元素,IE8及以下不支持
    var pe = and.previousElementSibling;
    
  • 09.读取#username的value属性值

  • 10.设置#username的value属性值

  • 11.返回#bj的文本值

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Untitled Document</title>
        <link rel="stylesheet" type="text/css" href="style/css.css" />
        <script type="text/javascript">

            /*
             * 定义一个函数,专门用来为指定元素绑定单击响应函数
             *     参数:
             *         idStr 要绑定单击响应函数的对象的id属性值
             *         fun 事件的回调函数,当单击元素时,该函数将会被触发
             */
            function myClick(idStr , fun){
                var btn = document.getElementById(idStr);
                btn.onclick = fun;
            }

            window.onload = function(){=
                 //重点关注 第二个参数是 返回一个回掉函数
                //为id为btn07的按钮绑定一个单击响应函数
                myClick("btn07",function(){
                    //获取id为bj的节点
                    var bj = document.getElementById("bj");
                    //返回#bj的父节点
                    var pn = bj.parentNode;
                    alert(pn.innerHTML);
                    /*
                     * innerText
                     *     - 该属性可以获取到元素内部的文本内容
                     *     - 它和innerHTML类似,不同的是它会自动将html去除
                     */
                    //alert(pn.innerText);


                });


                //为id为btn08的按钮绑定一个单击响应函数
                myClick("btn08",function(){

                    //获取id为android的元素
                    var and = document.getElementById("android");

                    //返回#android的前一个兄弟节点(也可能获取到空白的文本)
                    var ps = and.previousSibling;

                    //previousElementSibling获取前一个兄弟元素,IE8及以下不支持
                    //var pe = and.previousElementSibling;

                    alert(ps);

                });

                //读取#username的value属性值
                myClick("btn09",function(){
                    //获取id为username的元素
                    var um = document.getElementById("username");
                    //读取um的value属性值
                    //文本框的value属性值,就是文本框中填写的内容
                    alert(um.value);
                });


                //设置#username的value属性值
                myClick("btn10",function(){
                    //获取id为username的元素
                    var um = document.getElementById("username");

                    um.value = "今天天气真不错~~~";
                });


                //返回#bj的文本值
                myClick("btn11",function(){

                    //获取id为bj的元素
                    var bj = document.getElementById("bj");

                    //alert(bj.innerHTML);
                    //alert(bj.innerText);

                    //获取bj中的文本节点
                    /*var fc = bj.firstChild;
                    alert(fc.nodeValue);*/

                    alert(bj.firstChild.nodeValue);


                });

            };


        </script>
    </head>
    <body>
        <div id="total">
            <div class="inner">
                <p>
                    你喜欢哪个城市?
                </p>

                <ul id="city">
                    <li id="bj">北京</li>
                    <li>上海</li>
                    <li>东京</li>
                    <li>首尔</li>
                </ul>

                <br>
                <br>

                <p>
                    你喜欢哪款单机游戏?
                </p>

                <ul id="game">
                    <li id="rl">红警</li>
                    <li>实况</li>
                    <li>极品飞车</li>
                    <li>魔兽</li>
                </ul>

                <br />
                <br />

                <p>
                    你手机的操作系统是?
                </p>

                <ul id="phone"><li>IOS</li> <li id="android">Android</li><li>Windows Phone</li></ul>
            </div>

            <div class="inner">
                gender:
                <input class="hello" type="radio" name="gender" value="male"/>
                Male
                <input class="hello" type="radio" name="gender" value="female"/>
                Female
                <br>
                <br>
                name:
                <input type="text" name="name" id="username" value="abcde"/>
            </div>
        </div>
        <div id="btnList">
            <div><button id="btn01">查找#bj节点</button></div>
            <div><button id="btn02">查找所有li节点</button></div>
            <div><button id="btn03">查找name=gender的所有节点</button></div>
            <div><button id="btn04">查找#city下所有li节点</button></div>
            <div><button id="btn05">返回#city的所有子节点</button></div>
            <div><button id="btn06">返回#phone的第一个子节点</button></div>
            <div><button id="btn07">返回#bj的父节点</button></div>
            <div><button id="btn08">返回#android的前一个兄弟节点</button></div>
            <div><button id="btn09">返回#username的value属性值</button></div>
            <div><button id="btn10">设置#username的value属性值</button></div>
            <div><button id="btn11">返回#bj的文本值</button></div>
        </div>
    </body>
</html>

09.JS全选练习

  • getElementById
  • getElementsByName
  • 取反 !
  • 在事件的响应函数中,响应函数是给谁绑定的this就是谁
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>全选练习</title>
<script type="text/javascript">

    window.onload = function(){


        //获取四个多选框items
        var items = document.getElementsByName("items");
        //获取全选/全不选的多选框
        var checkedAllBox = document.getElementById("checkedAllBox");

        /*
         * 全选按钮
         *     - 点击按钮以后,四个多选框全都被选中
         */

        //1.#checkedAllBtn
        //为id为checkedAllBtn的按钮绑定一个单击响应函数
        var checkedAllBtn = document.getElementById("checkedAllBtn");
        checkedAllBtn.onclick = function(){


            //遍历items
            for(var i=0 ; i<items.length ; i++){

                //通过多选框的checked属性可以来获取或设置多选框的选中状态
                //alert(items[i].checked);

                //设置四个多选框变成选中状态
                items[i].checked = true;
            }

            //将全选/全不选设置为选中
            checkedAllBox.checked = true;


        };

        /*
         * 全不选按钮
         *     - 点击按钮以后,四个多选框都变成没选中的状态
         */
        //2.#checkedNoBtn
        //为id为checkedNoBtn的按钮绑定一个单击响应函数
        var checkedNoBtn = document.getElementById("checkedNoBtn");
        checkedNoBtn.onclick = function(){

            for(var i=0; i<items.length ; i++){
                //将四个多选框设置为没选中的状态
                items[i].checked = false;
            }

            //将全选/全不选设置为不选中
            checkedAllBox.checked = false;

        };

        /*
         * 反选按钮
         *     - 点击按钮以后,选中的变成没选中,没选中的变成选中
         */
        //3.#checkedRevBtn
        var checkedRevBtn = document.getElementById("checkedRevBtn");
        checkedRevBtn.onclick = function(){

            //将checkedAllBox设置为选中状态
            checkedAllBox.checked = true;

            for(var i=0; i<items.length ; i++){

                //判断多选框状态
                /*if(items[i].checked){
                    //证明多选框已选中,则设置为没选中状态
                    items[i].checked = false;
                }else{
                    //证明多选框没选中,则设置为选中状态
                    items[i].checked = true;
                }*/

                items[i].checked = !items[i].checked;

                //判断四个多选框是否全选
                //只要有一个没选中则就不是全选
                if(!items[i].checked){
                    //一旦进入判断,则证明不是全选状态
                    //将checkedAllBox设置为没选中状态
                    checkedAllBox.checked = false;
                }
            }

            //在反选时也需要判断四个多选框是否全都选中



        };

        /*
         * 提交按钮:
         *     - 点击按钮以后,将所有选中的多选框的value属性值弹出
         */
        //4.#sendBtn
        //为sendBtn绑定单击响应函数
        var sendBtn = document.getElementById("sendBtn");
        sendBtn.onclick = function(){
            //遍历items
            for(var i=0 ; i<items.length ; i++){
                //判断多选框是否选中
                if(items[i].checked){
                    alert(items[i].value);
                }
            }
        };


        //5.#checkedAllBox
        /*
         * 全选/全不选 多选框
         *     - 当它选中时,其余的也选中,当它取消时其余的也取消
         * 
         * 在事件的响应函数中,响应函数是给谁绑定的this就是谁
         */
        //为checkedAllBox绑定单击响应函数
        checkedAllBox.onclick = function(){

            //alert(this === checkedAllBox);

            //设置多选框的选中状态
            for(var i=0; i <items.length ; i++){
                items[i].checked = this.checked;
            }

        };

        //6.items
        /*
         * 如果四个多选框全都选中,则checkedAllBox也应该选中
         * 如果四个多选框没都选中,则checkedAllBox也不应该选中
         */

        //为四个多选框分别绑定点击响应函数
        for(var i=0 ; i<items.length ; i++){
            items[i].onclick = function(){

                //将checkedAllBox设置为选中状态
                checkedAllBox.checked = true;

                for(var j=0 ; j<items.length ; j++){
                    //判断四个多选框是否全选
                    //只要有一个没选中则就不是全选
                    if(!items[j].checked){
                        //一旦进入判断,则证明不是全选状态
                        //将checkedAllBox设置为没选中状态
                        checkedAllBox.checked = false;
                        //一旦进入判断,则已经得出结果,不用再继续执行循环
                        break;
                    }

                }



            };
        }


    };

</script>
</head>
<body>

    <form method="post" action="">
        你爱好的运动是?<input type="checkbox" id="checkedAllBox" />全选/全不选 

        <br />
        <input type="checkbox" name="items" value="足球" />足球
        <input type="checkbox" name="items" value="篮球" />篮球
        <input type="checkbox" name="items" value="羽毛球" />羽毛球
        <input type="checkbox" name="items" value="乒乓球" />乒乓球
        <br />
        <input type="button" id="checkedAllBtn" value="全 选" />
        <input type="button" id="checkedNoBtn" value="全不选" />
        <input type="button" id="checkedRevBtn" value="反 选" />
        <input type="button" id="sendBtn" value="提 交" />
    </form>
</body>
</html>

10.JS document对象的其他的属性和方法

  1. document.all 貌似已经弃用
    获取页面中的所有元素,相当于document.getElementsByTagName(“*”);
  2. document.documentElement
    获取页面中html根元素
  3. document.body
    获取页面中的body元素
  4. document.getElementsByClassName()
    根据元素的class属性值查询一组元素节点对象
    这个方法不支持IE8及以下的浏览器
  5. document.querySelector() 重点关注
    根据CSS选择器去页面中查询一个元素
    如果匹配到的元素有多个,则它会返回查询到的第一个元素
  6. document.querySelectorAll()
    根据CSS选择器去页面中查询一组元素
    会将匹配到所有元素封装到一个数组中返回,即使只匹配到一个
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <script type="text/javascript">

            window.onload = function(){

                //获取body标签
                //var body = document.getElementsByTagName("body")[0];

                /*
                 * 在document中有一个属性body,它保存的是body的引用
                 */
                var body = document.body;

                /*
                 * document.documentElement保存的是html根标签
                 */
                var html = document.documentElement;

                //console.log(html);

                /*
                 * document.all代表页面中所有的元素
                 */
                var all = document.all;

                //console.log(all.length);

                /*for(var i=0 ; i<all.length ; i++){
                    console.log(all[i]);
                }*/

                //all = document.getElementsByTagName("*");
                //console.log(all.length);


                /*
                 * 根据元素的class属性值查询一组元素节点对象
                 * getElementsByClassName()可以根据class属性值获取一组元素节点对象,
                 *     但是该方法不支持IE8及以下的浏览器
                 */
                //var box1 = document.getElementsByClassName("box1");
                //console.log(box1.length);

                //获取页面中的所有的div
                //var divs = document.getElementsByTagName("div");

                //获取class为box1中的所有的div
                //.box1 div
                /*
                 * document.querySelector()
                 *     - 需要一个选择器的字符串作为参数,可以根据一个CSS选择器来查询一个元素节点对象
                 *     - 虽然IE8中没有getElementsByClassName()但是可以使用querySelector()代替
                 *     - 使用该方法总会返回唯一的一个元素,如果满足条件的元素有多个,那么它只会返回第一个
                 */
                var div = document.querySelector(".box1 div");

                var box1 = document.querySelector(".box1")

                //console.log(div.innerHTML);
                //console.log(box1.innerHTML);

                /*
                 * document.querySelectorAll()
                 *     - 该方法和querySelector()用法类似,不同的是它会将符合条件的元素封装到一个数组中返回
                 *     - 即使符合条件的元素只有一个,它也会返回数组
                 */
                box1 = document.querySelectorAll(".box1");
                box1 = document.querySelectorAll("#box2");
                console.log(box1);

            };


        </script>
    </head>
    <body>
        <div id="box2"></div>    
        <div class="box1">
            我是第一个box1     
            <div>我是box1中的div</div>
        </div>
        <div class="box1">
            <div>我是box1中的div</div>
        </div>
        <div class="box1">
            <div>我是box1中的div</div>
        </div>
        <div class="box1">
            <div>我是box1中的div</div>
        </div>

        <div></div>
    </body>
</html>

11.JS DOM增删改

document.createElement(“TagName”)
可以用于创建一个元素节点对象,
它需要一个标签名作为参数,将会根据该标签名创建元素节点对象,
并将创建好的对象作为返回值返回
document.createTextNode(“textContent”)
可以根据文本内容创建一个文本节点对象

父节点.appendChild(子节点)
向父节点中添加指定的子节点
父节点.insertBefore(新节点,旧节点)
将一个新的节点插入到旧节点的前边
父节点.replaceChild(新节点,旧节点)
使用一个新的节点去替换旧节点

父节点.removeChild(子节点)
删除指定的子节点
推荐方式: 子节点.parentNode.removeChild(子节点)

使用innerHtML也可以完成DOM的增删改的相关操作

//向city中添加广州
var city = document.getElementById( "city" );
/*
*使用innerHTML也可以完成DOM的增删改的相关操作
 一般我们会两种方式结合使用
*/
city.innerHTML += "<li>广州</li>";


//创建一个li
var li = document.createElement( "li");//向li中设置文本
li.innerHTML = "广州";//将li添加到city中
city.appendChild(li);

以上方法,实际就是改变了相应元素(标签)的innerHTML的值。

myClick("btn07",function(){

    var city = document.getElementById("city");

    var li = document.createElement("li");

    li.innerHTML = "广州";

    city.appendChild(li);

});

代码汇总

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Untitled Document</title>
        <link rel="stylesheet" type="text/css" href="style/css.css" />
        <script type="text/javascript">

            window.onload = function() {

                //创建一个"广州"节点,添加到#city下
                myClick("btn01",function(){
                    //创建广州节点 <li>广州</li>
                    //创建li元素节点
                    /*
                     * document.createElement()
                     *     可以用于创建一个元素节点对象,
                     *     它需要一个标签名作为参数,将会根据该标签名创建元素节点对象,
                     *     并将创建好的对象作为返回值返回
                     */
                    var li = document.createElement("li");

                    //创建广州文本节点
                    /*
                     * document.createTextNode()
                     *     可以用来创建一个文本节点对象
                     *  需要一个文本内容作为参数,将会根据该内容创建文本节点,并将新的节点返回
                     */
                    var gzText = document.createTextNode("广州");

                    //将gzText设置li的子节点
                    /*
                     * appendChild()
                     *      - 向一个父节点中添加一个新的子节点
                     *      - 用法:父节点.appendChild(子节点);
                     */
                    li.appendChild(gzText);

                    //获取id为city的节点
                    var city = document.getElementById("city");

                    //将广州添加到city下
                    city.appendChild(li);


                });

                //将"广州"节点插入到#bj前面
                myClick("btn02",function(){
                    //创建一个广州
                    var li = document.createElement("li");
                    var gzText = document.createTextNode("广州");
                    li.appendChild(gzText);

                    //获取id为bj的节点
                    var bj = document.getElementById("bj");

                    //获取city
                    var city = document.getElementById("city");

                    /*
                     * insertBefore()
                     *     - 可以在指定的子节点前插入新的子节点
                     *  - 语法:
                     *         父节点.insertBefore(新节点,旧节点);
                     */
                    city.insertBefore(li , bj);


                });


                //使用"广州"节点替换#bj节点
                myClick("btn03",function(){
                    //创建一个广州
                    var li = document.createElement("li");
                    var gzText = document.createTextNode("广州");
                    li.appendChild(gzText);

                    //获取id为bj的节点
                    var bj = document.getElementById("bj");

                    //获取city
                    var city = document.getElementById("city");

                    /*
                     * replaceChild()
                     *     - 可以使用指定的子节点替换已有的子节点
                     *     - 语法:父节点.replaceChild(新节点,旧节点);
                     */
                    city.replaceChild(li , bj);


                });

                //删除#bj节点
                myClick("btn04",function(){
                    //获取id为bj的节点
                    var bj = document.getElementById("bj");
                    //获取city
                    var city = document.getElementById("city");

                    /*
                     * removeChild()
                     *     - 可以删除一个子节点
                     *     - 语法:父节点.removeChild(子节点);
                     *         
                     *         子节点.parentNode.removeChild(子节点);
                     */
                    //city.removeChild(bj);

                    bj.parentNode.removeChild(bj);
                });


                //读取#city内的HTML代码
                myClick("btn05",function(){
                    //获取city
                    var city = document.getElementById("city");

                    alert(city.innerHTML);
                });

                //设置#bj内的HTML代码
                myClick("btn06" , function(){
                    //获取bj
                    var bj = document.getElementById("bj");
                    bj.innerHTML = "昌平";
                });

                myClick("btn07",function(){

                    //向city中添加广州
                    var city = document.getElementById("city");

                    /*
                     * 使用innerHTML也可以完成DOM的增删改的相关操作
                     * 一般我们会两种方式结合使用
                     */
                    //city.innerHTML += "<li>广州</li>";

                    //创建一个li
                    var li = document.createElement("li");
                    //向li中设置文本
                    li.innerHTML = "广州";
                    //将li添加到city中
                    city.appendChild(li);

                });


            };

            function myClick(idStr, fun) {
                var btn = document.getElementById(idStr);
                btn.onclick = fun;
            }


        </script>

    </head>
    <body>
        <div id="total">
            <div class="inner">
                <p>
                    你喜欢哪个城市?
                </p>

                <ul id="city">
                    <li id="bj">北京</li>
                    <li>上海</li>
                    <li>东京</li>
                    <li>首尔</li>
                </ul>

            </div>
        </div>
        <div id="btnList">
            <div><button id="btn01">创建一个"广州"节点,添加到#city下</button></div>
            <div><button id="btn02">将"广州"节点插入到#bj前面</button></div>
            <div><button id="btn03">使用"广州"节点替换#bj节点</button></div>
            <div><button id="btn04">删除#bj节点</button></div>
            <div><button id="btn05">读取#city内的HTML代码</button></div>
            <div><button id="btn06">设置#bj内的HTML代码</button></div>
            <div><button id="btn07">创建一个"广州"节点,添加到#city下</button></div>
        </div>
    </body>
</html>

12.JS练习 表格增删

01点击超链接以后,删除一个员工的信息

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>添加删除记录练习</title>
<link rel="stylesheet" type="text/css" href="ex_2_style/css.css" />
<script type="text/javascript">

    window.onload = function(){

        /*
         * 点击超链接以后,删除一个员工的信息
         */

        //获取所有额超链接
        var allA = document.getElementsByTagName("a");

        //为每个超链接都绑定一个单击响应函数
        for(var i=0 ; i < allA.length ; i++){
            allA[i].onclick = function(){

                //点击超链接以后需要删除超链接所在的那行
                //这里我们点击那个超链接this就是谁
                //获取当前tr
                var tr = this.parentNode.parentNode;

                //获取要删除的员工的名字
                //var name = tr.getElementsByTagName("td")[0].innerHTML;
                var name = tr.children[0].innerHTML;

                //删除之前弹出一个提示框
                /*
                 * confirm()用于弹出一个带有确认和取消按钮的提示框
                 *     需要一个字符串作为参数,该字符串将会作为提示文字显示出来
                 * 如果用户点击确认则会返回true,如果点击取消则返回false
                 */
                var flag = confirm("确认删除"+name+"吗?");

                //如果用户点击确认
                if(flag){
                    //删除tr
                    tr.parentNode.removeChild(tr);
                }

                /*
                 * 点击超链接以后,超链接会跳转页面,这个是超链接的默认行为,
                 *     但是此时我们不希望出现默认行为,可以通过在响应函数的最后return false来取消默认行为
                 */
                return false;
            };
        }

    };


</script>
</head>
<body>

    <table id="employeeTable">
        <tr>
            <th>Name</th>
            <th>Email</th>
            <th>Salary</th>
            <th>&nbsp;</th>
        </tr>
        <tr>
            <td>Tom</td>
            <td>tom@tom.com</td>
            <td>5000</td>
            <td><a href="javascript:;">Delete</a></td>
        </tr>
        <tr>
            <td>Jerry</td>
            <td>jerry@sohu.com</td>
            <td>8000</td>
            <td><a href="deleteEmp?id=002">Delete</a></td>
        </tr>
        <tr>
            <td>Bob</td>
            <td>bob@tom.com</td>
            <td>10000</td>
            <td><a href="deleteEmp?id=003">Delete</a></td>
        </tr>
    </table>

    <div id="formDiv">

        <h4>添加新员工</h4>

        <table>
            <tr>
                <td class="word">name: </td>
                <td class="inp">
                    <input type="text" name="empName" id="empName" />
                </td>
            </tr>
            <tr>
                <td class="word">email: </td>
                <td class="inp">
                    <input type="text" name="email" id="email" />
                </td>
            </tr>
            <tr>
                <td class="word">salary: </td>
                <td class="inp">
                    <input type="text" name="salary" id="salary" />
                </td>
            </tr>
            <tr>
                <td colspan="2" align="center">
                    <button id="addEmpButton" value="abc">
                        Submit
                    </button>
                </td>
            </tr>
        </table>

    </div>

</body>
</h

02添加新员工

  • ```html <!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01//EN” “http://www.w3.org/TR/html4/strict.dtd">

    Name Email Salary  
    Tom tom@tom.com 5000 Delete
    Jerry jerry@sohu.com 8000 Delete
    Bob bob@tom.com 10000 Delete

    添加新员工

    name:
    email:
    salary:




<a name="bef4b2ca"></a>
#### 03.闭包问题

```html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>添加删除记录练习</title>
<link rel="stylesheet" type="text/css" href="ex_2_style/css.css" />
<script type="text/javascript">

    window.onload = function(){

        /*
         * 点击超链接以后,删除一个员工的信息
         */

        //获取所有额超链接
        var allA = document.getElementsByTagName("a");

        //为每个超链接都绑定一个单击响应函数
        for(var i=0 ; i < allA.length ; i++){
            /*
             * for循环会在页面加载完成之后立即执行,
             *     而响应函数会在超链接被点击时才执行
             * 当响应函数执行时,for循环早已执行完毕
             */

            alert("for循环正在执行"+i);

            allA[i].onclick = function(){

                alert("响应函数正在执行"+i);

                //alert(allA[i]);

                return false;
            };

        }

    };


</script>
</head>
<body>

    <table id="employeeTable">
        <tr>
            <th>Name</th>
            <th>Email</th>
            <th>Salary</th>
            <th>&nbsp;</th>
        </tr>
        <tr>
            <td>Tom</td>
            <td>tom@tom.com</td>
            <td>5000</td>
            <td><a href="javascript:;">Delete</a></td>
        </tr>
        <tr>
            <td>Jerry</td>
            <td>jerry@sohu.com</td>
            <td>8000</td>
            <td><a href="deleteEmp?id=002">Delete</a></td>
        </tr>
        <tr>
            <td>Bob</td>
            <td>bob@tom.com</td>
            <td>10000</td>
            <td><a href="deleteEmp?id=003">Delete</a></td>
        </tr>
    </table>

    <div id="formDiv">

        <h4>添加新员工</h4>

        <table>
            <tr>
                <td class="word">name: </td>
                <td class="inp">
                    <input type="text" name="empName" id="empName" />
                </td>
            </tr>
            <tr>
                <td class="word">email: </td>
                <td class="inp">
                    <input type="text" name="email" id="email" />
                </td>
            </tr>
            <tr>
                <td class="word">salary: </td>
                <td class="inp">
                    <input type="text" name="salary" id="salary" />
                </td>
            </tr>
            <tr>
                <td colspan="2" align="center">
                    <button id="addEmpButton" value="abc">
                        Submit
                    </button>
                </td>
            </tr>
        </table>

    </div>

</body>
</html>

13.JS DOM操作css

01.添加内联样式

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">

            #box1{
                width: 100px;
                height: 100px;
                background-color: red;
            }

        </style>

        <script type="text/javascript">

            window.onload = function(){

                /*
                 * 点击按钮以后,修改box1的大小
                 */
                //获取box1
                var box1 = document.getElementById("box1");
                //为按钮绑定单击响应函数
                var btn01 = document.getElementById("btn01");
                btn01.onclick = function(){

                    //修改box1的宽度
                    /*
                     * 通过JS修改元素的样式:
                     *     语法:元素.style.样式名 = 样式值
                     * 
                     * 注意:如果CSS的样式名中含有-,
                     *         这种名称在JS中是不合法的比如background-color
                     *         需要将这种样式名修改为驼峰命名法,
                     *         去掉-,然后将-后的字母大写
                     * 
                     * 我们通过style属性设置的样式都是内联样式,
                     *     而内联样式有较高的优先级,所以通过JS修改的样式往往会立即显示
                     * 
                     * 但是如果在样式中写了!important,则此时样式会有最高的优先级,
                     *     即使通过JS也不能覆盖该样式,此时将会导致JS修改样式失效
                     *     所以尽量不要为样式添加!important
                     * 
                     * 
                     * 
                     */
                    box1.style.width = "300px";
                    box1.style.height = "300px";
                    box1.style.backgroundColor = "yellow";

                };


                //点击按钮2以后,读取元素的样式
                var btn02 = document.getElementById("btn02");
                btn02.onclick = function(){
                    //读取box1的样式
                    /*
                     *     语法:元素.style.样式名
                     * 
                     * 通过style属性设置和读取的都是内联样式
                     *     无法读取样式表中的样式
                     */
                    //alert(box1.style.height);
                    alert(box1.style.width);
                };
            };


        </script>
    </head>
    <body>

        <button id="btn01">点我一下</button>
        <button id="btn02">点我一下2</button>

        <br /><br />

        <div id="box1"></div>

    </body>
</html>

02.获取元素样式

  • 元素.currentStyle.样式名
  • getComputedstyle()
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">

            #box1{
                width: 100px;
                height: 100px;
                background-color: yellow;
            }

        </style>

        <script type="text/javascript">

            window.onload = function(){

                //点击按钮以后读取box1的样式
                var box1 = document.getElementById("box1");
                var btn01 = document.getElementById("btn01");
                btn01.onclick = function(){
                    //读取box1的宽度
                    //alert(box1.style.width);

                    /*
                     * 获取元素的当前显示的样式
                     *     语法:元素.currentStyle.样式名
                     * 它可以用来读取当前元素正在显示的样式
                     *     如果当前元素没有设置该样式,则获取它的默认值
                     * 
                     * currentStyle只有IE浏览器支持,其他的浏览器都不支持
                     */

                    //alert(box1.currentStyle.width);
                    //box1.currentStyle.width = "200px";
                    //alert(box1.currentStyle.backgroundColor);

                    /*
                     * 在其他浏览器中可以使用
                     *         getComputedStyle()这个方法来获取元素当前的样式
                     *         这个方法是window的方法,可以直接使用
                     * 需要两个参数
                     *         第一个:要获取样式的元素
                     *         第二个:可以传递一个伪元素,一般都传null
                     * 
                     * 该方法会返回一个对象,对象中封装了当前元素对应的样式
                     *     可以通过对象.样式名来读取样式
                     *     如果获取的样式没有设置,则会获取到真实的值,而不是默认值
                     *     比如:没有设置width,它不会获取到auto,而是一个长度
                     * 
                     * 但是该方法不支持IE8及以下的浏览器
                     * 
                     * 通过currentStyle和getComputedStyle()读取到的样式都是只读的,
                     *     不能修改,如果要修改必须通过style属性
                     */
                    //var obj = getComputedStyle(box1,null);

                    /*alert(getComputedStyle(box1,null).width);*/
                    //正常浏览器的方式
                    //alert(getComputedStyle(box1,null).backgroundColor);

                    //IE8的方式
                    //alert(box1.currentStyle.backgroundColor);

                    //alert(getStyle(box1,"width"));

                    var w = getStyle(box1,"width");
                    alert(w);


                };

            };

            /*
             * 定义一个函数,用来获取指定元素的当前的样式
             * 参数:
             *         obj 要获取样式的元素
             *         name 要获取的样式名
             */

            function getStyle(obj , name){

                if(window.getComputedStyle){
                    //正常浏览器的方式,具有getComputedStyle()方法
                    return getComputedStyle(obj , null)[name];
                }else{
                    //IE8的方式,没有getComputedStyle()方法
                    return obj.currentStyle[name];
                }

                //return window.getComputedStyle?getComputedStyle(obj , null)[name]:obj.currentStyle[name];

            }


        </script>
    </head>
    <body>
        <button id="btn01">点我一下</button>
        <br /><br />
        <div id="box1" ></div>
    </body>
</html>

03.其他样式操作属性

  • clientWidth 只读
  • clientHeight 只读
  • offsetWidth
  • offsetHeight
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">

            #box1{
                width: 100px;
                height: 100px;
                background-color: red;
                padding: 10px;
                border: 10px solid yellow;
            }


            #box2{
                padding: 100px;
                background-color: #bfa;
            }

            #box4{
                width: 200px;
                height: 300px;
                background-color: #bfa;
                overflow: auto;
            }

            #box5{
                width: 450px;
                height: 600px;
                background-color: yellow;
            }

        </style>
        <script type="text/javascript">

            window.onload = function(){
                var box1 = document.getElementById("box1");
                var btn01 = document.getElementById("btn01");
                var box4 = document.getElementById("box4");

                btn01.onclick = function(){
                    /*
                     * clientWidth
                     * clientHeight
                     *     - 这两个属性可以获取元素的可见宽度和高度
                     *     - 这些属性都是不带px的,返回都是一个数字,可以直接进行计算
                     *     - 会获取元素宽度和高度,包括内容区和内边距
                     *  - 这些属性都是只读的,不能修改
                     */
                    //alert(box1.clientWidth);
                    //alert(box1.clientHeight);
                    //box1.clientHeight = 300;

                    /*
                     * offsetWidth
                     * offsetHeight
                     *     - 获取元素的整个的宽度和高度,包括内容区、内边距和边框
                     */
                    //alert(box1.offsetWidth);

                    /*
                     * offsetParent
                     *     - 可以用来获取当前元素的定位父元素
                     *  - 会获取到离当前元素最近的开启了定位的祖先元素
                     *         如果所有的祖先元素都没有开启定位,则返回body
                     */
                    var op = box1.offsetParent;

                    //alert(op.id);

                    /*
                     * offsetLeft
                     *     - 当前元素相对于其定位父元素的水平偏移量
                     * offsetTop
                     *     - 当前元素相对于其定位父元素的垂直偏移量
                     */

                    //alert(box1.offsetLeft);

                    /*
                     * scrollWidth
                     * scrollHeight
                     *     - 可以获取元素整个滚动区域的宽度和高度
                     */
                    //alert(box4.clientHeight);
                    //alert(box4.scrollWidth);

                    /*
                     * scrollLeft
                     *     - 可以获取水平滚动条滚动的距离
                     * scrollTop
                     *     - 可以获取垂直滚动条滚动的距离
                     */
                    //alert(box4.scrollLeft);
                    //alert(box4.scrollTop);

                    //alert(box4.clientHeight); // 283

                    //当满足scrollHeight - scrollTop == clientHeight
                    //说明垂直滚动条滚动到底了

                    //当满足scrollWidth - scrollLeft == clientWidth
                    //说明水平滚动条滚动到底
                    //alert(box4.scrollHeight - box4.scrollTop); // 600



                };

            };


        </script>
    </head>
    <body id="body">
        <button id="btn01">点我一下</button>
        <br /><br />

         <div id="box4">
             <div id="box5"></div>
         </div>



        <br /><br />

        <div id="box3">
            <div id="box2" style="position: relative;">
                <div id="box1"></div>
            </div>
        </div>


    </body>
</html>

04.练习 写一下话题叫

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">

            #info{
                width: 300px;
                height: 500px;
                background-color: #bfa;
                overflow: auto;
            }

        </style>
        <script type="text/javascript">
            window.onload = function(){

                /*
                 * 当垂直滚动条滚动到底时使表单项可用
                 * onscroll
                 *     - 该事件会在元素的滚动条滚动时触发
                 */

                //获取id为info的p元素
                var info = document.getElementById("info");
                //获取两个表单项
                var inputs = document.getElementsByTagName("input");
                //为info绑定一个滚动条滚动的事件
                info.onscroll = function(){

                    //检查垂直滚动条是否滚动到底
                    if(info.scrollHeight - info.scrollTop == info.clientHeight){
                        //滚动条滚动到底,使表单项可用
                        /*
                         * disabled属性可以设置一个元素是否禁用,
                         *     如果设置为true,则元素禁用
                         *     如果设置为false,则元素可用
                         */
                        inputs[0].disabled = false;
                        inputs[1].disabled = false;
                    }

                };

            };


        </script>
    </head>
    <body>
        <h3>欢迎亲爱的用户注册</h3>
        <p id="info">
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
            亲爱的用户,请仔细阅读以下协议,如果你不仔细阅读你就别注册
        </p>
        <!-- 如果为表单项添加disabled="disabled" 则表单项将变成不可用的状态 -->
        <input type="checkbox" disabled="disabled" />我已仔细阅读协议,一定遵守
        <input type="submit" value="注册" disabled="disabled" />
    </body>
</html>

读取内联样式:
语法:元素.style.样式名
例子:
元素.style.width
元素.style.height
注意: 如果样式名中带有-,则需要将样式名修改为驼峰命名法将-去掉,然后后的字母改大写
比如:backgroundcolor > backgroundColor
borderwidth > borderWidth
修改内联样式:
语法:元素.style.样式名 = 样式值
通过style修改和读取的样式都是内联样式,由于内联样式的优先级比较高,
所以我们通过JS来修改的样式,往往会立即生效,
但是如果样式中设置了!important,则内联样式将不会生效。

正常浏览器
使用getComputedStyle()
这个方法是window对象的方法,可以返回一个对象,这个对象中保存着当前元素生效样式
参数:
1.要获取样式的元素
2.可以传递一个伪元素,一般传null
例子:
获取元素的宽度
getComputedStyle(box , null)[“width”];
通过该方法读取到样式都是只读的不能修改

IE8
使用currentStyle
语法:
元素.currentStyle.样式名
例子:
box.currentStyle[“width”]
通过这个属性读取到的样式是只读的不能修改

实现兼容性

//对象.属性不存在,不会报错,如果直接寻找对象,(当前作用域到全局作用域)找不到会报错


function getStyle(obj , name){

    if(window.getComputedStyle){

        return getComputedStyle(obj , null)[name];
    }else{

        return obj.currentStyle[name];
    }

}

注意:以下样式都是只读的,未指明偏移量都是相对于当前窗口左上角

clientHeight
元素的可见高度,包括元素的内容区和内边距的高度
clientWidth
元素的可见宽度,包括元素的内容区和内边距的宽度
offsetHeight
整个元素的高度,包括内容区、内边距、边框
offfsetWidth
整个元素的宽度,包括内容区、内边距、边框
offsetParent
当前元素的定位父元素
离他最近的开启了定位的祖先元素,如果所有的元素都没有开启定位,则返回body
offsetLeft
offsetTop
当前元素和定位父元素之间的偏移量
offsetLeft水平偏移量 offsetTop垂直偏移量

scrollHeight
scrollWidth
获取元素滚动区域的高度和宽度

scrollTop
scrollLeft
获取元素垂直和水平滚动条滚动的距离

判断滚动条是否滚动到底
垂直滚动条
scrollHeight -scrollTop = clientHeight

水平滚动
scrollWidth -scrollLeft = clientWidth

14JS.事件对象

01.实例 获取鼠标坐标

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<style type="text/css">

    #areaDiv {
        border: 1px solid black;
        width: 300px;
        height: 50px;
        margin-bottom: 10px;
    }

    #showMsg {
        border: 1px solid black;
        width: 300px;
        height: 20px;
    }

</style>
<script type="text/javascript">

    window.onload = function(){
        /*
         * 当鼠标在areaDiv中移动时,在showMsg中来显示鼠标的坐标
         */
        //获取两个div
        var areaDiv = document.getElementById("areaDiv");
        var showMsg = document.getElementById("showMsg");

        /*
         * onmousemove
         *     - 该事件将会在鼠标在元素中移动时被触发
         * 
         * 事件对象
         *     - 当事件的响应函数被触发时,浏览器每次都会将一个事件对象作为实参传递进响应函数,
         *         在事件对象中封装了当前事件相关的一切信息,比如:鼠标的坐标  键盘哪个按键被按下  鼠标滚轮滚动的方向。。。
         */
        areaDiv.onmousemove = function(event){

            /*
             * 在IE8中,响应函数被处罚时,浏览器不会传递事件对象,
             *     在IE8及以下的浏览器中,是将事件对象作为window对象的属性保存的
             */
            /*if(!event){
                event = window.event;
            }*/

            //解决事件对象的兼容性问题
             // || 如果第一个是true 直接返回第一个 否则返回第二个 
            event = event || window.event;

            /*
             * clientX可以获取鼠标指针的水平坐标
             * cilentY可以获取鼠标指针的垂直坐标
             */
            var x = event.clientX;
            var y = event.clientY;

            //alert("x = "+x + " , y = "+y);

            //在showMsg中显示鼠标的坐标
            showMsg.innerHTML = "x = "+x + " , y = "+y;

        };

    };

</script>
</head>
<body>

    <div id="areaDiv"></div>
    <div id="showMsg"></div>

</body>
</html>

02.实例 div随着鼠标移动

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">
            #box1{
                width: 100px;
                height: 100px;
                background-color: red;
                /*
                 * 开启box1的绝对定位
                 */
                position: absolute;
            }

        </style>

        <script type="text/javascript">
            window.onload = function(){

                /*
                 * 使div可以跟随鼠标移动
                 */

                //获取box1
                var box1 = document.getElementById("box1");
                //绑定鼠标移动事件
                document.onmousemove = function(event){

                    //解决兼容问题
                    event = event || window.event;

                    //获取滚动条滚动的距离
                    /*
                     * chrome认为浏览器的滚动条是body的,可以通过body.scrollTop来获取
                     * 火狐等浏览器认为浏览器的滚动条是html的,
                     */
                    var st = document.body.scrollTop || document.documentElement.scrollTop;
                    var sl = document.body.scrollLeft || document.documentElement.scrollLeft;
                    //var st = document.documentElement.scrollTop;


                    //获取到鼠标的坐标
                    /*
                     * clientX和clientY
                     *     用于获取鼠标在当前的可见窗口的坐标
                     * div的偏移量,是相对于整个页面的
                     * 
                     * pageX和pageY可以获取鼠标相对于当前页面的坐标
                     *     但是这个两个属性在IE8中不支持,所以如果需要兼容IE8,则不要使用
                     */
                    var left = event.clientX;
                    var top = event.clientY;

                    //设置div的偏移量
                    box1.style.left = left + sl + "px";
                    box1.style.top = top + st + "px";

                };


            };


        </script>
    </head>
    <body style="height: 1000px;width: 2000px;">
        <div id="box1"></div>
    </body>
</html>

当响应函数被调用时,浏览器每次都会将一个事件对象作为实参传递进响应函数中,这个事件对象中封装了当前事件的相关信息,比如:鼠标的坐标,键盘的按键,鼠标的按键,滚轮的方向。。

可以在响应函数中定义一个形参,来使用事件对象,但是在IE8以下浏览器中事件对象没有做完实参传递,而是作为window对象的属性保存

例子:

元素.事件 = function(event){
    event = event || window.event;
};

元素.事件 = function(e){
    e = e || event;

};

获取到鼠标的坐标
clientX和clientY
用于获取鼠标在当前的可见窗口的坐标
div的偏移量,是相对于整个页面的

pageX和pageY 可以获取鼠标相对于当前页面的坐标
但是这个两个属性在IE8中不支持,所以如果需要兼容IE8,则不要使用
var left = event.clientX;
var top = event.clientY;

15.JS 事件的冒泡(Bubble)

事件的冒泡指的是事件向上传导,当后代元素上的事件被触发时,将会导致其祖先元素上的同类事件也会触发。
事件的冒泡大部分情况下都是有益的,如果需要取消冒泡,则需要使用事件对象来取消
可以将事件对象的cancelBubble设置为true,即可取消冒泡
例子:

元素.事件 = function(event){
    event = event || window.event;
    event.cancelBubble = true;
};
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">
            #box1{
                width: 200px;
                height: 200px;
                background-color: yellowgreen;
            }

            #s1{
                background-color: yellow;
            }


        </style>
        <script type="text/javascript">

            window.onload = function(){

                /*
                 * 事件的冒泡(Bubble)
                 *     - 所谓的冒泡指的就是事件的向上传导,当后代元素上的事件被触发时,其祖先元素的相同事件也会被触发
                 *     - 在开发中大部分情况冒泡都是有用的,如果不希望发生事件冒泡可以通过事件对象来取消冒泡
                 * 
                 */

                //为s1绑定一个单击响应函数
                var s1 = document.getElementById("s1");
                s1.onclick = function(event){
                    event = event || window.event;
                    alert("我是span的单击响应函数");

                    //取消冒泡
                    //可以将事件对象的cancelBubble设置为true,即可取消冒泡
                    event.cancelBubble = true;
                };

                //为box1绑定一个单击响应函数
                var box1 = document.getElementById("box1");
                box1.onclick = function(event){
                    event = event || window.event;
                    alert("我是div的单击响应函数");

                    event.cancelBubble = true;
                };

                //为body绑定一个单击响应函数
                document.body.onclick = function(){
                    alert("我是body的单击响应函数");
                };


            };


        </script>
    </head>
    <body>

        <div id="box1">
            我是box1
            <span id="s1">我是span</span>
        </div>

    </body>
</html>

16.JS事件的委派

指将事件统一绑定给元素的共同的祖先元素,这样当后代元素上的事件触发时,会一直冒泡到祖先元素,从而通过祖先元素的响应函数来处理事件。

事件委派是利用了冒泡,通过委派可以减少事件绑定的次数,提高程序的性能

我们希望,只绑定一次事件,即可应用到多个的元素上,即使元素是后添加的
我们可以尝试将其绑定给元素的共同的祖先元素

target : event中的target表示的触发事件的对象

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title></title>
        <script type="text/javascript">

            window.onload = function(){

                var u1 = document.getElementById("u1");

                //点击按钮以后添加超链接
                var btn01 = document.getElementById("btn01");
                btn01.onclick = function(){
                    //创建一个li
                    var li = document.createElement("li");
                    li.innerHTML = "<a href='javascript:;' class='link'>新建的超链接</a>";

                    //将li添加到ul中
                    u1.appendChild(li);
                };


                /*
                 * 为每一个超链接都绑定一个单击响应函数
                 * 这里我们为每一个超链接都绑定了一个单击响应函数,这种操作比较麻烦,
                 *     而且这些操作只能为已有的超链接设置事件,而新添加的超链接必须重新绑定
                 */
                //获取所有的a
                var allA = document.getElementsByTagName("a");
                //遍历
                /*for(var i=0 ; i<allA.length ; i++){
                    allA[i].onclick = function(){
                        alert("我是a的单击响应函数!!!");
                    };
                }*/

                /*
                 * 我们希望,只绑定一次事件,即可应用到多个的元素上,即使元素是后添加的
                 * 我们可以尝试将其绑定给元素的共同的祖先元素
                 * 
                 * 事件的委派
                 *     - 指将事件统一绑定给元素的共同的祖先元素,这样当后代元素上的事件触发时,会一直冒泡到祖先元素
                 *         从而通过祖先元素的响应函数来处理事件。
                 *  - 事件委派是利用了冒泡,通过委派可以减少事件绑定的次数,提高程序的性能
                 */

                //为ul绑定一个单击响应函数
                u1.onclick = function(event){
                    event = event || window.event;

                    /*
                     * target
                     *     - event中的target表示的触发事件的对象
                     */
                    //alert(event.target);


                    //如果触发事件的对象是我们期望的元素,则执行否则不执行
                    if(event.target.className == "link"){
                        alert("我是ul的单击响应函数");
                    }

                };

            };

        </script>
    </head>
    <body>
        <button id="btn01">添加超链接</button>

        <ul id="u1" style="background-color: #bfa;">
            <li>
                <p>我是p元素</p>
            </li>
            <li><a href="javascript:;" class="link">超链接一</a></li>
            <li><a href="javascript:;" class="link">超链接二</a></li>
            <li><a href="javascript:;" class="link">超链接三</a></li>
        </ul>

    </body>
</html>

16.JS事件的绑定 修改this的指向

addEventListener()
通过这个方法也可以为元素绑定响应函数
参数:
1.事件的字符串,不要on
2.回调函数,当事件触发时该函数会被调用
3.是否在捕获阶段触发事件,需要一个布尔值,一般都传false

使用addEventListener()可以同时为一个元素的相同事件同时绑定多个响应函数,
这样当事件被触发时,响应函数将会按照函数的绑定顺序执行

这个方法不支持IE8及以下的浏览器

btn01.addEventListener("click",function(){
    alert(1);
},false);

btn01.addEventListener("click",function(){
    alert(2);
},false);

attachEvent()

在IE8中可以使用attachEvent()来绑定事件
参数:
1.事件的字符串,要on
2.回调函数

这个方法也可以同时为一个事件绑定多个处理函数,
不同的是它是后绑定先执行,执行顺序和addEventListener()相反

btn01.attachEvent("onclick",function(){
alert(1);
});

btn01.attachEvent("onclick",function(){
alert(2);
});

function bind(obj , eventStr , callback){
    if(obj.addEventListener){

        obj.addEventListener(eventStr , callback , false);
    }else{

        obj.attachEvent("on"+eventStr , function(){

            callback.call(obj);
        });
    }
}
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <script type="text/javascript">

            window.onload = function(){

                /*
                 * 点击按钮以后弹出一个内容
                 */
                //获取按钮对象
                var btn01 = document.getElementById("btn01");

                /*
                 * 使用 对象.事件 = 函数 的形式绑定响应函数,
                 *     它只能同时为一个元素的一个事件绑定一个响应函数,
                 *     不能绑定多个,如果绑定了多个,则后边会覆盖掉前边的
                 */

                //为btn01绑定一个单击响应函数
                /*btn01.onclick = function(){
                    alert(1);
                };*/

                //为btn01绑定第二个响应函数
                /*btn01.onclick = function(){
                    alert(2);
                };*/

                /*
                 * addEventListener()
                 *     - 通过这个方法也可以为元素绑定响应函数
                 *  - 参数:
                 *         1.事件的字符串,不要on
                 *         2.回调函数,当事件触发时该函数会被调用
                 *         3.是否在捕获阶段触发事件,需要一个布尔值,一般都传false
                 * 
                 * 使用addEventListener()可以同时为一个元素的相同事件同时绑定多个响应函数,
                 *     这样当事件被触发时,响应函数将会按照函数的绑定顺序执行
                 * 
                 * 这个方法不支持IE8及以下的浏览器
                 */
                /*btn01.addEventListener("click",function(){
                    alert(1);
                },false);

                btn01.addEventListener("click",function(){
                    alert(2);
                },false);

                btn01.addEventListener("click",function(){
                    alert(3);
                },false);*/

                /*
                 * attachEvent()
                 *     - 在IE8中可以使用attachEvent()来绑定事件
                 *  - 参数:
                 *         1.事件的字符串,要on
                 *         2.回调函数
                 * 
                 *  - 这个方法也可以同时为一个事件绑定多个处理函数,
                 *         不同的是它是后绑定先执行,执行顺序和addEventListener()相反
                 */
                /*btn01.attachEvent("onclick",function(){
                    alert(1);
                });

                btn01.attachEvent("onclick",function(){
                    alert(2);
                });

                btn01.attachEvent("onclick",function(){
                    alert(3);
                });*/

                /*btn01.addEventListener("click",function(){
                    alert(this);
                },false);*/

                /*btn01.attachEvent("onclick",function(){
                    alert(this);
                });*/

                bind(btn01 , "click" , function(){
                    alert(this);
                });


            };

            //定义一个函数,用来为指定元素绑定响应函数
            /*
             * addEventListener()中的this,是绑定事件的对象
             * attachEvent()中的this,是window
             *  需要统一两个方法this
             */
            /*
             * 参数:
             *     obj 要绑定事件的对象
             *     eventStr 事件的字符串(不要on)
             *  callback 回调函数
             */
            function bind(obj , eventStr , callback){
                if(obj.addEventListener){
                    //大部分浏览器兼容的方式
                    obj.addEventListener(eventStr , callback , false);
                }else{
                    /*
                     * this是谁由调用方式决定
                     * callback.call(obj)
                     */
                    //IE8及以下
                    obj.attachEvent("on"+eventStr , function(){
                        //在匿名函数中调用回调函数
                        callback.call(obj);
                    });
                }
            }

        </script>
    </head>
    <body>

        <button id="btn01">点我一下</button>
    </body>
</html>

17. JS事件的传播

关于事件的传播网景公司和微软公司有不同的理解
微软公司认为事件应该是由内向外传播,也就是当事件触发时,应该先触发当前元素上的事件,
然后再向当前元素的祖先元素上传播,也就说事件应该在冒泡阶段执行。00.JavaScript基础 - 图14
网景公司认为事件应该是由外向内传播的,也就是当前事件触发时,应该先触发当前元素的最外层的祖先元素的事件,
然后在向内传播给后代元素
W3C综合了两个公司的方案,将事件传播分成了三个阶段
1.捕获阶段
在捕获阶段时从最外层的祖先元素,向目标元素进行事件的捕获,但是默认此时不会触发事件
2.目标阶段
事件捕获到目标元素,捕获结束开始在目标元素上触发事件
3.冒泡阶段
事件从目标元素向他的祖先元素传递,依次触发祖先元素上的事件

如果希望在捕获阶段就触发事件,可以将addEventListener()的第三个参数设置为true
一般情况下我们不会希望在捕获阶段触发事件,所以这个参数一般都是false

IE8及以下的浏览器中没有捕获阶段

18.练习 拖拽div

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">

            #box1{
                width: 100px;
                height: 100px;
                background-color: red;
                position: absolute;
            }

            #box2{
                width: 100px;
                height: 100px;
                background-color: yellow;
                position: absolute;

                left: 200px;
                top: 200px;
            }

        </style>

        <script type="text/javascript">

            window.onload = function(){
                /*
                 * 拖拽box1元素
                 *  - 拖拽的流程
                 *         1.当鼠标在被拖拽元素上按下时,开始拖拽  onmousedown
                 *         2.当鼠标移动时被拖拽元素跟随鼠标移动 onmousemove
                 *         3.当鼠标松开时,被拖拽元素固定在当前位置    onmouseup
                 */

                //获取box1
                var box1 = document.getElementById("box1");
                //为box1绑定一个鼠标按下事件
                //当鼠标在被拖拽元素上按下时,开始拖拽  onmousedown
                box1.onmousedown = function(event){
                    event = event || window.event;
                    //div的偏移量 鼠标.clentX - 元素.offsetLeft
                    //div的偏移量 鼠标.clentY - 元素.offsetTop
                    var ol = event.clientX - box1.offsetLeft;
                    var ot = event.clientY - box1.offsetTop;


                    //为document绑定一个onmousemove事件
                    document.onmousemove = function(event){
                        event = event || window.event;
                        //当鼠标移动时被拖拽元素跟随鼠标移动 onmousemove
                        //获取鼠标的坐标
                        var left = event.clientX - ol;
                        var top = event.clientY - ot;

                        //修改box1的位置
                        box1.style.left = left+"px";
                        box1.style.top = top+"px";

                    };

                    //为document绑定一个鼠标松开事件
                    document.onmouseup = function(){
                        //当鼠标松开时,被拖拽元素固定在当前位置    onmouseup
                        //取消document的onmousemove事件
                        document.onmousemove = null;
                        //取消document的onmouseup事件
                        document.onmouseup = null;
                    };
                };




            };


        </script>
    </head>
    <body>
        <div id="box1"></div>

        <div id="box2"></div>
    </body>
</html>

19.练习 拖拽优化

包含浏览器兼容 ie使用setCapture

&&的妙用

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">

            #box1{
                width: 100px;
                height: 100px;
                background-color: red;
                position: absolute;
            }

            #box2{
                width: 100px;
                height: 100px;
                background-color: yellow;
                position: absolute;

                left: 200px;
                top: 200px;
            }

        </style>

        <script type="text/javascript">

            window.onload = function(){
                /*
                 * 拖拽box1元素
                 *  - 拖拽的流程
                 *         1.当鼠标在被拖拽元素上按下时,开始拖拽  onmousedown
                 *         2.当鼠标移动时被拖拽元素跟随鼠标移动 onmousemove
                 *         3.当鼠标松开时,被拖拽元素固定在当前位置    onmouseup
                 */

                //获取box1
                var box1 = document.getElementById("box1");
                var box2 = document.getElementById("box2");
                //为box1绑定一个鼠标按下事件
                //当鼠标在被拖拽元素上按下时,开始拖拽  onmousedown
                box1.onmousedown = function(event){

                    //设置box1捕获所有鼠标按下的事件
                    /*
                     * setCapture()
                     *     - 只有IE支持,但是在火狐中调用时不会报错,
                     *         而如果使用chrome调用,会报错
                     */
                    /*if(box1.setCapture){
                        box1.setCapture();
                    }*/
                    box1.setCapture && box1.setCapture();


                    event = event || window.event;
                    //div的偏移量 鼠标.clentX - 元素.offsetLeft
                    //div的偏移量 鼠标.clentY - 元素.offsetTop
                    var ol = event.clientX - box1.offsetLeft;
                    var ot = event.clientY - box1.offsetTop;


                    //为document绑定一个onmousemove事件
                    document.onmousemove = function(event){
                        event = event || window.event;
                        //当鼠标移动时被拖拽元素跟随鼠标移动 onmousemove
                        //获取鼠标的坐标
                        var left = event.clientX - ol;
                        var top = event.clientY - ot;

                        //修改box1的位置
                        box1.style.left = left+"px";
                        box1.style.top = top+"px";

                    };

                    //为document绑定一个鼠标松开事件
                    document.onmouseup = function(){
                        //当鼠标松开时,被拖拽元素固定在当前位置    onmouseup
                        //取消document的onmousemove事件
                        document.onmousemove = null;
                        //取消document的onmouseup事件
                        document.onmouseup = null;
                        //当鼠标松开时,取消对事件的捕获
                        box1.releaseCapture && box1.releaseCapture();
                    };

                    /*
                     * 当我们拖拽一个网页中的内容时,浏览器会默认去搜索引擎中搜索内容,
                     *     此时会导致拖拽功能的异常,这个是浏览器提供的默认行为,
                     *     如果不希望发生这个行为,则可以通过return false来取消默认行为
                     * 
                     * 但是这招对IE8不起作用
                     */
                    return false;

                };



            };


        </script>
    </head>
    <body>

        我是一段文字

        <div id="box1"></div>

        <div id="box2"></div>
    </body>
</html>

20.练习 拖拽封装优化

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">

            #box1{
                width: 100px;
                height: 100px;
                background-color: red;
                position: absolute;
            }

            #box2{
                width: 100px;
                height: 100px;
                background-color: yellow;
                position: absolute;

                left: 200px;
                top: 200px;
            }

        </style>

        <script type="text/javascript">

            window.onload = function(){
                /*
                 * 拖拽box1元素
                 *  - 拖拽的流程
                 *         1.当鼠标在被拖拽元素上按下时,开始拖拽  onmousedown
                 *         2.当鼠标移动时被拖拽元素跟随鼠标移动 onmousemove
                 *         3.当鼠标松开时,被拖拽元素固定在当前位置    onmouseup
                 */

                //获取box1
                var box1 = document.getElementById("box1");
                var box2 = document.getElementById("box2");
                var img1 = document.getElementById("img1");

                //开启box1的拖拽
                drag(box1);
                //开启box2的
                drag(box2);

                drag(img1);




            };

            /*
             * 提取一个专门用来设置拖拽的函数
             * 参数:开启拖拽的元素
             */
            function drag(obj){
                //当鼠标在被拖拽元素上按下时,开始拖拽  onmousedown
                obj.onmousedown = function(event){

                    //设置box1捕获所有鼠标按下的事件
                    /*
                     * setCapture()
                     *     - 只有IE支持,但是在火狐中调用时不会报错,
                     *         而如果使用chrome调用,会报错
                     */
                    /*if(box1.setCapture){
                        box1.setCapture();
                    }*/
                    obj.setCapture && obj.setCapture();


                    event = event || window.event;
                    //div的偏移量 鼠标.clentX - 元素.offsetLeft
                    //div的偏移量 鼠标.clentY - 元素.offsetTop
                    var ol = event.clientX - obj.offsetLeft;
                    var ot = event.clientY - obj.offsetTop;


                    //为document绑定一个onmousemove事件
                    document.onmousemove = function(event){
                        event = event || window.event;
                        //当鼠标移动时被拖拽元素跟随鼠标移动 onmousemove
                        //获取鼠标的坐标
                        var left = event.clientX - ol;
                        var top = event.clientY - ot;

                        //修改box1的位置
                        obj.style.left = left+"px";
                        obj.style.top = top+"px";

                    };

                    //为document绑定一个鼠标松开事件
                    document.onmouseup = function(){
                        //当鼠标松开时,被拖拽元素固定在当前位置    onmouseup
                        //取消document的onmousemove事件
                        document.onmousemove = null;
                        //取消document的onmouseup事件
                        document.onmouseup = null;
                        //当鼠标松开时,取消对事件的捕获
                        obj.releaseCapture && obj.releaseCapture();
                    };

                    /*
                     * 当我们拖拽一个网页中的内容时,浏览器会默认去搜索引擎中搜索内容,
                     *     此时会导致拖拽功能的异常,这个是浏览器提供的默认行为,
                     *     如果不希望发生这个行为,则可以通过return false来取消默认行为
                     * 
                     * 但是这招对IE8不起作用
                     */
                    return false;

                };
            }


        </script>
    </head>
    <body>

        我是一段文字

        <div id="box1"></div>

        <div id="box2"></div>

        <img src="img/an.jpg" id="img1" style="position: absolute;"/>
    </body>
</html>

21常用事件 滚轮+键盘

拖拽事件

<!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
        <title></title>
<style type="text/css">

    #box1{
width: 100px;
height: 100px;
background-color: red;
position: absolute;
}

#box2{
width: 100px;
height: 100px;
background-color: yellow;
position: absolute;

left: 200px;
top: 200px;
}

    </style>

<script type="text/javascript">

    window.onload = function(){

    var box1 = document.getElementById("box1");
    var box2 = document.getElementById("box2");
    var img1 = document.getElementById("img1");

    drag(box1);

    drag(box2);

    drag(img1);

};

function drag(obj){

    obj.onmousedown = function(event){

        obj.setCapture && obj.setCapture();

        event = event || window.event;

        var ol = event.clientX - obj.offsetLeft;
        var ot = event.clientY - obj.offsetTop;

        document.onmousemove = function(event){
            event = event || window.event;

            var left = event.clientX - ol;
            var top = event.clientY - ot;

            obj.style.left = left+"px";
            obj.style.top = top+"px";

        };

        document.onmouseup = function(){

            document.onmousemove = null;

            document.onmouseup = null;

            obj.releaseCapture && obj.releaseCapture();
        };

        return false;
    };
}

</script>
</head>
<body>

    我是一段文字

<div id="box1"></div>

<div id="box2"></div>

<img src="img/an.jpg" id="img1" style="position: absolute;"/>
    </body>
</html>

滚轮事件:

onwheel都支持

<!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
        <title></title>
<style type="text/css">

    #box1{
width: 100px;
height: 100px;
background-color: red;
}

    </style>
<script type="text/javascript">

    window.onload = function(){

    var box1 = document.getElementById("box1");

    box1.onmousewheel = function(event){

        event = event || window.event;

        if(event.wheelDelta > 0 || event.detail < 0){

            box1.style.height = box1.clientHeight - 10 + "px";

        }else{

            box1.style.height = box1.clientHeight + 10 + "px";
        }

        event.preventDefault && event.preventDefault();

        return false;

    };

    bind(box1,"DOMMouseScroll",box1.onmousewheel);

};

function bind(obj , eventStr , callback){
    if(obj.addEventListener){

        obj.addEventListener(eventStr , callback , false);
    }else{

        obj.attachEvent("on"+eventStr , function(){

            callback.call(obj);
        });
    }
}

</script>
</head>
<body style="height: 2000px;">

    <div id="box1"></div>

</body>
</html>

键盘事件:
onkeydown
按键被按下
对于onkeydown来说如果一直按着某个按键不松手,则事件会一直触发
当onkeydown连续触发时,第一次和第二次之间会间隔稍微长一点,其他的会非常的快,这种设计是为了防止误操作的发生。
onkeyup
按键被松开

键盘事件一般都会绑定给一些可以获取到焦点的对象或者是document

keyCode

可以通过keyCode来获取按键的编码
通过它可以判断哪个按键被按下
除了keyCode,事件对象中还提供了几个属性
altKey
ctrlKey
shiftKey
这个三个用来判断alt ctrl 和 shift是否被按下
如果按下则返回true,否则返回false


if(event.keyCode === 89 && event.ctrlKey){
    console.log("ctrl和y都被按下了");
}
input.onkeydown = function(event) {
    event = event || window.event;

    if(event.keyCode >= 48 && event.keyCode  57) {

        return false;
    }
};

29.JS BOM

浏览器对象模型(browser object model)
BOM可以使我们通过JS来操作浏览器
在BOM中为我们提供了一组对象,用来完成对浏览器的操作
BOM对象

  • Window
    代表的是整个浏览器的窗口,同时window也是网页中的全局对象
  • Navigator
    代表的当前浏览器的信息,通过该对象可以来识别不同的浏览器
  • Location
    代表当前浏览器的地址栏信息,通过Location可以获取地址栏信息,或者操作浏览器跳转页面
  • History
    代表浏览器的历史记录,可以通过该对象来操作浏览器的历史记录
    由于隐私原因,该对象不能获取到具体的历史记录,只能操作浏览器向前或向后翻页
    而且该操作只在当次访问时有效
  • Screen
    代表用户的屏幕的信息,通过该对象可以获取到用户的显示器的相关的信息

这些BOM对象在浏览器中都是作为window对象的属性保存的,
可以通过window对象来使用,也可以直接使用

01.Navigator

代表的当前浏览器的信息,通过该对象可以来识别不同的浏览器
由于历史原因,Navigator对象中的大部分属性都已经不能帮助我们识别浏览器了
一般我们只会使用userAgent来判断浏览器的信息,
userAgent是一个字符串,这个字符串中包含有用来描述浏览器信息的内容,
不同的浏览器会有不同的userAgent

火狐的userAgent
Mozilla5.0 (Windows NT 6.1; WOW64; rv:50.0) Gecko20100101 Firefox50.0

Chrome的userAgent
Mozilla5.0 (Windows NT 6.1; Win64; x64) AppleWebKit537.36 (KHTML, like Gecko) Chrome52.0.2743.82 Safari537.36

IE8
Mozilla4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)

IE9
Mozilla5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)

IE10
Mozilla5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)

IE11
Mozilla5.0 (Windows NT 6.1; WOW64; Trident7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; rv:11.0) like Gecko
在IE11中已经将微软和IE相关的标识都已经去除了,所以我们基本已经不能通过UserAgent来识别一个浏览器是否是IE了

alert(navigator.appName);

var ua = navigator.userAgent;

console.log(ua);

if(firefoxi.test(ua)){
alert("你是火狐!!!");
}else if(chromei.test(ua)){
alert("你是Chrome");
}else if(msiei.test(ua)){
alert("你是IE浏览器~~~");
}else if("ActiveXObject" in window){
alert("你是IE11,枪毙了你~~~");
}
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title></title>
        <script type="text/javascript">
            /*
             * BOM
             *     - 浏览器对象模型
             *     - BOM可以使我们通过JS来操作浏览器
             *     - 在BOM中为我们提供了一组对象,用来完成对浏览器的操作
             *     - BOM对象
             *         Window
             *             - 代表的是整个浏览器的窗口,同时window也是网页中的全局对象
             *         Navigator
             *             - 代表的当前浏览器的信息,通过该对象可以来识别不同的浏览器
             *         Location
             *             - 代表当前浏览器的地址栏信息,通过Location可以获取地址栏信息,或者操作浏览器跳转页面
             *         History
             *             - 代表浏览器的历史记录,可以通过该对象来操作浏览器的历史记录
             *                 由于隐私原因,该对象不能获取到具体的历史记录,只能操作浏览器向前或向后翻页
             *                 而且该操作只在当次访问时有效
             *         Screen
             *             - 代表用户的屏幕的信息,通过该对象可以获取到用户的显示器的相关的信息
             * 
             * 
             *         这些BOM对象在浏览器中都是作为window对象的属性保存的,
             *             可以通过window对象来使用,也可以直接使用
             * 
             *         
             */

            //console.log(navigator);
            //console.log(location);
            //console.log(history);

            /*
             * Navigator
             *     - 代表的当前浏览器的信息,通过该对象可以来识别不同的浏览器
             *     - 由于历史原因,Navigator对象中的大部分属性都已经不能帮助我们识别浏览器了
             *     - 一般我们只会使用userAgent来判断浏览器的信息,
             *         userAgent是一个字符串,这个字符串中包含有用来描述浏览器信息的内容,
             *         不同的浏览器会有不同的userAgent
             * 
             * 火狐的userAgent
             *     Mozilla/5.0 (Windows NT 6.1; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0
             * 
             * Chrome的userAgent
             *  Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36
             * 
             * IE8
             *     Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)
             * 
             * IE9
             *     Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)
             * 
             * IE10
             *     Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)
             * 
             * IE11
             *     Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; rv:11.0) like Gecko
             *     - 在IE11中已经将微软和IE相关的标识都已经去除了,所以我们基本已经不能通过UserAgent来识别一个浏览器是否是IE了
             */

            //alert(navigator.appName);

            var ua = navigator.userAgent;

            console.log(ua);

            if(/firefox/i.test(ua)){
                alert("你是火狐!!!");
            }else if(/chrome/i.test(ua)){
                alert("你是Chrome");
            }else if(/msie/i.test(ua)){
                alert("你是IE浏览器~~~");
            }else if("ActiveXObject" in window){
                alert("你是IE11,枪毙了你~~~");
            }

            /*
             * 如果通过UserAgent不能判断,还可以通过一些浏览器中特有的对象,来判断浏览器的信息
             * 比如:ActiveXObject
             */
            /*if("ActiveXObject" in window){
                alert("你是IE,我已经抓住你了~~~");
            }else{
                alert("你不是IE~~~");
            }*/

            /*alert("ActiveXObject" in window);*/



        </script>
    </head>
    <body>

    </body>
</html>

02.History

对象可以用来操作浏览器向前或向后翻页
length
属性,可以获取到当成访问的链接数量
back()
可以用来回退到上一个页面,作用和浏览器的回退按钮一样
forward()
可以跳转下一个页面,作用和浏览器的前进按钮一样
go()
可以用来跳转到指定的页面
它需要一个整数作为参数
1:表示向前跳转一个页面 相当于forward()
2:表示向前跳转两个页面
-1:表示向后跳转一个页面
-2:表示向后跳转两个页面

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <script type="text/javascript">
            /*
             * History
             *     - 对象可以用来操作浏览器向前或向后翻页
             */
            window.onload = function(){

                //获取按钮对象
                var btn = document.getElementById("btn");

                btn.onclick = function(){
                    /*
                     * length
                     *     - 属性,可以获取到当成访问的链接数量
                     */
                    //alert(history.length);

                    /*
                     * back()
                     *     - 可以用来回退到上一个页面,作用和浏览器的回退按钮一样
                     */
                    //history.back();

                    /*
                     * forward()
                     *     - 可以跳转下一个页面,作用和浏览器的前进按钮一样
                     */
                    //history.forward();

                    /*
                     * go()
                     *     - 可以用来跳转到指定的页面
                     *     - 它需要一个整数作为参数
                     *         1:表示向前跳转一个页面 相当于forward()
                     *         2:表示向前跳转两个页面
                     *         -1:表示向后跳转一个页面
                     *         -2:表示向后跳转两个页面
                     */
                    history.go(-2);
                };

            };

        </script>
    </head>
    <body>

        <button id="btn">点我一下</button>

        <h1>History</h1>

        <a href="01.BOM.html">去BOM</a>
    </body>
</html>

03.Location

该对象中封装了浏览器的地址栏的信息
如果直接打印location,则可以获取到地址栏的信息(当前页面的完整路径)
alert(location);
如果直接将location属性修改为一个完整的路径,或相对路径
则我们页面会自动跳转到该路径,并且会生成相应的历史记录
location = “http:www.baidu.com”;
location = “01.BOM.html”;
assign()
用来跳转到其他的页面,作用和直接修改location一样
reload()
用于重新加载当前页面,作用和刷新按钮一样
如果在方法中传递一个true,作为参数,则会强制清空缓存刷新页面
location.reload(true);
replace()
可以使用一个新的页面替换当前页面,调用完毕也会跳转页面
不会生成历史记录,不能使用回退按钮回退

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <script type="text/javascript">
            /*
             * Location
             *     - 该对象中封装了浏览器的地址栏的信息
             */
            window.onload = function(){

                //获取按钮对象
                var btn = document.getElementById("btn");

                btn.onclick = function(){

                    //如果直接打印location,则可以获取到地址栏的信息(当前页面的完整路径)
                    //alert(location);

                    /*
                     * 如果直接将location属性修改为一个完整的路径,或相对路径
                     *     则我们页面会自动跳转到该路径,并且会生成相应的历史记录
                     */
                    //location = "http://www.baidu.com";
                    //location = "01.BOM.html";

                    /*
                     * assign()
                     *     - 用来跳转到其他的页面,作用和直接修改location一样
                     */
                    //location.assign("http://www.baidu.com");

                    /*
                     * reload()
                     *     - 用于重新加载当前页面,作用和刷新按钮一样
                     *     - 如果在方法中传递一个true,作为参数,则会强制清空缓存刷新页面
                     */
                    //location.reload(true);

                    /*
                     * replace()
                     *     - 可以使用一个新的页面替换当前页面,调用完毕也会跳转页面
                     *         不会生成历史记录,不能使用回退按钮回退
                     */
                    location.replace("01.BOM.html");

                };

            };

        </script>
    </head>
    <body>

        <button id="btn">点我一下</button>

        <h1>Location</h1>

        <input type="text" />
        <a href="01.BOM.html">去BOM</a>
    </body>
</html>

04.定时器相关

01.setInterval()

定时调用
可以将一个函数,每隔一段时间执行一次
参数:
1.回调函数,该函数会每隔一段时间被调用一次
2.每次调用间隔的时间,单位是毫秒

返回值:
返回一个Number类型的数据
这个数字用来作为定时器的唯一标识
clearInterval()可以用来关闭一个定时器
方法中需要一个定时器的标识作为参数,这样将关闭标识对应的定时器

clearInterval()可以接收任意参数,
如果参数是一个有效的定时器的标识,则停止对应的定时器
如果参数不是一个有效的标识,则什么也不做

var num = 1;
var timer = setInterval(function() {
    count.innerHTML = num++;
    if(num == 11) {

        clearInterval(timer);
    }
}, 1000);
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <script type="text/javascript">

            window.onload = function(){

                //获取count
                var count = document.getElementById("count");

                //使count中的内容,自动切换
                /*
                 * JS的程序的执行速度是非常非常快的
                 *     如果希望一段程序,可以每间隔一段时间执行一次,可以使用定时调用
                 */
                /*for(var i=0 ; i<10000 ; i++){
                    count.innerHTML = i;

                    alert("hello");
                }*/

                /*
                 * setInterval()
                 *     - 定时调用
                 *     - 可以将一个函数,每隔一段时间执行一次
                 *     - 参数:
                 *         1.回调函数,该函数会每隔一段时间被调用一次
                 *         2.每次调用间隔的时间,单位是毫秒
                 * 
                 *     - 返回值:
                 *         返回一个Number类型的数据
                 *         这个数字用来作为定时器的唯一标识
                 */
                var num = 1;

                var timer = setInterval(function(){

                    count.innerHTML = num++;

                    if(num == 11){
                        //关闭定时器
                        clearInterval(timer);
                    }

                },1000);

                //console.log(timer);

                //clearInterval()可以用来关闭一个定时器
                //方法中需要一个定时器的标识作为参数,这样将关闭标识对应的定时器
                //clearInterval(timer);

            };


        </script>
    </head>
    <body>
        <h1 id="count"></h1>
    </body>
</html>

02.练习 间隔切换图片

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <script type="text/javascript">

            window.onload = function(){

                /*
                 * 使图片可以自动切换
                 */

                //获取img标签
                var img1 = document.getElementById("img1");

                //创建一个数组来保存图片的路径
                var imgArr = ["img/1.jpg","img/2.jpg","img/3.jpg","img/4.jpg","img/5.jpg"];

                //创建一个变量,用来保存当前图片的索引
                var index = 0;

                //定义一个变量,用来保存定时器的标识
                var timer;

                //为btn01绑定一个单击响应函数
                var btn01 = document.getElementById("btn01");
                btn01.onclick = function(){

                    /*
                     * 目前,我们每点击一次按钮,就会开启一个定时器,
                     *     点击多次就会开启多个定时器,这就导致图片的切换速度过快,
                     *     并且我们只能关闭最后一次开启的定时器
                     */

                    //在开启定时器之前,需要将当前元素上的其他定时器关闭
                    clearInterval(timer);

                    /*
                     * 开启一个定时器,来自动切换图片
                     */
                    timer = setInterval(function(){
                        //使索引自增
                        index++;
                        //判断索引是否超过最大索引
                        /*if(index >= imgArr.length){
                            //则将index设置为0
                            index = 0;
                        }*/
                        index %= imgArr.length;
                        //修改img1的src属性
                        img1.src = imgArr[index];

                    },1000);
                };

                //为btn02绑定一个单击响应函数
                var btn02 = document.getElementById("btn02");
                btn02.onclick = function(){
                    //点击按钮以后,停止图片的自动切换,关闭定时器
                    /*
                     * clearInterval()可以接收任意参数,
                     *     如果参数是一个有效的定时器的标识,则停止对应的定时器
                     *     如果参数不是一个有效的标识,则什么也不做
                     */
                    clearInterval(timer);

                };


            };

        </script>
    </head>
    <body>

        <img id="img1" src="img/1.jpg"/>
        <br /><br />
        <button id="btn01">开始</button>
        <button id="btn02">停止</button>
    </body>
</html>

03.练习 修改动画div移动

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">
            #box1{
                width: 100px;
                height: 100px;
                background-color: red;
                position: absolute;
            }


        </style>

        <script type="text/javascript">

            //使div可以根据不同的方向键向不同的方向移动
            /*
             * 按左键,div向左移
             * 按右键,div向右移
             * 。。。
             */
            window.onload = function(){


                //定义一个变量,来表示移动的速度
                var speed = 10;

                //创建一个变量表示方向
                //通过修改dir来影响移动的方向
                var dir = 0;

                //开启一个定时器,来控制div的移动
                setInterval(function(){
                    /*
                     * 37 左
                     * 38 上
                     * 39 右
                     * 40 下
                     */
                    switch(dir){
                        case 37:
                            //alert("向左"); left值减小
                            box1.style.left = box1.offsetLeft - speed + "px";
                            break;
                        case 39:
                            //alert("向右");
                            box1.style.left = box1.offsetLeft + speed + "px";
                            break;
                        case 38:
                            //alert("向上");
                            box1.style.top = box1.offsetTop - speed + "px";
                            break;
                        case 40:
                            //alert("向下");
                            box1.style.top = box1.offsetTop + speed + "px";
                            break;
                    }
                },30);



                //为document绑定一个按键按下的事件
                document.onkeydown = function(event){
                    event = event || window.event;

                    //当用户按了ctrl以后,速度加快
                    if(event.ctrlKey){
                        speed = 500;
                    }else{
                        speed = 10;
                    }

                    //使dir等于按键的值
                    dir = event.keyCode;
                };

                //当按键松开时,div不再移动
                document.onkeyup = function(){
                    //设置方向为0
                    dir = 0;
                };

            };


        </script>
    </head>
    <body>
        <div id="box1"></div>
    </body>
</html>

04.延时调用setTimeout

延时调用一个函数不马上执行,而是隔一段时间以后在执行,而且只会执行一次
延时调用和定时调用的区别,定时调用会执行多次,而延时调用只会执行一次
延时调用和定时调用实际上是可以互相代替的,在开发中可以根据自己需要去选择

var timer = setTimeout(function(){
console.log(num++);
},3000);

使用clearTimeout()来关闭一个延时调用
clearTimeout(timer);

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <script type="text/javascript">

            var num = 1;

            //开启一个定时器
            /*setInterval(function(){
                console.log(num++);
            },3000);*/


            /*
             * 延时调用,
             *     延时调用一个函数不马上执行,而是隔一段时间以后在执行,而且只会执行一次
             * 
             * 延时调用和定时调用的区别,定时调用会执行多次,而延时调用只会执行一次
             * 
             * 延时调用和定时调用实际上是可以互相代替的,在开发中可以根据自己需要去选择
             */
            var timer = setTimeout(function(){
                console.log(num++);
            },3000);

            //使用clearTimeout()来关闭一个延时调用
            clearTimeout(timer);

        </script>
    </head>
    <body>
    </body>
</html>

05.练习 定时器 按键按后右移

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">

            *{
                margin: 0;
                padding: 0;
            }

            #box1{
                width: 100px;
                height: 100px;
                background-color: red;
                position: absolute;
                left: 0;
            }

        </style>

        <script type="text/javascript">

            window.onload = function(){

                //获取box1
                var box1 = document.getElementById("box1");
                //获取btn01
                var btn01 = document.getElementById("btn01");

                //定义一个变量,用来保存定时器的标识
                var timer;

                //点击按钮以后,使box1向右移动(left值增大)
                btn01.onclick = function(){

                    //关闭上一个定时器
                    clearInterval(timer);

                    //开启一个定时器,用来执行动画效果
                    timer = setInterval(function(){

                        //获取box1的原来的left值
                        var oldValue = parseInt(getStyle(box1,"left"));

                        //在旧值的基础上增加
                        var newValue = oldValue + 1;

                        //判断newValue是否大于800
                        if(newValue > 800){
                            newValue = 800;
                        }

                        //将新值设置给box1
                        box1.style.left = newValue + "px";

                        //当元素移动到800px时,使其停止执行动画
                        if(newValue == 800){
                            //达到目标,关闭定时器
                            clearInterval(timer);
                        }


                    },30);


                };

            };


            /*
             * 定义一个函数,用来获取指定元素的当前的样式
             * 参数:
             *         obj 要获取样式的元素
             *         name 要获取的样式名
             */
            function getStyle(obj , name){

                if(window.getComputedStyle){
                    //正常浏览器的方式,具有getComputedStyle()方法
                    return getComputedStyle(obj , null)[name];
                }else{
                    //IE8的方式,没有getComputedStyle()方法
                    return obj.currentStyle[name];
                }

            }


        </script>
    </head>
    <body>

        <button id="btn01">点击按钮以后box1向右移动</button>

        <br /><br />

        <div id="box1"></div>

        <div style="width: 0; height: 1000px; border-left:1px black solid; position: absolute; left: 800px;top:0;"></div>

    </body>
</html>

06. 练习 按键移动拓展

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">

            *{
                margin: 0;
                padding: 0;
            }

            #box1{
                width: 100px;
                height: 100px;
                background-color: red;
                position: absolute;
                left: 0;
            }

        </style>

        <script type="text/javascript">

            window.onload = function(){

                //获取box1
                var box1 = document.getElementById("box1");
                //获取btn01
                var btn01 = document.getElementById("btn01");

                //获取btn02
                var btn02 = document.getElementById("btn02");


                //点击按钮以后,使box1向右移动(left值增大)
                btn01.onclick = function(){
                    move(box1 , 800 , 10);
                };


                //点击按钮以后,使box1向左移动(left值减小)
                btn02.onclick = function(){
                    move(box1 , 0 , 10);
                };

            };

            //定义一个变量,用来保存定时器的标识
            var timer;

            //尝试创建一个可以执行简单动画的函数
            /*
             * 参数:
             *     obj:要执行动画的对象
             *     target:执行动画的目标位置
             *     speed:移动的速度(正数向右移动,负数向左移动)
             */
            function move(obj , target ,speed){
                //关闭上一个定时器
                clearInterval(timer);

                //获取元素目前的位置
                var current = parseInt(getStyle(obj,"left"));

                //判断速度的正负值
                //如果从0 向 800移动,则speed为正
                //如果从800向0移动,则speed为负
                if(current > target){
                    //此时速度应为负值
                    speed = -speed;
                }

                //开启一个定时器,用来执行动画效果
                timer = setInterval(function(){

                    //获取box1的原来的left值
                    var oldValue = parseInt(getStyle(obj,"left"));

                    //在旧值的基础上增加
                    var newValue = oldValue + speed;

                    //判断newValue是否大于800
                    //从800 向 0移动
                    //向左移动时,需要判断newValue是否小于target
                    //向右移动时,需要判断newValue是否大于target
                    if((speed < 0 && newValue < target) || (speed > 0 && newValue > target)){
                        newValue = target;
                    }

                    //将新值设置给box1
                    obj.style.left = newValue + "px";

                    //当元素移动到0px时,使其停止执行动画
                    if(newValue == target){
                        //达到目标,关闭定时器
                        clearInterval(timer);
                    }


                },30);
            }


            /*
             * 定义一个函数,用来获取指定元素的当前的样式
             * 参数:
             *         obj 要获取样式的元素
             *         name 要获取的样式名
             */
            function getStyle(obj , name){

                if(window.getComputedStyle){
                    //正常浏览器的方式,具有getComputedStyle()方法
                    return getComputedStyle(obj , null)[name];
                }else{
                    //IE8的方式,没有getComputedStyle()方法
                    return obj.currentStyle[name];
                }

            }


        </script>
    </head>
    <body>

        <button id="btn01">点击按钮以后box1向右移动</button>
        <button id="btn02">点击按钮以后box1向左移动</button>

        <br /><br />

        <div id="box1"></div>

        <div style="width: 0; height: 1000px; border-left:1px black solid; position: absolute; left: 800px;top:0;"></div>

    </body>
</html>

07.练习 按键移动进一步封装

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">

            *{
                margin: 0;
                padding: 0;
            }

            #box1{
                width: 100px;
                height: 100px;
                background-color: red;
                position: absolute;
                left: 0;
            }

            #box2{
                width: 100px;
                height: 100px;
                background-color: yellow;
                position: absolute;
                left: 0;
                top: 200px;
            }

        </style>
        <script type="text/javascript" src="js/tools.js"></script>
        <script type="text/javascript">

            window.onload = function(){

                //获取box1
                var box1 = document.getElementById("box1");
                //获取btn01
                var btn01 = document.getElementById("btn01");

                //获取btn02
                var btn02 = document.getElementById("btn02");


                //点击按钮以后,使box1向右移动(left值增大)
                btn01.onclick = function(){
                    move(box1 ,"left", 800 , 20);
                };


                //点击按钮以后,使box1向左移动(left值减小)
                btn02.onclick = function(){
                    move(box1 ,"left", 0 , 10);
                };


                //获取btn03
                var btn03 = document.getElementById("btn03");
                btn03.onclick = function(){
                    move(box2 , "left",800 , 10);
                };

                //测试按钮
                var btn04 = document.getElementById("btn04");
                btn04.onclick = function(){
                    //move(box2 ,"width", 800 , 10);
                    //move(box2 ,"top", 800 , 10);
                    //move(box2 ,"height", 800 , 10);
                    move(box2 , "width" , 800 , 10 , function(){
                        move(box2 , "height" , 400 , 10 , function(){
                            move(box2 , "top" , 0 , 10 , function(){
                                move(box2 , "width" , 100 , 10 , function(){

                                });
                            });
                        });
                    });
                };
            };

            //定义一个变量,用来保存定时器的标识
            /*
             * 目前我们的定时器的标识由全局变量timer保存,
             *     所有的执行正在执行的定时器都在这个变量中保存
             */
            //var timer;




        </script>
    </head>
    <body>

        <button id="btn01">点击按钮以后box1向右移动</button>
        <button id="btn02">点击按钮以后box1向左移动</button>
        <button id="btn03">点击按钮以后box2向右移动</button>
        <button id="btn04">测试按钮</button>

        <br /><br />

        <div id="box1"></div>
        <div id="box2"></div>

        <div style="width: 0; height: 1000px; border-left:1px black solid; position: absolute; left: 800px;top:0;"></div>

    </body>
</html>

08.练习 轮播图

  • inline-block 元素间的回车键会产生空格
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>

        <style type="text/css">
            *{
                margin: 0;
                padding: 0;
            }

            /*
             * 设置outer的样式
             */
            #outer{
                /*设置宽和高*/
                width: 520px;
                height: 333px;
                /*居中*/
                margin: 50px auto;
                /*设置背景颜色*/
                background-color: greenyellow;
                /*设置padding*/
                padding: 10px 0;
                /*开启相对定位*/
                position: relative;
                /*裁剪溢出的内容*/
                overflow: hidden;
            }

            /*设置imgList*/
            #imgList{
                /*去除项目符号*/
                list-style: none;
                /*设置ul的宽度*/
                /*width: 2600px;*/
                /*开启绝对定位*/
                position: absolute;
                /*设置偏移量*/
                /*
                 * 每向左移动520px,就会显示到下一张图片
                 */
                left: 0px;
            }

            /*设置图片中的li*/
            #imgList li{
                /*设置浮动*/
                float: left;
                /*设置左右外边距*/
                margin: 0 10px;
            }

            /*设置导航按钮*/
            #navDiv{
                /*开启绝对定位*/
                position: absolute;
                /*设置位置*/
                bottom: 15px;
                /*设置left值
                     outer宽度  520
                     navDiv宽度 25*5 = 125
                         520 - 125 = 395/2 = 197.5
                 * */
                /*left: 197px;*/
            }

            #navDiv a{
                /*设置超链接浮动*/
                float: left;
                /*设置超链接的宽和高*/
                width: 15px;
                height: 15px;
                /*设置背景颜色*/
                background-color: red;
                /*设置左右外边距*/
                margin: 0 5px;
                /*设置透明*/
                opacity: 0.5;
                /*兼容IE8透明*/
                filter: alpha(opacity=50);
            }

            /*设置鼠标移入的效果*/
            #navDiv a:hover{
                background-color: black;
            }
        </style>

        <!--引用工具-->
        <script type="text/javascript" src="js/tools.js"></script>
        <script type="text/javascript">
            window.onload = function(){
                //获取imgList
                var imgList = document.getElementById("imgList");
                //获取页面中所有的img标签
                var imgArr = document.getElementsByTagName("img");
                //设置imgList的宽度
                imgList.style.width = 520*imgArr.length+"px";

                /*设置导航按钮居中*/
                //获取navDiv
                var navDiv = document.getElementById("navDiv");
                //获取outer
                var outer = document.getElementById("outer");
                //设置navDiv的left值
                navDiv.style.left = (outer.offsetWidth - navDiv.offsetWidth)/2 + "px";

                //默认显示图片的索引
                var index = 0;
                //获取所有的a
                var allA = document.getElementsByTagName("a");
                //设置默认选中的效果
                allA[index].style.backgroundColor = "black";

                /*
                     点击超链接切换到指定的图片
                         点击第一个超链接,显示第一个图片
                         点击第二个超链接,显示第二个图片
                 * */

                //为所有的超链接都绑定单击响应函数
                for(var i=0; i<allA.length ; i++){

                    //为每一个超链接都添加一个num属性
                    allA[i].num = i;

                    //为超链接绑定单击响应函数
                    allA[i].onclick = function(){

                        //获取点击超链接的索引,并将其设置为index
                        index = this.num;

                        //切换图片
                        /*
                         * 第一张  0 0
                         * 第二张  1 -520
                         * 第三张  2 -1040
                         */
                        //imgList.style.left = -520*index + "px";
                        //设置选中的a
                        setA();

                        //使用move函数来切换图片
                        move(imgList , "left" , -520*index , 20 , function(){

                        });

                    };
                }

                //创建一个方法用来设置选中的a
                function setA(){

                    //遍历所有a,并将它们的背景颜色设置为红色
                    for(var i=0 ; i<allA.length ; i++){
                        allA[i].style.backgroundColor = "";
                    }

                    //将选中的a设置为黑色
                    allA[index].style.backgroundColor = "black";
                };


            };

        </script>
    </head>
    <body>
        <!-- 创建一个外部的div,来作为大的容器 -->
        <div id="outer">
            <!-- 创建一个ul,用于放置图片 -->
            <ul id="imgList">
                <li><img src="img/1.jpg"/></li>
                <li><img src="img/2.jpg"/></li>
                <li><img src="img/3.jpg"/></li>
                <li><img src="img/4.jpg"/></li>
                <li><img src="img/5.jpg"/></li>
            </ul>
            <!--创建导航按钮-->
            <div id="navDiv">
                <a href="javascript:;"></a>
                <a href="javascript:;"></a>
                <a href="javascript:;"></a>
                <a href="javascript:;"></a>
                <a href="javascript:;"></a>
            </div>
        </div>
    </body>
</html>

09.封装函数tools

  • move
  • getStyle
//尝试创建一个可以执行简单动画的函数
/*
 * 参数:
 *     obj:要执行动画的对象
 *     attr:要执行动画的样式,比如:left top width height
 *     target:执行动画的目标位置
 *     speed:移动的速度(正数向右移动,负数向左移动)
 *  callback:回调函数,这个函数将会在动画执行完毕以后执行
 */
function move(obj, attr, target, speed, callback) {
    //关闭上一个定时器
    clearInterval(obj.timer);

    //获取元素目前的位置
    var current = parseInt(getStyle(obj, attr));

    //判断速度的正负值
    //如果从0 向 800移动,则speed为正
    //如果从800向0移动,则speed为负
    if(current > target) {
        //此时速度应为负值
        speed = -speed;
    }

    //开启一个定时器,用来执行动画效果
    //向执行动画的对象中添加一个timer属性,用来保存它自己的定时器的标识
    obj.timer = setInterval(function() {

        //获取box1的原来的left值
        var oldValue = parseInt(getStyle(obj, attr));

        //在旧值的基础上增加
        var newValue = oldValue + speed;

        //判断newValue是否大于800
        //从800 向 0移动
        //向左移动时,需要判断newValue是否小于target
        //向右移动时,需要判断newValue是否大于target
        if((speed < 0 && newValue < target) || (speed > 0 && newValue > target)) {
            newValue = target;
        }

        //将新值设置给box1
        obj.style[attr] = newValue + "px";

        //当元素移动到0px时,使其停止执行动画
        if(newValue == target) {
            //达到目标,关闭定时器
            clearInterval(obj.timer);
            //动画执行完毕,调用回调函数
            callback && callback();
        }

    }, 30);
}

/*
 * 定义一个函数,用来获取指定元素的当前的样式
 * 参数:
 *         obj 要获取样式的元素
 *         name 要获取的样式名
 */
function getStyle(obj, name) {

    if(window.getComputedStyle) {
        //正常浏览器的方式,具有getComputedStyle()方法
        return getComputedStyle(obj, null)[name];
    } else {
        //IE8的方式,没有getComputedStyle()方法
        return obj.currentStyle[name];
    }

}

30.JS类的操作

01.文字理解

直接修改元素的类css:

通过style属性来修改元素的样式,每修改一个样式,浏览器就需要重新渲染一次页面。 这样的执行的性能是比较差的,而且这种形式当我们要修改多个样式时,也不太方便 我希望一行代码,可以同时修改多个样式

我们可以通过修改元素的class属性来间接的修改样式.这样一来,我们只需要修改一次,即可同时修改多个样式,浏览器只需要重新渲染页面一次,性能比较好,
并且这种方式,可以使表现和行为进一步的分离

box.className += " b2";

function addClass(obj, cn) {
    if (!hasClass(obj, cn)) {
        obj.className += " " + cn;
    }
}

function hasClass(obj, cn) {
    var reg = new RegExp("\\b" + cn + "\\b");
    return reg.test(obj.className);
}

function removeClass(obj, cn) {

    var reg = new RegExp("\\b" + cn + "\\b");

    obj.className = obj.className.replace(reg, "");
}

function toggleClass(obj , cn){

    if(hasClass(obj , cn)){

        removeClass(obj , cn);
    }else{

        addClass(obj , cn);
    }
}

02.练习 菜单栏折叠

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title>二级菜单</title>
        <style type="text/css">
            * {
                margin: 0;
                padding: 0;
                list-style-type: none;
            }

            a,img {
                border: 0;
                text-decoration: none;
            }

            body {
                font: 12px/180% Arial, Helvetica, sans-serif, "新宋体";
            }
        </style>

        <link rel="stylesheet" type="text/css" href="css/sdmenu.css" />

        <script type="text/javascript" src="js/tools.js"></script>
        <script type="text/javascript">
            window.onload = function(){

                /*
                 * 我们的每一个菜单都是一个div
                 *     当div具有collapsed这个类时,div就是折叠的状态
                 *     当div没有这个类是,div就是展开的状态
                 */

                /*
                 * 点击菜单,切换菜单的显示状态
                 */
                //获取所有的class为menuSpan的元素
                var menuSpan = document.querySelectorAll(".menuSpan");

                //定义一个变量,来保存当前打开的菜单
                var openDiv = menuSpan[0].parentNode;

                //为span绑定单击响应函数
                for(var i=0 ; i<menuSpan.length ; i++){
                    menuSpan[i].onclick = function(){

                        //this代表我当前点击的span
                        //获取当前span的父元素
                        var parentDiv = this.parentNode;

                        //切换菜单的显示状态
                        toggleMenu(parentDiv);


                        //判断openDiv和parentDiv是否相同
                        if(openDiv != parentDiv  && !hasClass(openDiv , "collapsed")){
                            //打开菜单以后,应该关闭之前打开的菜单
                            //为了可以统一处理动画过渡效果,我们希望在这将addClass改为toggleClass
                            //addClass(openDiv , "collapsed");
                            //此处toggleClass()不需要有移除的功能
                            //toggleClass(openDiv , "collapsed");
                            //切换菜单的显示状态
                            toggleMenu(openDiv);
                        }

                        //修改openDiv为当前打开的菜单
                        openDiv = parentDiv;

                    };
                }

                /*
                 * 用来切换菜单折叠和显示状态
                 */
                function toggleMenu(obj){
                    //在切换类之前,获取元素的高度
                    var begin = obj.offsetHeight;

                    //切换parentDiv的显示
                    toggleClass(obj , "collapsed");

                    //在切换类之后获取一个高度
                    var end = obj.offsetHeight;

                    //console.log("begin = "+begin +" , end = "+end);
                    //动画效果就是将高度从begin向end过渡
                    //将元素的高度重置为begin
                    obj.style.height = begin + "px";

                    //执行动画,从bengin向end过渡
                    move(obj,"height",end,10,function(){
                        //动画执行完毕,内联样式已经没有存在的意义了,删除之
                        obj.style.height = "";
                    });

                }


            };


        </script>

    </head>

    <body>

        <div id="my_menu" class="sdmenu">
            <div>
                <span class="menuSpan">在线工具</span>
                <a href="#">图像优化</a>
                <a href="#">收藏夹图标生成器</a>
                <a href="#">邮件</a>
                <a href="#">htaccess密码</a>
                <a href="#">梯度图像</a>
                <a href="#">按钮生成器</a>
            </div>
            <div class="collapsed">
                <span class="menuSpan">支持我们</span>
                <a href="#">推荐我们</a>
                <a href="#">链接我们</a>
                <a href="#">网络资源</a>
            </div>
            <div class="collapsed">
                <span class="menuSpan">合作伙伴</span>
                <a href="#">JavaScript工具包</a>
                <a href="#">CSS驱动</a>
                <a href="#">CodingForums</a>
                <a href="#">CSS例子</a>
            </div>
            <div class="collapsed">
                <span class="menuSpan">测试电流</span>
                <a href="#">Current or not</a>
                <a href="#">Current or not</a>
                <a href="#">Current or not</a>
                <a href="#">Current or not</a>
            </div>
        </div>
    </body>
</html>

31.JS json

01.什么是json

JavaScript Object Notation JS对象表示法

JS中的对象只有JS自己认识,其他的语言都不认识
JSON就是一个特殊格式的字符串,这个字符串可以被任意的语言所识别,
并且可以转换为任意语言中的对象,JSON在开发中主要用来数据的交互
JSON和JS对象的格式一样,只不过JSON字符串中的属性名必须加双引号
其他的和JS语法一致
JSON分类:
1.对象 {}
2.数组 []

JSON中允许的值:
1.字符串
2.数值
3.布尔值
4.null
5.对象
6.数组

举例:

var arr = '[1,2,3,"hello",true]';

var obj2 = '{"arr":[1,2,3]}';

var arr2 ='[{"name":"孙悟空","age":18,"gender":"男"},{"name":"孙悟空","age":18,"gender":"男"}]';

JSON工具类

json > js对象
JSON.parse()
可以将以JSON字符串转换为js对象
它需要一个JSON字符串作为参数,会将该字符串转换为JS对象并返回

var o = JSON.parse(json);
var o2 = JSON.parse(arr);

var obj3 = {name:”猪八戒” , age:28 , gender:”男”};

JS对象 > JSON
JSON.stringify() -ify/fy,表示”使……化。
可以将一个JS对象转换为JSON字符串
需要一个js对象作为参数,会返回一个JSON字符串

var str = JSON.stringify(obj3);
console.log(str);

JSON这个对象在IE7及以下的浏览器中不支持,所以在这些浏览器中调用时会报错

  • js ie8及以上的使用方式

    • ```html <!DOCTYPE html>