概述

  • JavaScript负责页面中的的行为。

  • 它是一门运行在浏览器端的脚本语言。

  • javascript和java的一些区别:

    • javascript是一个解释性语言,java是编译解释性语言
    • javascript是一个弱势语言,Java是一个强势语言
    • 在页面上引入的方式不同javascript代表用<script>引入,Java代码<%>
    • JS是基于对象,Java是面向对象。

JavaScript组成

1
2
3
4
EcMAScript  + BOM + DOM
ECMAScript: 规定了一些语法,变量,for循环等等结构
BOM: Browser object Model 浏览器对象模型
DOM: Document object Model 文档对象模型

JavaScript与Html的结合方式

  • Javascript与HTML的结合方式有三种:
    • 可以编写到标签的指定属性中
    • 可以编写到script标签中
    • 通过标签将其引入
      • script标签一旦用于引入外部文件了,就不能在编写代码了
      • 即使编写了浏览器也会忽略 ,如果需要则可以在创建一个新的script标签用于编写内部代码
  1. 采用事件来调用,代码写在字符串中

    1
    2
    3
    <button onclick = "alert('大家好')">点击</button>
    <button onclick="alert('hello');">我是按钮</button>
    <a href="javascript:alert('aaa');">超链接</a>
    1. 采用定义函数的方式: 用function来定义函数
    1
    function fun(){ alert('你好')} ;
    1. 采用外部js文件,利用script引入
    1
    2
    3
    4
    5
    6
    // 可以将代码编写到外部的js文件中,然后通过标签将其引入
    <script type="text/javascript" src="文件路径"></script>

    <script type="text/javascript">
    //编写js代码
    </script>

基本语法

JS严格区分大小写

  • JS中每条语句以分号(;)结尾如果不写分号,浏览器会自动添加,但是会消耗一些系统资源

  • 而且有些时候,浏览器会加错分号,所以在开发中分号必须写

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

输出语句

  • 该语句会在浏览器窗口中弹出一个警告框
1
alert("要输出的内容");
  • 该内容将会被写到body标签中,并在页面中显示
1
document.write("要输出的内容");
  • 该内容会被写到开发者工具的控制台中
1
console.log("要输出的内容");

函数声明

  • js函数声明不需要分号,但是赋值语句要加分号
1
2
3
4
5
6
7
function functionName(arg0, arg1, arg2) {
//函数声明
}
var functionName = function (arg0, arg1, arg2) {
//函数表达式
};
注意分号;

注释

  • 单行注释
1
//注释内容
  • 多行注释
1
2
3
/*  
注释内容
*/

字面量

  • 字面量实际上就是一些固定的值,比如 1 2 3 4 true false null NaN "hello"

  • 字面量都是不可以改变的。

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

变量

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

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

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

    1
    var a;
  • 为变量赋值

    1
    a = 1;
  • 声明和赋值同时进行

    1
    var a = 456;

标识符

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

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

  • 规范:

    1. 标识符中可以含有字母数字_$
    2. 标识符不能以数字开头
    3. 标识符不能是JS中的关键字和保留字
    4. 标识符一般采用驼峰命名法 :xxxYyyZzz

六种数据类型

  • JS中一共分成六种数据类型 5个基本数据类型+object,typeof运算符检查数据类型
数据类型 说明
String 字符串
Number 数值
Boolean 布尔值
Null 空值
Undefined 未定义
Object 对象

String 字符串

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

    1
    2
    3
    4
    5
    \'  ==> '
    \" ==> "
    \n ==> 换行
    \t ==> 制表符
    \\ ==> \
  • 使用typeof运算符检查字符串时,会返回"string"

Number 数值

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

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

  • 特殊的数字:能赋值给变量

    • Infinity 正无穷 a = Infinity ,能赋值
    • -Infinity 负无穷 NaN 非法数字(Not A Number)
  • 其他进制的数字的表示:

    • 0b开头表示二进制,但是不是所有的浏览器都支持
    • 0 开头表示八进制
    • 0x 开头表示十六进制
  • 使用typeof检查一个Number类型的数据时,会返回”number” ,(包括NaN 和 Infinity)

Boolean 布尔值

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

Null 空值

  • 空值专门用来表示为空的对象,Null类型的值只有一个null

  • 使用typeof检查一个Null类型的值时会返回”object”

Undefined 未定义

  • 如果声明一个变量但是没有为变量赋值此时变量的值就是undefined

  • 该类型的值只有一个 undefined

  • 使用typeof检查一个Undefined类型的值时,会返回”undefined”

引用数据类型

  • Object 对象

类型转换

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

转换为String

强制类型转换:toString()方法

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

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

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

强制类型转换:String()函数

  • 例子:

    1
    2
    var a = 123;
    a = String(a);
  • 原理:

    • 对于Number Boolean String都会调用他们的toString()方法来将其转换为字符串
    • **对于null值,直接转换为字符串”null”**。
    • 对于undefined直接转换为字符串”undefined”

隐式的类型转换

  • 为任意的数据类型 +""

  • 原理:和String()函数一样

  • 例子:

    1
    2
    var a = true;
    a = a + "";

转换为Number

强制类型转换:调用Number()函数

  • 例子:

    1
    2
    var s = "123";
    s = Number(s);
  1. 字符串 > 数字

    • 如果字符串是一个合法的数字,则直接转换为对应的数字
    • 如果字符串是一个非法的数字,则转换为NaN
    • 如果是一个空串或纯空格的字符串,则转换为0
  2. 布尔值 > 数字

    • true转换为1
    • false转换为0
  3. 空值 > 数字

    • null转换为0
  4. 未定义 > 数字

    • undefined 转换为NaN

强制类型转换:parseXXX

  • 调用parseInt()parseFloat()

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

  • 如果对非String使用parseInt()或parseFloat(),它会先将其转换为String然后在操作parseInt()

  • 可以将一个字符串中的有效的整数位提取出来,并转换为Number

  • 例子:

    1
    2
    var a = "123.456px";
    a = parseInt(a); //123
  • 如果需要可以在parseInt()中指定一个第二个参数可选。给解析的数字指定进制。该值介于 2 ~ 36 之间。

    1
    var result = parseInt("11", 2); //返回 3 (2+1);
  • parseFloat()可以将一个字符串中的有效的小数位提取出来,并转换为Number

    1
    2
    var a = "123.456px";
    a = parseFloat(a); //123.456

隐式的类型转换:

  • 使用一元的+来进行隐式的类型转换

  • 原理:和Number()函数一样

  • 例子:

    1
    2
    var a = "123";
    a = +a;

转换为布尔值

强制类型转换: 使用Boolean()函数

  • 例子:

    1
    2
    var s = "false";
    s = Boolean(s); //true
  1. 字符串 > 布尔
    • 除了空串其余全是true
  2. 数值 > 布尔
    • 除了0和NaN其余的全是true
  3. null、undefined > 布尔
    • 都是false
  4. 对象 > 布尔
    • 都是true

隐式类型转换

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

  • 例子:

    1
    2
    var a = "hello";
    a = !!a; //true

运算符

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

typeof运算符

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

算数运算符

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

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

  • *: 对两个值进行乘法运算并返回结果

  • /: 对两个值进行除法运算并返回结果

  • %: 对两个值进行取余运算并返回结果

  • 除了加法以外,对非Number类型的值进行运算时,都会先转换为Number然后在做运算。

  • 而做加法运算时,如果是两个字符串进行相加,则会做拼串操作,将两个字符连接为一个字符串。

  • 任何值和字符串做加法,都会先转换为字符串,然后再拼串

一元运算符

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

一元的+

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

  • 例子:

    1
    2
    var a = true;
    a = +a;

一元的-

  • 对于JS的减法运算,整体规则是当运算符两边的运算元不为Number时,通过ToNumber()把值转换成Number再计算。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    //Number(直接相减)
    console.log(5 - 2); //3
    console.log(1 - 3); //-2

    //String(转化为Number后相减)
    console.log(3 - "1"); //2
    console.log("7" - 2); //5
    console.log(2 - "7"); //-5
    console.log("2" - 7); //-5
    console.log("7" - "2"); //5
    console.log("2" - "7"); //-5
    console.log("abc" - 1); //NaN

    //Boolean(转换后true为1,false为+0)
    console.log(4 - true); //3
    console.log(true - false); //1

    //undefined(undefined转换后为NaN)
    console.log(1 - undefined); //NaN
    console.log(undefined - 1); //NaN

    //Null(null转换后为+0)
    console.log(1 - null); //1
    console.log(null - 1); //-1
  • Object类型
    由于Object为复杂类型,做减法运算时,要先调用内置的valueOf()转化为Number类型后再做运算

    1
    2
    3
    4
    5
    6
    7
    8
    //Object
    console.log(1 - []); //1
    console.log(1 - {}); //NaN
    console.log({} - 1); //NaN
    console.log([] - []); //0
    console.log({} - {}); //NaN
    console.log({} - []); //NaN
    console.log([] - {}); //NaN
  • 一元运算

    1
    2
    3
    4
    console.log(-1);   //-1
    console.log(-[]); //-0
    console.log(-{}); //NaN
    console.log(-'1'); //-1

自增

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

自减

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

~运算(按位取反)

  • 规则
1
result = ~ [数字]

~ 运算符查看表达式的二进制表示形式的值,并执行位非运算,表达式中的任何一位为 1,则结果中的该位变为 0。表达式中的任何一位为 0,则结果中的该位变为 1。

  • 实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var temp = ~5;
/*
5 二进制 101,补满 32位
00000000000000000000000000000101
按位取反
11111111111111111111111111111010
由于32位开头第一个是1,所以这是一个负数,将二进制转换成负数,需要先反码
00000000000000000000000000000101
之后,再+1
00000000000000000000000000000110
转换成十进制为6,加上符号变成负数 -6
*/
alert(temp);
// 弹出 [-6]

~【数字】,所以~运算符后面的类型要转换为Number。

1
2
3
4
5
6
7
8
9
10
11
12
/**
* JS 按位取非
*/
console.log(~1); //-2
console.log(~2); //-3
console.log(~"abc"); //-1
console.log(~""); //-1
console.log(~true); //-2
console.log(~null); //-1
console.log(~undefined); //-1
console.log(~{}); //-1
console.log(~[]); //-1
  • 扩展~~
1
2
3
4
5
6
console.log(~~true); //-1
console.log(~~false); //1
console.log(~~""); //0
console.log(~~[]); //0
console.log(~~undefined); //0
console.log(~~null); //0

~~运算在****的基础上再做一次操作

逻辑运算符

  • ! 非运算可以对一个布尔值进行取反,true变false false边true

    • 当对非布尔值使用!时,会先将其转换为布尔值然后再取反
    • 我们可以利用!来将其他的数据类型转换为布尔值
  • && 可以对符号两侧的值进行与运算

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

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

    • 对于非布尔值,它会将其转换为布尔值然后做运算,并返回原值

    • 规则:

      1. 如果第一个值为false,则返回第一个值
      2. 2.如果第一个值为true,则返回第二个值
  • ||可以对符号两侧的值进行或运算

    • 只有两端都是false时,才会返回false。只要有一个true,就会返回true。
    • 如果第一个值是true,则不再检查第二个值
    • 对于非布尔值,它会将其转换为布尔值然后做运算,并返回原值
    • 规则:
      1. 如果第一个值为true,则返回第一个值
      2. 如果第一个值为false,则返回第二个值

赋值运算符

  • = 可以将符号右侧的值赋值给左侧变量
  • +=
1
2
3
a += 5 相当于 a = a+5
var str = "hello";
str += "world";
  • -=
1
a -= 5  相当于 a = a-5
  • *=
1
a *= 5 相当于 a = a*5
  • /=
1
a /= 5 相当于 a = a/5
  • %=
1
a %= 5 相当于 a = a%5

关系运算符

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

  • 如果关系成立则返回true,关系不成立则返回false。
  • 如果比较的两个值是非数值,会将其转换为Number然后再比较。
  • 如果比较的两个值都是字符串,此时会比较字符串的Unicode编码,而不会转换为Number。
  • =

  • <

  • <=

相等运算符

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

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

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

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

    • 特殊的值: null和undefined
    • 由于undefined衍生自null,所以null == undefined 会返回true。但是 null === undefined 会返回false。
    • NaN不与任何值相等,包括它自身 NaN == NaN //false
    • 判断一个值是否是NaN 使用isNaN()函数

三元运算符:

  • ?
    • 语法:条件表达式?语句1:语句2;
    • 执行流程:
      1. 先对条件表达式求值判断,
      2. 如果判断结果为true,则执行语句1,并返回执行结果
      3. 如果判断结果为false,则执行语句2,并返回执行结果

优先级

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

下面的表将所有运算符按照优先级的不同从高(20)到低(1)排列。

流程控制语句

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

条件分支语句

if语句

语法一:

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

语法二:

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

语法三:

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

switch语句

语法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
switch(条件表达式){
case 表达式:
语句...
break;
case 表达式:
语句...
break;
case 表达式:
语句...
break;
default:
语句...
break;
}
1
2
3
4
执行流程:
switch...case...语句在执行时,会依次将case后的表达式的值和switch后的表达式的值进行全等比较,
如果比较结果为false,则继续向下比较。如果比较结果为true,则从当前case处开始向下执行代码。
如果所有的case判断结果都为false,则从default处开始执行代码。

循环语句

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

while循环

语法:

1
2
3
4
5
6
7
8
9
while(条件表达式){
语句...
}

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

do…while循环

语法:

1
2
3
4
5
6
7
8
9
do{
语句...
}while(条件表达式)

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

和while的区别

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

for循环

语法:

1
2
3
4
5
6
7
8
9
10
for(①初始化表达式 ; ②条件表达式 ; ④更新表达式){
③语句...
}
执行流程:
首先执行①初始化表达式,初始化一个变量,
然后对②条件表达式进行求值判断,如果为false则终止循环
如果判断结果为true,则执行③循环体
循环体执行完毕,执行④更新表达式,对变量进行更新。
更新表达式执行完毕重复②

死循环

1
2
3
while (true) {}

for (;;) {}

对象(Object)

对象是JS中的引用数据类型 对象是一种复合数据类型,在对象中可以保存多个不同数据类型的属性

使用typeof检查一个对象时,会返回object

对象的分类

  1. 内建对象

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

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

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

创建对象

方式一:

1
var obj = new Object();

方式二:

1
var obj = {};

向对象中添加属性

  • 语法:
1
2
3
4
5
对象.属性名 = 属性值;
对象["属性名"] = 属性值; //这种方式能够使用特殊的属性名

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

读取对象中的属性

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

删除对象中的属性

语法:

1
2
delete 对象.属性名;
delete 对象["属性名"];

方法(method)

  • 可以将一个函数设置为一个对象的属性,当一个对象的属性是一个函数时,我们称这个函数是该对象的方法。

  • 调用的区别

    • 对象.方法名();
    • 函数名() 直接调用

遍历

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

  • 语法:

    1
    2
    3
    4
    "属性名" in 对象
    如果在对象中含有该属性,则返回true
    如果没有则返回false
    循环遍历对象自身的和继承的可枚举属性(不含Symbol属性).
    1
    2
    3
    4
    5
    var obj = { 0: "a", 1: "b", 2: "c" };

    for (var i in obj) {
    console.log(i, ":", obj[i]);
    }
  • 使用对象字面量,在创建对象时直接向对象中添加属性

  • 语法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var obj = {
    属性名: 属性值,
    属性名: 属性值,
    属性名: 属性值,
    属性名: 属性值,
    };
    //遍历对象
    for (var v in obj) {
    document.write("property:name =" + v + "value=" + obj[v] + "<br/>");
    }

基本数据类型和引用数据类型

基本数据类型

  • 基本数据类型的数据,变量是直接保存的它的值。
  • 变量与变量之间是互相独立的,修改一个变量不会影响其他的变量。
  • 比较两个变量时,对于基本数据类型,比较的就是值,
    • String
    • Number
    • Boolean
    • Null
    • Undefined

引用数据类型

  • 引用数据类型的数据,变量是保存的对象的引用(内存地址)。
  • 如果多个变量指向的是同一个对象,此时修改一个变量的属性,会影响其他的变量。
  • 对于引用数据类型比较的是地址,地址相同才相同
    • Object

函数(Function)

  • 函数也是一个对象,也具有普通对象的功能(能有属性)

  • 函数中可以封装一些代码,在需要的时候可以去调用函数来执行这些代码

  • 使用typeof检查一个函数时会返回function

  • 函数的定义有三种方式:

    1. 采用function关键字来定义
    2. 采用匿名的方式来定义
    3. 采用new Function()的方式(了解,不推荐)

创建函数

  • 函数声明

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    function 函数名([形参1,形参2...形参N]){
    语句...
    }

    function fun(){
    alert("大家好") ;
    }
    // 调用 fun() ;

    var a = function(){
    alert("我是匿名函数") ;
    }

    // a() ;

    var b = new Function("x","y","z","alert(x+y+z)") ;
    小括号中最后一个参数是函数体,之前所有的参数都是形参.
    // b(3,4,5) ;
  • 函数表达式

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

调用函数

  • 没有重载的概念

  • 函数调用的时候参数可以传递多个,可以和函数定义的形参个数不符合

  • 如果函数重名了,那么调用的时候一定是调用最后一个,与参数无关。

  • 语法:

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

函数的劫持

  • 改变函数本身的作用.改变javascript的预定义的函数预定义好的功能

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <script type="text/javascript">

    //函数劫持:改变javascript的预定义的函数预定义好的功能
    window.alert = function(x){
    document.write(x) ;
    }
    alert("abc") ;

    /*var a = function(){
    alert("1") ;
    }

    a = function(){
    alert("2") ;
    }*/ //不是函数劫持

    </script>

立即执行函数

  • 函数定义完,立即被调用,这种函数叫做立即执行函数 ,立即执行函数往往只会执行一次
1
2
3
4
(function (a, b) {
console.log("a = " + a);
console.log("b = " + b);
})(123, 456);

形参和实参

  • 形参:形式参数

  • 定义函数时,可以在()中定义一个或多个形参,形参之间使用,隔开

  • 定义形参就相当于在函数内声明了对应的变量但是并不赋值,

  • 形参会在调用时才赋值

  • 实参:实际参数

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

返回值

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

break、continue和return

  • break:退出循环
  • continue:跳过当次循环
  • return:退出函数

作用域

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

全局作用域

  • 直接在script标签中编写的代码都运行在全局作用域中
  • 全局作用域在打开页面时创建,在页面关闭时销毁。
  • 全局作用域中有一个全局对象window,window对象由浏览器提供,
  • 可以在页面中直接使用,它代表的是整个的浏览器的窗口。
  • 在全局作用域中创建的变量都会作为window对象的属性保存
  • 在全局作用域中创建的函数都会作为window对象的方法保存
  • 在全局作用域中创建的变量和函数可以在页面的任意位置访问。
  • 在函数作用域中也可以访问到全局作用域的变量。
  • 尽量不要在全局中创建变量

函数作用域

  • 函数作用域是函数执行时创建的作用域,每次调用函数都会创建一个新的函数作用域。
  • 函数作用域在函数执行时创建,在函数执行结束时销毁。
  • 在函数作用域中创建的变量,不能在全局中访问。
  • 当在函数作用域中使用一个变量时,它会先在自身作用域中寻找,
  • 如果找到了则直接使用,如果没有找到则到上一级作用域中寻找,
  • 如果找到了则使用,找不到则继续向上找,最后没有null

变量的声明提前

  • 在全局作用域中,使用var关键字声明的变量会在所有的代码执行之前被声明,但是不会赋值。

  • 所以我们可以在变量声明前使用变量。但是不使用var关键字声明的变量不会被声明提前。

  • 在函数作用域中,也具有该特性,使用var关键字声明的变量会在函数所有的代码执行前被声明, 如果没有使用var关键字声明变量,则变量会变成全局变量

函数的声明提前

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

全局(内置)函数

方法名 描述
isNaN 用来判断变量是否是数字类型的字符串
NaN: not a Number ,不是一个数字
返回TRUE不是数字
parseInt,parseFloat 将字符串转换为整形的数据(浮点数)
eval 将字符串转换为js代码
a. 主要执行字符串,将结果转换为数字
b. 将json格式的字符串转换为json
escape() 编码
unescape() 解码
encodeURI() 对网址(URL)进行编码
decodeURI() (): 对网址(URL)进行解码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
if(isNaN(a)){
alert("不是数字") ;
}else
alert("是数字") ;

-----------------
alert(eval("3 + 10") + eval("2")) ;//15

---------------------

var b = "中国" ;
var c = escape(b) ;
alert(c) ; //%u4E2D%u56FD
alert(unescape(c)) ; //中国

---------------------------------------
var e = "http://www.sohu.com?a=中国&b=美国" ;
var f = encodeURI(e) ;
alert(f) ; //http://www.sohu.com?a=%E4%B8%AD%E5%9B%BD&b=%E7%BE%8E%E5%9B%BD
alert(decodeURI(f)) ;

对象的属性和方法

call(),apply()

  • 这两个方法都是函数对象的方法需要通过函数对象来调用

  • 通过两个方法可以直接调用函数,并且可以通过第一个实参来指定函数中this

  • 不同的是call是直接传递函数的实参,而apply需要将实参封装到一个数组中传递

    • call 的参数是直接放进去的,第二第三第 n 个参数全都用逗号分隔,直接放到后面 obj.myFun.call(db,'成都', ... ,'string' )
    • apply 的所有参数都必须放在一个数组里面传进去 obj.myFun.apply(db,['成都', ..., 'string' ])
    • bind 返回是函数,调用方法的时候后面多加个 () ,除了返回是函数以外,它 的参数和 call 一样。
    1
    2
    3
    4
    obj.myFun.call(db,'成都','上海');     // 德玛 年龄 99  来自 成都去往上海
    obj.myFun.apply(db,['成都','上海']); // 德玛 年龄 99 来自 成都去往上海
    obj.myFun.bind(db,'成都','上海')(); // 德玛 年龄 99 来自 成都去往上海
    obj.myFun.bind(db,['成都','上海'])();   // 德玛 年龄 99 来自 成都, 上海去往 undefined

arguments

  • arguments和this类似,都是函数中的隐含的参数

  • arguments是一个类数组元素,它用来封装函数执行过程中的实参

  • 所以即使不定义形参,也可以通过arguments来使用实参

  • arguments中有一个属性callee表示当前执行的函数对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    //callee能够打印其本身
    function calleeDemo() {
    alert(arguments.callee);
    }

    //用匿名函数实现的计算10的阶乘
    //匿名函数,没有名子,无名可调。可以用arguments.callee来代替匿名的函数
    (function (n) {
    if (n > 1) return n * arguments.callee(n - 1);
    return n;
    })(10);

this(调用函数的那个对象)

  • 我们每次调用函数时,解析器都会将一个上下文对象作为隐含的参数传递进函数。

  • 使用this来引用上下文对象,根据函数的调用形式不同,this的值也不同。

  • this是函数的上下文对象,根据函数的调用方式不同会执向不同的对象

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

对象构造函数,toString

  • 构造函数是专门用来创建对象的函数,一个构造函数我们也可以称为一个类

  • 通过一个构造函数创建的对象,我们称该对象时这个构造函数的实例

  • 通过同一个构造函数创建的对象,我们称为一类对象

  • 构造函数就是一个普通的函数,只是他的调用方式不同,

    • 如果直接调用,它就是一个普通函数
    • 如果使用new来调用,则它就是一个构造函数 。
  • 例子:

1
2
3
4
5
6
7
8
function Person(name, age, gender) {
this.name = name;
this.age = age;
this.gender = gender;
this.sayName = function () {
alert(this.name);
};
}

实例检查

  1. 创建一个新的对象
  2. 将新的对象作为函数的上下文对象(this)
  3. 执行函数中的代码
  4. 将新建的对象返回
  • instanceof 用来检查一个对象是否是一个类的实例
  • 语法:
1
2
3
4
5
对象 instanceof 构造函数
alert( arr instanceof Array );
alert( a1 instanceof Object ); //任何对象返回的都是true
如果该对象时构造函数的实例,则返回true,否则返回false
Object是所有对象的祖先,所以任何对象和Objectinstanceof都会返回true

toString方法

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

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

1
2
3
4
5
6
7
8
9
10
11
12
//修改Person原型的toString
Person.prototype.toString = function () {
return (
"Person[name=" +
this.name +
",age=" +
this.age +
",gender=" +
this.gender +
"]"
);
};

原型(prototype)

  • 创建一个函数以后,解析器都会默认在函数中添加一个属性prototype

    • prototype属性指向的是一个对象,这个对象我们称为原型对象。
    • 当函数作为构造函数使用,它所创建的对象中都会有一个隐含的属性执行该原型对象。
      • 这个隐含的属性可以通过对象.__proto__来访问。
  • 原型对象就相当于一个公共的区域,凡是通过同一个构造函数创建的对象他们通常都可以访问到相同的原型对象。

  • 我们可以将对象中共有的属性和方法统一添加到原型对象中, 这样我们只需要添加一次,就可以使所有的对象都可以使用。

  • 当我们去访问对象的一个属性或调用对象的一个方法时,它会先自身中寻找,

    • 如果在自身中找到了,则直接使用。
    • 如果没有找到,则去原型对象中寻找,如果找到了则使用,
    • 如果没有找到,则去原型的原型中寻找,依此类推。
    • 直到找到Object的原型为止,Object的原型的原型为null,如果依然没有找到则返回undefined

hasOwnProperty()

  • 这个方法可以用来检查对象自身中是否含有某个属性
  • 语法:对象.hasOwnProperty("属性名")
1
2
3
4
5
6
7
8
9
10
11
12
13
function employee(name, job, born) {
this.age = 18;
this.name = name;
this.job = job;
this.born = born;
}

var bill = new employee("Bill Gates", "Engineer", 1985);

employee.prototype.salary = null;
bill.salary = 20000;

document.write(bill.salary);

垃圾回收(GC)

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

数组(Array)

  • typeof(数组名):得到的是object,数组也是一个对象,是一个用来存储数据的对象和Object类似,但是它的存储效率比普通对象要高
  • 数组中保存的内容我们称为元素
  • 数组使用索引(index)来操作元素
  • 索引指由0开始的整数
  • 数组的长度可以随时改变
  • javascript中数组的下标可以是任意对象

与java中数组的差别

  1. 类型区别
    • Java中数组是有类型的,意味着一旦类型确定,则数组中所有的数据都是同一种类型。
    • javascript中数组时没有类型的,意味着数组中的数据可以存放任意类型 (不推荐,取出转换麻烦)
  2. 长度区别
    • java中数组的长度一旦确定就不能再更改了
    • javascript中数组的长度是可以变化的(扩大缩小都可以)
    • 变长的两种办法 :
      • 指定length属性的值
      • 指定某个数组中元素的值
  3. 下标类型区别
    • java中的数组的数据引用必须用下标引用,小标必须是整数.
    • javascript中数组的数据引用可以用任意对象

创建数组

  1. 采用new的方式

  2. 采用中括号[]来定义

    1
    2
    3
    4
    5
    var arr = new Array(); //定义一个数组arr,初始长度为0
    var arr1 = new Array(4); //定义一个数组arr1,初始长度是4
    var arr2 = new Array(1, 2, 3, 4, 5); //定义一个数组arr2,初始化数据是1,2,3,4,5
    var arr3 = []; //定义了一个数组,里面是空的
    var arr3 = [3, 2, 4, 5]; //定义了一个数组,同时初始化数据
  • 默认不初始化

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    var arr = new Array(); //定义一个数组arr,初始长度为0
    var arr1 = new Array(4); //定义一个数组arr1,初始长度是4
    arr1[0] = 1;
    arr1[1] = 10;
    alert(arr1[2]); //弹出来undefined,没有初始化
    alert(arr1[100]); //相当于定义了一个变量arr1[100],没有赋值*/

    //-----------------------

    var arr3 = []; //定义了一个数组,里面是空的
    var arr3 = [3, 2, 4, 5]; //定义了一个数组,同时初始化数据

    //改变数组的的长度
    alert(arr4.length);
    //arr4.length = 100 ; //将数组的长度变为100
    //alert(arr4.length) ;

    //arr4[100] = 100 ; //将数组的长度变为101
    //alert(arr4.length) ;

    arr4.length = 2; //将数组的长度变为2,多于的数据将消失了
    //alert(arr4[2]) ; //弹不出原来的数据了,弹出来undefined

    //--数组下标的访问------------------
    var arr5 = ["中国", "美国", "日本"];
    arr5["中国"] = ["北京", "上海", "天津"];
    alert(arr5["中国"][0]); //北京

获取和修改数组的长度

  • 使用length属性来操作数组的长度

  • 获取长度: 数组.length

    • length获取到的是数组的最大索引+1
    • 对于连续的数组,length获取到的就是数组中元素的个数
  • 修改数组的长度:数组.length = 新长度

    • 如果修改后的length大于原长度,则多出的部分会空出来
    • 如果修改后的length小于原长度,则原数组中多出的元素会被删除
  • 向数组的最后添加元素 :数组[数组.length] = 值;

数组的方法

添加,删除,

functionName function
push() 用来向数组的末尾添加一个或多个元素,并返回数组新的长度
pop() 用来删除数组的最后一个元素,并返回被删除的元素
unshift() 向数组的开头添加一个或多个元素,并返回数组的新的长度
shift() 删除数组的开头的一个元素,并返回被删除的元素
reverse() 可以用来反转一个数组,它会对原数组产生影响
concat() 可以连接两个或多个数组,它不会影响原数组,而是新数组作为返回值返回
join() 把数组的所有元素放入一个字符串. 默认用逗号连接
sort() 排序 .默认同类型的数据相比较.

截取 slice(sart,[end])

 可以从一个数组中截取指定的元素
 该方法不会影响原数组,而是将截取到的内容封装为一个新的数组并返回
 参数:
    1.截取开始位置的索引(包括开始位置)
    2.截取结束位置的索引(不包括结束位置)
         第二个参数可以省略不写,如果不写则一直截取到最后
     参数可以传递一个负值,如果是负值,则从后往前数

删除指定元素splice()

 可以用来删除数组中指定元素,并使用新的元素替换
    该方法会将删除的元素封装到新数组中返回
 参数:
    1.删除开始位置的索引
    2.删除的个数
    3.三个以后,都是替换的元素,这些元素将会插入到开始位置索引的前边

join([splitor]) 拼接为字符串

1
2
3
4
可以将一个数组转换为一个字符串
参数:
需要一个字符串作为参数,这个字符串将会作为连接符来连接数组中的元素
如果不指定连接符则默认使用,

sort()

  • 可以对一个数组中的内容进行排序,默认是按照Unicode编码进行排序

  • 调用以后,会直接修改原数组

  • V8 引擎 sort 函数只给出了两种排序 InsertionSort 和 QuickSort,数量小于10的数组使用 InsertionSort,比10大的数组则使用 QuickSort。

  • 可以自己指定排序的规则,需要一个回调函数作为参数:

    • 我们可以在sort()添加一个回调函数,来指定排序规则,

    • 回调函数中需要定义两个形参,

    • 浏览器将会分别使用数组中的元素作为实参去调用回调函数

    • 使用哪个元素调用不确定,但是肯定的是在数组中a一定在b前边

    • 浏览器会根据回调函数的返回值来决定元素的顺序,

      • 如果返回一个大于0的值,则元素会交换位置
      • 如果返回一个小于0的值,则元素位置不变
      • 如果返回一个0,则认为两个元素相等,也不交换位置
    • 如果需要升序排列,则返回 a-b

    • 如果需要降序排列,则返回b-a

  • 指定排序的规则

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    function(a,b){
    //升序排列
    //return a-b;
    //降序排列
    return b-a;
    }
    var students = [
    {age: 18, name: "tom"},
    {age: 20, name: "jack"},
    {age: 19, name: "bob"}
    ]
    students.sort(
    (a, b) => {
    return (a.name < b.name) ? -1 : (a.name > b.name) ? 1 : 0
    }
    )
  • 封装成方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    // 统一封装
    const sortBy = (key) => {
    return (a, b) => {
    var result = a[key] < b[key] ? -1 : a[key] > b[key] ? 1 : 0;
    return result;
    };
    };

    students.sort(sortBy("name"));

数组遍历

  • 遍历数组就是将数组中元素都获取到

  • 一般情况我们都是使用for循环来遍历数组

1
2
3
for (var i = 0; i < 数组.length; i++) {
//数组[i]
}
  • 使用forEach()方法来遍历数组(不兼容IE8)
1
数组.forEach(function (value, index, obj) {});
  • forEach()方法需要一个回调函数作为参数,

  • 数组中有几个元素,回调函数就会被调用几次,

  • 每次调用时,都会将遍历到的信息以实参的形式传递进来,

  • 我们可以定义形参来获取这些信息。

    • value:正在遍历的元素
    • index:正在遍历元素的索引
    • obj:被遍历对象

包装类

  • JS中为我们提供了三个包装类:String() Boolean() Number()

  • 通过这三个包装类可以创建基本数据类型的对象

  • 例子:

    1
    2
    3
    var num = new Number(2);
    var str = new String("hello");
    var bool = new Boolean(true);
  • 但是在实际应用中千万不要这么干。 当我们去操作一个基本数据类型的属性和方法时,解析器会临时将其转换为对应的包装类,然后再去操作属性和方法,操作完成以后再将这个临时对象进行销毁。

Date对象

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

  • 创建对象

    1
    2
    3
    4
    // 创建一个当前的时间对象
    var d = new Date();
    // 创建一个指定的时间对象
    var d = new Date("月/日/年 时:分:秒");

方法

name
getDate() 当前日期对象是几日(1-31)
getDay() 返回当前日期对象时周几(0-6)
0 周日
1 周一
getMonth() 返回当前日期对象的月份(0-11)
0 一月 1 二月 。。。
getFullYear() 从 Date 对象以四位数字返回年份。
getHours() 返回 Date 对象的小时 (0 ~ 23)。
getMinutes() 返回 Date 对象的分钟 (0 ~ 59)。
getSeconds() 返回 Date 对象的秒数 (0 ~ 59)。
getMilliseconds() 返回 Date 对象的毫秒(0 ~ 999)。
getTime() 返回当前日期对象的时间戳
时间戳,指的是从1970年月1日 0时0分0秒,到现在时间的毫秒数
计算机底层保存时间都是以时间戳的形式保存的。
Date.now() 可以获取当前代码执行时的时间戳
  • 示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var d = new Date();
    alert(d.toLocaleString()); //转换为11
    alert(d.getYear()); //返回的是 "当前年份-1900" 的值(即年份基数是1900)
    alert(d.getFullYear()); //获取正确的4位年份
    alert(d.getMonth()); //月:0-11
    alert(d.getDate()); //天
    alert(d.getDay()); //0-6;星期天位0
    alert(d.getHours());
    0 - 23;
    alert(d.getMinutes());
    alert(d.getSeconds());

Math对象

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

方法:

方法
Math.PI 常量,圆周率
Math.abs() 绝对值运算
Math.ceil() 向上取整
Math.floor() 向下取整
Math.round() 四舍五入取整
Math.random() 生成一个0-1之间的随机数(可以等于0,永远不能取得1)
生成一个xy之间的随机数 Math.round(Math.random()*(y-x)+x);
Math.pow(x,y) 求x的y次幂
Math.sqrt() 对一个数进行开方
Math.max(x,y) 求多个数中最大值
Math.min(x,y) 求多个数中的最小值
1
2
3
4
var a = 3.1;
alert(Math.floor(a)); //3
alert(Math.ceil(a)); //4
alert(Math.round(a)); //3

String对象

属性:length查看字符串的长度

方法

方法名 描述
charAt() 根据索引获取指定的字符
charCodeAt() 根据索引获取指定的字符编码
String.fromCharCode() 根据字符编码获取字符
indexOf(str,start) indexOf()是从前向后找,返回其第一次出现的索引
如果没有找到则返回-1。
第二个参数,来表示开始查找的位置
lastIndexOf() lastIndexOf()是从后向前找
slice(start,[end]) 可以从一个字符串中截取指定位置[star,end)的内容,并将截取到内容返回,不会影响原变量。
可以省略第二个参数,如果省略则一直截取到最后
可以传负数,如果是负数则从后往前数
substr(start,nums) 和slice()基本一致,不同的是它第二个参数不是索引,而是截取的数量
substring() 和slice()基本一致,不同的是它不能接受负值作为参数,如果设置一个负值,则会自动修正为0,substring()中如果第二个参数小于第一个,自动调整位置
split() 切割字符串
toLowerCase() 将字符串转换为小写并返回
toUpperCase() 将字符串转换为大写并返回
fontcolor() 使用指定的颜色显示字符串
fontsize() 设置字符串显示大小
link(): 将字符串显示为超链接
big() 字体变大
bold() 字体变粗(一次)
1
2
3
4
5
6
7
8
9
10
var s = "abcdefg";
//alert(s.substring(2,3)) ;//c
//alert(s.substring(3,2)) ;//c

当大于长度, 按最大;
当为负数, 按最小;
位置可相反;
// alert(s.substring(300,-200)) ; //abcdefg

alert(s.substr(2, 3)); //3是i长度,不是索引 cde

ES6中的字符串新方法

  • 判断当前字符串中是否包含给定的字符串,返回布尔值。

    • String.prototype.includes(str)

      1
      2
      let str = "hello world";
      console.log(str.include("hello")); // true
    • 判断浏览器类型。

      1
      2
      3
      if (navigator.userAgent.includes("Chrome")) {
      alert("这是Chrome浏览器!");
      } else alert("这不是Chrome浏览器!");
  • 判断当前字符串是否给定字符串开头 / 结尾,返回布尔值。

    • String.prototype.startsWith(xxx) / String.prototype.endsWith()

      1
      2
      3
      let str = "hello world";
      console.log(str.startsWith("hello"));
      console.log(str.endsWith("world"));
    • 检测地址、检测上传的文件是否以xxx结尾。

  • 以指定的次数复制当前字符串,并返回一个新的字符串。

    • String.prototype.repeat(次数)

      1
      2
      let str = "mm and gg";
      console.log(str.repeat(3)); // 'mm and ggmm and ggmm and gg'
  • 填充字符串,可以输入两个参数,第一个参数是前后填充的字符总数,第二个参数是用来填充的字符串。

    • String.prototype.padStart(maxLength, fillString='')

    • String.prototype.padEnd(maxLength, fillString='')

      1
      2
      3
      4
      let str = "hello";
      console.log(str.padStrat(10, "world")); // 'worldhello'
      let pad = "mmgg";
      console.log(str.padEnd(str.length + pad.length, pad)); // 'mmgghello'

正则表达式

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

创建正则表达式

  • RegExp 对象正则表达式对象
  • 注意:使用构造函数时,由于它的参数是一个字符串,而\是字符串中转义字符,如果要使用\则需要使用\\来代替
1
2
var reg = new RegExp("正则","匹配模式");
var reg = /正则表达式/匹配模式 (匹配模式可以多个一起写:/gi)

匹配模式

  • i:忽略大小写(ignore)
  • g:全局匹配模式(默认为1次)
  • 设置匹配模式时,可以都不设置,也可以设置1个,也可以全设置,设置时没有顺序要求

正则语法

  • | 或

  • []

  • [^ ] 除了

  • [x-y] x的ascii到y的ascii码之间的值

  • [a-z] 小写字母 (也可以[e-i])

  • [A-Z] 大写字母

  • [A-z] 任意字母,但是还包括了其他ASCII在此之中的

  • [0-9] 任意数字

元符号

检查一个字符串中是否含有 ., . 表示任意字符 , 在正则表达式中使用\作为转义字符

  • \.:来表示.
  • \\:表示\
  • \w:任意字母、数字、_ [A-z0-9_]
  • \W:除了字母、数字、_ [ ^A-z0-9_]
  • \d:任意的数字 [0-9]
  • \D:除了数字 [ ^0-9]
  • \s:空格
  • \S:除了空格
  • \b:单词边界
  • \B:除了单词边界

量词

  • 通过量词可以设置一个内容出现的次数 ,量词只对它前边的一个内容起作用

  • {n} 正好出现n次

  • {m,n} 出现mn次

  • {m,} m次以上

  • +:至少一个,相当于{1,}

  • *:0个或多个,相当于{0,}

  • ? :0个或1个,相当于{0,1}

边界表达式

(不要在java中用,javaScript中用)

  • ^:正则开始
  • $:正则结束 :注意结束前一个才是结束匹配
1
2
reg = /^a/; //以a开头
reg = /b$/; //以b结尾

方法

split()

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

match()

  • 可以根据正则表达式,从一个字符串中将符合条件的内容提取出来

  • 默认情况下我们的match只会找到第一个符合要求的内容,找到以后就停止检索

    • 我们可以设置正则表达式为全局匹配模式,这样就会匹配到所有的内容
  • 可以为一个正则表达式设置多个匹配模式,且顺序无所谓

  • 非全局查找时:返回一个集合:[匹配子项,index,input,groups]

1
2
3
4
let str = "曹操草草的收拾了屋子,去操场约会去咯";
let result = "结果他被放鸽子了";
let reg = /[草|操]/;
str.match(reg); // ["操", index: 1, input: "曹操草草的收拾了屋子,去操场约会去咯", groups: undefined]
  • 全局查找‘g’时:返回所有匹配的子项,会将匹配到的内容封装到一个数组Array 中返回

    1
    2
    3
    4
    5
    let str = "曹操草草的收拾了屋子,去操场约会去咯";
    let result = "结果他被放鸽子了";
    let reg = /[草|操]/g;
    str.match(reg); // ["操", "草", "草", "操"]
    result.match(reg); // null

replace()

  • 可以将字符串中指定内容替换为新的内容

  • 默认只会替换第一个

  • 参数:

    • 被替换的内容,可以接受一个正则表达式作为参数
    • 新的内容,空串则为删除””
    1
    2
    3
    4
    5
    let str = "曹操草草的收拾了屋子,去操场约会去咯";
    let result = "结果他被放鸽子了";
    let reg = /[草|操]/g;
    str.replace(reg, "*"); // "曹***的收拾了屋子,去*场约会去咯"
    result.replace(reg, "*"); // "结果他被放鸽子了"
  • 可以搜索字符串中是否含有指定内容
  • 如果搜索到指定内容,则会返回第一次出现的索引,如果没有搜索到返回1
  • 它可以接受一个正则表达式作为参数,然后会根据正则表达式去检索字符串
  • serach()只会查找第一个,即使设置全局匹配也没用
1
2
3
4
5
let str = "曹操草草的收拾了屋子,去操场约会去咯";
let result = "结果他被放鸽子了";
let reg = /[草|操]/g;
str.search(reg); // 1(曹操的操字,index:1)
result.search(reg); // -1(没有找到操或者草字,index:-1)

test()

  • 可以用来检查一个字符串是否符合正则表达式
  • 如果符合返回true,否则返回false
  • 例子:去掉两端的空格:
1
2
3
4
5
let str = "曹操草草的收拾了屋子,去操场约会去咯";
let result = "结果他被放鸽子了";
let reg = /[草|操]/g;
reg.test(str); // true
reg.test(result); // flase

exec方法

  • 全局匹配时 reg.exec(str) 会依次匹配子项,直到匹配完成

    1
    2
    3
    4
    5
    6
    7
    8
    let str = "曹操草草的收拾了屋子,去操场约会去咯";
    let result = "结果他被放鸽子了";
    let reg = /[草|操]/g; // 全局匹配
    console.log(reg.exec(str)); // ["操", index: 1, input: "曹操草草的收拾了屋子,去操场约会去咯", groups: undefined]
    console.log(reg.exec(str)); // ["草", index: 2, input: "曹操草草的收拾了屋子,去操场约会去咯", groups: undefined]
    console.log(reg.exec(str)); // ["草", index: 3, input: "曹操草草的收拾了屋子,去操场约会去咯", groups: undefined]
    console.log(reg.exec(str)); // ["操", index: 12, input: "曹操草草的收拾了屋子,去操场约会去咯", groups: undefined]
    console.log(reg.exec(str)); // null
  • 非全局匹配:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    let str = "曹操草草的收拾了屋子,去操场约会去咯"
    let result = "结果他被放鸽子了"
    let reg = /[草|操]/ // 非全局匹配
    console.log(reg.exec(str)) // ["操", index: 1, input: "曹操草草的收拾了屋子,去操场约会去咯", groups: undefined]
    console.log(reg.exec(str)) // ["操", index: 1, input: "曹操草草的收拾了屋子,去操场约会去咯", groups: undefined]
    console.log(reg.exec(str)) // ["操", index: 1, input: "曹操草草的收拾了屋子,去操场约会去咯", groups: undefined]
    console.log(reg.exec(str)) // ["操", index: 1, input: "曹操草草的收拾了屋子,去操场约会去咯", groups: undefined]

    } // -作用域-

常用的正则验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 是否带有小数
function isDecimal(strValue) {
var objRegExp = /^\d+\.\d+$/;
return objRegExp.test(strValue);
}

// 校验是否中文名称组成
function ischina(str) {
var reg = /^[\u4E00-\u9FA5]{2,4}$/; // 定义验证表达式
return reg.test(str); // 进行验证
}

// 校验是否全由8位数字组成
function isStudentNo(str) {
var reg = /^[0-9]{8}$/;
return reg.test(str);
}

// 校验电话码格式
function isTelCode(str) {
var reg = /^((0\d{2,3}-\d{7,8})|(1[3584]\d{9}))$/;
return reg.test(str);
}

// 校验邮件地址是否合法
function IsEmail(str) {
var reg = /^\w+@[a-zA-Z0-9]{2,10}(?:\.[a-z]{2,4}){1,3}$/;
return reg.test(str);
}

DOM

  • 文档对象模型(Document Object Model),通过DOM可以来任意来修改网页中各个内容
说明
文档 文档指的是网页,一个网页就是一个文档
对象 对象指将网页中的每一个节点都转换为对象,转换完对象以后,就可以以一种纯面向对象的形式来操作网页了
模型 模型用来表示节点和节点之间的关系,方便操作页面
节点(Node) 节点是构成网页的最基本的单元,网页中的每一个部分都可以称为是一个节点,虽然都是节点,但是节点的类型却是不同的

常用的节点

  • 文档节点 (Document),代表整个网页
  • 元素节点(Element),代表网页中的标签
  • 属性节点(Attribute),代表标签中的属性
  • 文本节点(Text),代表网页中的文本内容

document查询

  • 在网页中浏览器已经为我们提供了document对象

  • 它代表的是整个网页,它是window对象的属性,可以在页面中直接使用

  • 根据元素的id属性查询一个元素节点对象:

    • document.getElementById("id属性值");
  • 根据元素的name属性值查询一组元素节点对象:

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

    • document.getElementsByTagName("标签名");

元素节点来查询

  • 通过标签名查询当前元素的指定后代元素

  • 元素.getElementsByTagName()

  • 元素.childNodes

    • 获取当前元素的所有子节点
    • 子节点包括便签元素中的文本,子元素自包含标签元素
  • childNodes属性会获取包括文本节点在内的所有节点

    • DOM标签标签间空白也会当成文本节点
    • 注意:在IE8及以下的浏览器中,不会将空白文本当成子节点
  • 元素.children

  • 获取当前元素的所有子元素

  • 元素.firstChild

  • 获取当前元素的第一个子节点,会获取到空白的文本子节点

  • 元素.lastChild

  • 获取当前元素的最后一个子节点

  • 元素.parentNode

  • 获取当前元素的父元素

  • 元素.previousSibling

  • 获取当前元素的前一个兄弟节点

  • previousElementSibling

    • 获取前一个兄弟元素,IE8及以下不支持
  • 元素.nextSibling

  • 获取当前元素的后一个兄弟节点

  • firstElementChild

    • 获取当前元素的第一个子元素
  • firstElementChild不支持IE8及以下的浏览器,

  • innerHTML和innerText

    • 这两个属性并没有在DOM标准定义,但是大部分浏览器都支持这两个属性
    • 两个属性作用类似,都可以获取到标签内部的内容,
    • 不同是innerHTML会获取到html标签,而innerText会自动去除标签
  • innerHTML必须是有开始标签和结束标签的标签对象才能使用

    • 如果使用这两个属性来设置标签内部的内容时,没有任何区别的
  • 读取标签内部的文本内容

    1
    2
    </h1>h1中的文本内容</h1>
    元素.firstChild.nodeValue

读取元素的属性

  • 语法:元素.属性名

  • 例子:

    1
    2
    3
    4
    5
    ele.name;
    ele.id;
    ele.value;
    //注意:读取class属性时需要使用
    元素.className;

修改元素的属性

  • 语法:元素.属性名 = 属性值

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

DOM的加载顺序

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

  • 解决方式一: 可以将js代码编写到body的下边

    1
    2
    3
    4
    5
    6
    7
    <body>
    <button id="btn">按钮</button>

    <script>
    var btn = document.getElementById("btn"); btn.onclick = function(){};
    </script>
    </body>
  • 解决方式二:将js代码编写到window.onload = function(){}

  • window.onload 对应的回调函数会在整个页面加载完毕以后才执行

  • 所以可以确保代码执行时,DOM对象已经加载完毕了

    1
    2
    3
    4
    5
    6
    7
    <script>
    window.onload = function(){
    var btn = document.getElementById("btn");
    btn.onclick = function(){
    };
    };
    </script>

document对象的属性和方法

  • document.all

    获取页面中的所有元素,相当于document.getElementsByTagName(“*“);

  • document.documentElement

  • 获取页面中html根元素

  • document.body

  • 获取页面中的body元素

  • document.getElementsByClassName()

    • 根据元素的class属性值查询一组元素节点对象
  • 这个方法不支持IE8及以下的浏览器

  • document.querySelector()

    • 根据CSS选择器去页面中查询一个元素
  • 如果匹配到的元素有多个,则它会返回查询到的第一个元素

  • document.querySelectorAll()

    • 根据CSS选择器去页面中查询一组元素
    • 会将匹配到所有元素封装到一个数组中返回,即使只匹配到一个

DOM修改

  • document.createElement("TagName") - 可以用于创建一个元素节点对象,
    • 它需要一个标签名作为参数,将会根据该标签名创建元素节点对象,
    • 并将创建好的对象作为返回值返回
  • document.createTextNode("textContent")
    • 可以根据文本内容创建一个文本节点对象
  • 父节点.appendChild(子节点)
    • 向父节点中添加指定的子节点
  • 父节点.insertBefore(新节点,旧节点)
    • 将一个新的节点插入到旧节点的前边
  • 父节点.replaceChild(新节点,旧节点)
    • 使用一个新的节点去替换旧节点
  • 父节点.removeChild(子节点)
    • 删除指定的子节点
    • 推荐方式:子节点.parentNode.removeChild(子节点)

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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);
});

DOM对CSS的操作

读取和修改内联样式

  • 使用style属性来操作元素的内联样式

  • 读取内联样式: 元素.style.样式名

    • 元素.style.width
    • 元素.style.height
  • 注意:如果样式名中带有-,则需要将样式名修改为驼峰命名法将-去掉,然后后的字母改大写

    • background-color > backgroundColor
    • border-width > borderWidth
  • 修改内联样式:

  • 语法:元素.style.样式名 = 样式值

  • 通过style修改和读取的样式都是内联样式,由于内联样式的优先级比较高,

  • 所以我们通过JS来修改的样式,往往会立即生效,

  • 但是如果样式中设置了!important,则内联样式将不会生效。

读取元素的当前样式

  • 正常浏览器 使用getComputedStyle()

    • 这个方法是window对象的方法,可以返回一个对象
    • 这个对象中保存着当前元素生效样式 通过该方法读取到样式都是只读的不能修改
  • 参数:

    1. 要获取样式的元素

    2. 可以传递一个伪元素,一般传null

      1
      2
      //获取元素的宽度
      getComputedStyle(box, null)["width"];
  • IE8 :使用currentStyle,通过这个属性读取到的样式是只读的不能修改

  • 语法:元素.currentStyle.样式名

    1
    box.currentStyle["width"];
  • 实现兼容性

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    /*
    * 定义一个函数,用来获取指定元素的当前的样式
    * 参数:
    * 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];
    }

其他的样式相关的属性

  • 注意:以下样式都是只读的,未指明偏移量都是相对于当前窗口左上角
属性 说明
clientHeight 元素的可见高度,包括元素的内容区和内边距的高度
clientWidth 元素的可见宽度,包括元素的内容区和内边距的宽度
offsetHeight 整个元素的高度,包括内容区、内边距、边框
offfsetWidth 整个元素的宽度,包括内容区、内边距、边框
offsetParent 当前元素的定位父元素,离他最近的开启了定位的祖先元素,如果所有的元素都没有开启定位,则返回body, 当前元素和定位父元素之间的偏移量
offsetLeft offsetLeft水平偏移量
offsetTop offsetTop垂直偏移量
scrollHeight 获取元素滚动区域的高度
scrollWidth 获取元素滚动区域的宽度
scrollTop 获取元素垂直滚动条滚动的距离
scrollLeft 获取元素水平滚动条滚动的距离
  • 判断滚动条是否滚动到底

    • 垂直滚动条
      scrollHeight -scrollTop = clientHeight
  • 水平滚动

    • scrollWidth -scrollLeft = clientWidth

案例

标题栏的滚动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<body onload="init()">
<script type="text/javascript">

//示例:标题栏的滚动
function init() {
//1.拿到标题栏的文本
var title = document.title;
//alert(title) ;
//2.将文本字串转换为数组
var arr = title.split("");
//3.拿到数组的第一个元素,并从数组中删除
var first = arr.shift();
//4.将第一个元素添加到数组的最后
arr.push(first);
//5.将数组再组合成一个字符串
title = arr.join("");
//6.将字符串再赋值回标题栏
document.title = title;
//7.每隔1秒做一遍前6步
setTimeout("init()", 1000);
}
</script>
</body>

字体变变变

1
2
3
4
5
6
7
8
9
10
11
function fun(){
//1.拿到p标签对象
var p = document.getElementById("p") ;
//2.拿到p标签对象的主体内容
var txt = p.innerHTML ; //innerHTML必须是有开始标签和结束标签的标签对象才能使用
//3.改变字体内容,再赋值回去
p.innerHTML = txt.big().big() ;
}

<p id = "p">大</p>
<input type="button" value="变变变" onclick="fun()">

字体颜色随机变换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var arr = ["red","blue","green","yellow","#666666"] ;
function fun1(){
//1.拿到p标签对象
var p = document.getElementById("p") ;
//2.随机取得一个整数作为数组的下标
var index = Math.floor(Math.random()*arr.length) ;
//3. 拿到p标签对象的主体内容
// var txt = p.innerHTML ;
var txt = p.innerText ;
//3.给p标签对象的主体内容改变颜色,并赋值回去
p.innerHTML = txt.fontcolor(arr[index]) ;
// alert(p.innerHTML) ;

setTimeout("fun1()",500) ;
}

<p id = "p">大</p>
<input type="button" value="变变变1" onclick="fun1()">

js修改CSS样式

  • 对象.style,css样式有- 的,需要将-去掉,大写后面的第一个

    1
    2
    3
    4
    5
    6
    7
    8
    9
    function fun() {
    //拿到p标签对象
    var p = document.getElementById("p");
    //定义p的样式
    //p.style.color = "red" ;
    //p.style.border = "5px dashed green" ;

    p.style.backgroundColor = "red";
    }
  • 写一个css,类选择器(推荐)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <style type="text/css">
    .one{
    color:red ;
    border:6px solid green ;
    cursor:hand;
    }
    </style>

    //拿到p标签对象
    var p = document.getElementById("p") ;
    p.className = "one" ;//对象会应用选择器的样式
    p.className = "" / "none"; //取消样式

定义方法修改元素的css

  • 通过style属性来修改元素的样式,每修改一个样式,浏览器就需要重新渲染一次页面。 这样的执行的性能是比较差的,而且这种形式当我们要修改多个样式时,也不太方便 我希望一行代码,可以同时修改多个样式

  • 我们可以通过修改元素的class属性来间接的修改样式.这样一来,我们只需要修改一次,即可同时修改多个样式,浏览器只需要重新渲染页面一次,性能比较好,并且这种方式,可以使表现和行为进一步的分离

1
box.className += " b2"; //注意有空格,添加class属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
//定义一个函数,用来向一个元素中添加指定的class属性值
/*
* 参数:
* obj 要添加class属性的元素
* cn 要添加的class值
*
*/
function addClass(obj, cn) {
if (!hasClass(obj, cn)) {
obj.className += " " + cn;
}
}
/*
* 判断一个元素中是否含有指定的class属性值
* 如果有该class,则返回true,没有则返回false
*
*/
function hasClass(obj, cn) {
var reg = new RegExp("\\b" + cn + "\\b");
return reg.test(obj.className);
}
/*
* 删除一个元素中的指定的class属性
*/
function removeClass(obj, cn) {
//创建一个正则表达式
var reg = new RegExp("\\b" + cn + "\\b");
//删除class
obj.className = obj.className.replace(reg, "");
}
/*
* toggleClass可以用来切换一个类
* 如果元素中具有该类,则删除
* 如果元素中没有该类,则添加
*/
function toggleClass(obj, cn) {
//判断obj中是否含有cn
if (hasClass(obj, cn)) {
//有,则删除
removeClass(obj, cn);
} else {
//没有,则添加
addClass(obj, cn);
}
}

省市联动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<script>
var arr = ["中国", "美国", "日本"];

arr["中国"] = ["北京", "上海", "钓鱼岛"];
arr["美国"] = ["纽约", "华盛顿", "旧金山"];
arr["日本"] = ["东京", "大阪", "神户"];

arr["北京"] = ["海淀", "朝阳", "昌平", "丰台"];
arr["上海"] = ["浦东", "金山", "崇明", "浦西"];
arr["钓鱼岛"] = ["钓鱼岛东", "钓鱼岛南", "钓鱼岛西", "钓鱼岛北"];

arr["纽约"] = ["纽约1", "纽约2", "纽约3", "纽约4"];
arr["华盛顿"] = ["华盛顿1", "华盛顿2", "华盛顿3", "华盛顿4"];
arr["旧金山"] = ["旧金山1", "旧金山2", "旧金山3", "旧金山4"];

arr["东京"] = ["东京1", "东京2", "东京3", "东京4"];
arr["大阪"] = ["大阪1", "大阪2", "大阪3", "大阪4"];
arr["神户"] = ["神户1", "神户2", "神户3", "神户4"];

function init() {
//填充国家
fillData(arr, "country");

//填充省市
fillData(arr[arr[0]], "province");
//填充地区
fillData(arr[arr[arr[0]][0]], "area");
}

function fillData(arr, id) {
//清空select选项
document.getElementById(id).options.length = 0;
//添加选项
for(var i = 0; i < arr.length; i++) {
//创建一个option对象
//第一种
/* var option = new Option() ;
option.text = arr[i] ;
option.value = arr[i] ;*/

//第二种
var option = new Option(arr[i], arr[i]);

//将option对象添加到select中
document.getElementById(id).options.add(option);
}
}

function changePro(coun) {

//添加省市
fillData(arr[coun], "province");

//添加地区
fillData(arr[arr[coun][0]], "area");
}

function changeArea(pro) {
//改变地区
fillData(arr[pro], "area");

}
</script>

<body onload="init()">
国家:
<select id="country" onchange="changePro(this.value)"></select>
省市:
<select id="province" onchange="changeArea(this.value)"></select>
地区:
<select id="area"></select>
</body>

事件(Event)

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

绑定事件

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

    1
    <button onclick="js代码。。。">按钮</button>
  2. 可以通过为对象的指定事件属性设置回调函数的形式来处理事件

    1
    2
    3
    4
    5
    6
    7
    <button id="btn">按钮</button>
    <script>
    var btn = document.getElementById("btn");
    btn.onclick = function(){

    };
    </script>

事件对象

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

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

  • 例子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    元素.事件 = function (event) {
    // var e=event?event||window.event;
    // 实现浏览器兼容
    event = event || window.event;
    };

    元素.事件 = function (e) {
    e = e || event;
    };
  • Event 对象代表事件的状态,比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态。

  • 鼠标移动事件

    • onmousemove(event) : 鼠标移动事件 event是事件对象。名字固定
    • onmouseover : 鼠标悬停事件
    • onmouseout : 鼠标移出事件
  • 鼠标点击事件

    • onclick
  • img, 和widows加载与卸载事件

    • onload ,onunload
  • 聚焦与离焦事件

    • onfocus, onblur

    • focus():获得焦点

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      function fun(obj) {
      obj.style.border = "1px solid red ";
      obj.style.backgroundColor = "#ff66ff";
      obj.style.color = "green";
      }

      function fun1(obj) {
      if (obj.value == "") {
      alert("内容不得为空");
      //obj.focus() ; //获得焦点
      }
      }
      <input type="text" name="" onfocus = "fun(this)" onblur = "fun1(this)" />
  • 键盘事件

    • onkeypress,onkeyup,onkeydown

      1
      2
      3
      4
      5
      6
      7
      function fun(obj,e){
      //拿到按键的asc码
      obj.value = e.keyCode ;
      }


      <input type="text" name="" onkeypress = "fun(this,event)">
  • 提交与重置事件

    • 位置:form表单的<form>标签内,必须要return语句

      • onsubmit,onreset
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      function check(form){
      //拿到文本框中的内容
      var txt = form.username.value ;
      //判断内容
      if(txt == ""){
      document.getElementById("sname").innerHTML = " <font color = red>* 姓名必须填写</font>" ;
      form.username.focus() ;
      return false;
      }

      return true ;
      }

      function fun(form){
      alert("重置事件") ;
      return true ;
      }

      <form method="post" action="01-鼠标的单击事件.html" onsubmit = "return check(this)" onreset = "return fun(this)">
      姓名:<input type="text" name="username"><span id = "sname"></span><br>
      <input type="submit" value = "提交">
      <input type="reset" value = "重置">
      </form>
  • 选择与改变事件

    • onselect = "fun(this)"

    • onchange = "fun1(this.value)"

    • 文本框: 内容发生改变,失去焦点

    • 下拉框: 下标发生改变

    • onchange = "fun2(this.value,this.selectedIndex)"

      • 多行文本框
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    function fun(obj){
    alert(obj.value) ;
    }

    function fun1(v){
    alert(v) ;
    }

    function fun2(v,index){
    alert(v + ":" + index) ;
    }

    <input type="text" name="" onselect = "fun(this)" onchange = "fun1(this.value)" >
    <select onchange = "fun2(this.value,this.selectedIndex)">
    <option value = "china">中国</option>
    <option value = "america"> 美国</option>
    <option value = "japan">日本</option>
    </select>

事件的冒泡(Bubble)

  • 事件的冒泡指的是事件向上传导,当后代元素上的事件被触发时,将会导致其祖先元素上的同类事件也会触发。

  • 事件的冒泡大部分情况下都是有益的,如果需要取消冒泡,则需要使用事件对象来取消

  • 可以将事件对象的cancelBubble设置为true,即可取消冒泡

  • 例子:

    1
    2
    3
    4
    元素.事件 = function (event) {
    event = event || window.event;
    event.cancelBubble = true;
    };

事件的委派

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

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

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

  • target : event中的target表示的触发事件的对象 ,使用它对触发事件的元素进行判断

  • 示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    <head>
    <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");
    //为ul绑定一个单击响应函数
    u1.onclick = function (event) {
    event = event || window.event;
    //如果触发事件的对象是我们期望的元素,则执行否则不执行
    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>

事件的绑定

  • addEventListener(): 通过这个方法也可以为元素绑定响应函数

  • 参数:

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

  • 这样当事件被触发时,响应函数将会按照函数的绑定顺序执行

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    btn01.addEventListener(
    "click",
    function () {
    alert(1);
    },
    false,
    );

    btn01.addEventListener(
    "click",
    function () {
    alert(2);
    },
    false,
    );
  • attachEvent() 在IE8中可以使用attachEvent()来绑定事件 ,这个方法也可以同时为一个事件绑定多个处理函数, 不同的是它是后绑定先执行,执行顺序和addEventListener()相反

  • 参数:

    1. 事件的字符串,要on
    2. 回调函数
    1
    2
    3
    4
    5
    6
    7
    btn01.attachEvent("onclick", function () {
    alert(1);
    });

    btn01.attachEvent("onclick", function () {
    alert(2);
    });
  • 兼容性:定义一个函数,用来为指定元素绑定响应函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    /*
    * 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);
    });
    }
    }

事件的传播

  • 关于事件的传播网景公司和微软公司有不同的理解

  • 微软公司认为事件应该是由内向外传播,也就是当事件触发时,应该先触发当前元素上的事件,然后再向当前元素的祖先元素上传播,也就说事件应该在冒泡阶段执行。

  • 网景公司认为事件应该是由外向内传播的,也就是当前事件触发时,应该先触发当前元素的最外层的祖先元素的事件, 然后在向内传播给后代元素 , W3C综合了两个公司的方案,将事件传播分成了三个阶段

  • 捕获阶段

    • 在捕获阶段时从最外层的祖先元素,向目标元素进行事件的捕获,但是默认此时不会触发事件
  • 目标阶段

    • 事件捕获到目标元素,捕获结束开始在目标元素上触发事件
  • 冒泡阶段

    • 事件从目标元素向他的祖先元素传递,依次触发祖先元素上的事件
  • 如果希望在捕获阶段就触发事件,可以将addEventListener()的第三个参数设置为true

    • 一般情况下我们不会希望在捕获阶段触发事件,所以这个参数一般都是false
  • IE8及以下的浏览器中没有捕获阶段

事件句柄 (Event Handlers)

属性 此事件发生在何时…
onabort 图像的加载被中断。
onblur 元素失去焦点。
onchange 域的内容被改变。
onclick 当用户点击某个对象时调用的事件句柄。
ondblclick 当用户双击某个对象时调用的事件句柄。
onerror 在加载文档或图像时发生错误。
onfocus 元素获得焦点。
onkeydown 某个键盘按键被按下。
onkeypress 某个键盘按键被按下并松开。
onkeyup 某个键盘按键被松开。
onload 一张页面或一幅图像完成加载。
onmousedown 鼠标按钮被按下。
onmousemove 鼠标被移动。
onmouseout 鼠标从某元素移开。
onmouseover 鼠标移到某元素之上。
onmouseup 鼠标按键被松开。
onreset 重置按钮被点击。
onresize 窗口或框架被重新调整大小。
onselect 文本被选中。
onsubmit 确认按钮被点击。
onunload 用户退出页面。

鼠标 / 键盘属性

属性 描述
altKey 返回当事件被触发时,”ALT” 是否被按下。
button 返回当事件被触发时,哪个鼠标按钮被点击。
clientX 返回当事件被触发时,鼠标指针的水平坐标。
clientY 返回当事件被触发时,鼠标指针的垂直坐标。
ctrlKey 返回当事件被触发时,”CTRL” 键是否被按下。
metaKey 返回当事件被触发时,”meta” 键是否被按下。
relatedTarget 返回与事件的目标节点相关的节点。
screenX 返回当个某事件被触发时,鼠标指针的水平坐标。
screenY 返回当个某事件被触发时,鼠标指针的垂直坐标。
shiftKey 返回当事件被触发时,”Shift” 键是否被按下。

拖拽事件

  • 鼠标事件 :获取到鼠标的坐标

    • clientXclientY
      • 用于获取鼠标在当前的可见窗口的坐标
      • div的偏移量,是相对于整个页面的
  • pageXpageY 可以获取鼠标相对于当前页面的坐标

    • 但是这个两个属性在IE8中不支持,所以如果需要兼容IE8,则不要使用
    • var left = event.clientX;
    • var top = event.clientY;
  • 页面定义

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <head>
    <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>
    </head>
    <body>
    <div id="box1"></div>
    <div id="box2"></div>
    </body>
  • 监听拖拽

    1. 当鼠标在被拖拽元素上按下时,开始拖拽 onmousedown
    2. 当鼠标移动时被拖拽元素跟随鼠标移动 onmousemove
    3. 当鼠标松开时,被拖拽元素固定在当前位置 onmouseup
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
<head>
<script type="text/javascript">
window.onload = function(){
//获取box1
var box1 = document.getElementById("box1");
var box2 = document.getElementById("box2");

//开启box1的拖拽
drag(box1);
//开启box2的
drag(box2);
};

/*
* 提取一个专门用来设置拖拽的函数
* 参数:开启拖拽的元素
*/
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>

滚轮事件

  • onwheel事件都支持

  • 定义元素

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <head>
    <style>
    #box1 {
    width: 100px;
    height: 100px;
    background-color: red;
    }
    </style>
    </head>

    <body style="height: 2000px;">
    <div id="box1"></div>
    </body>
  • 元素监听滚动事件

    • onmousewheel鼠标滚轮滚动的事件,会在滚轮滚动时触发,
      • 但是火狐不支持该属性
      • 在火狐中需要使用addEventListener()函数来绑定 DOMMouseScroll 来绑定滚动事件
    • event.wheelDelta 可以获取鼠标滚轮滚动的方向
      • wheelDelta这个值我们不看大小,只看正负 ,向上滚 120 向下滚 -120
      • wheelDelta这个属性火狐中不支持
      • Firefox 使用detail,其余四类使用wheelDelta;
    • detail,wheelDelta` 两者只在取值上不一致,代表含义一致,detail与wheelDelta只各取两个 值,detail只取±3,wheelDelta只取±120,其中正数表示为向上,负数表示向下。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    <head>
    <script type="text/javascript">
    window.onload = function(){
    //获取id为box1的div
    var box1 = document.getElementById("box1");

    box1.onmousewheel = function(event){
    event = event || window.event;
    /*
    * 当鼠标滚轮向下滚动时,box1变长
    * 当滚轮向上滚动时,box1变短
    */
    //判断鼠标滚轮滚动的方向
    if(event.wheelDelta > 0 || event.detail > 0){
    //向上滚,box1变短
    box1.style.height = box1.clientHeight - 10 + "px";
    }else{
    //向下滚,box1变长
    box1.style.height = box1.clientHeight + 10 + "px";
    }

    /*
    * 使用addEventListener()方法绑定响应函数,取消默认行为时不能使用return false
    * 需要使用event来取消默认行为event.preventDefault();
    * 但是IE8不支持event.preventDefault();这个玩意,如果直接调用会报错
    */
    event.preventDefault && event.preventDefault();


    /*
    * 当滚轮滚动时,如果浏览器有滚动条,滚动条会随之滚动,
    * 这是浏览器的默认行为,如果不希望发生,则可以取消默认行为
    */
    return false;
    };

    //为火狐绑定滚轮事件
    bind(box1,"DOMMouseScroll",box1.onmousewheel);
    };

    </script>
    </head>
  • 火狐绑定滚轮事件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    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);
    });
    }
    }

键盘事件

  • onkeydown :按键被按下
    • 对于onkeydown来说如果一直按着某个按键不松手,则事件会一直触发
    • 当onkeydown连续触发时,第一次和第二次之间会间隔稍微长一点,其他的会非常的快,这种设计是为了防止误操作的发生。
  • onkeyup 按键被松开 ,键盘事件一般都会绑定给一些可以获取到焦点的对象或者是document
    • keyCode :可以通过keyCode来获取按键的编码 通过它可以判断哪个按键被按下 。
    • 除了keyCode,事件对象中还提供了几个属性
  • altKey
    • ctrlKey
    • shiftKey
    • 这个三个用来判断alt ctrl 和 shift是否被按下
  • 如果按下则返回true,否则返回false
1
2
3
4
5
6
7
//console.log(event.keyCode);

//判断一个y是否被按下
//判断y和ctrl是否同时被按下
if (event.keyCode === 89 && event.ctrlKey) {
console.log("ctrl和y都被按下了");
}
1
2
3
4
5
6
7
8
9
10
input.onkeydown = function (event) {
event = event || window.event;
//数字 48 - 57
//使文本框中不能输入数字
if (event.keyCode >= 48 && event.keyCode <= 57) {
//在文本框中输入内容,属于onkeydown的默认行为
//如果在onkeydown中取消了默认行为,则输入的内容,不会出现在文本框中
return false;
}
};

BOM

  • 浏览器对象模型(browser object model)
  • BOM可以使我们通过JS来操作浏览器
  • 在BOM中为我们提供了一组对象,用来完成对浏览器的操作

BOM对象

  • 这些BOM对象在浏览器中都是作为window对象的属性保存的,可以通过window对象来使用,也可以直接使用

  • Window

    • 代表的是整个浏览器的窗口,同时window也是网页中的全局对象
  • Navigator

    • 代表的当前浏览器的信息,通过该对象可以来识别不同的浏览器
  • Location

    • 代表当前浏览器的地址栏信息,通过Location可以获取地址栏信息,或者操作浏览器跳转页面
  • History

    • 代表浏览器的历史记录,可以通过该对象来操作浏览器的历史记录
    • 由于隐私原因,该对象不能获取到具体的历史记录,只能操作浏览器向前或向后翻页
    • 而且该操作只在当次访问时有效
  • Screen

    • 代表用户的屏幕的信息,通过该对象可以获取到用户的显示器的相关的信息
  • 代表的当前浏览器的信息,通过该对象可以来识别不同的浏览器

  • 由于历史原因,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了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
alert(navigator.appName);  --Netscape

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,枪毙了你~~~");
}

History

  • 对象可以用来操作浏览器向前或向后翻页

  • length 属性,可以获取到当成访问的链接数量

  • back() 可以用来回退到上一个页面,作用和浏览器的回退按钮一样

  • forward() 可以跳转下一个页面,作用和浏览器的前进按钮一样

  • go() 可以用来跳转到指定的页面 ,它需要一个整数作为参数

    • 1:表示向前跳转一个页面 相当于forward()
    • 2:表示向前跳转两个页面
    • -1:表示向后跳转一个页面
    • -2:表示向后跳转两个页面

Location

  • 该对象中封装了浏览器的地址栏的信息

  • 如果直接打印location:alert(location); ,则可以获取到地址栏的信息(当前页面的完整路径)

  • 如果直接将location属性修改为一个完整的路径,或相对路径 ,则我们页面会自动跳转到该路径,并且会生成相应的历史记录

    • location="http://www.baidu.com"
    • location = "01.BOM.html"
  • assign() 用来跳转到其他的页面,作用和直接修改location一样

  • reload() 用于重新加载当前页面,作用和刷新按钮一样

  • 如果在方法中传递一个true:location.reload(true),作为参数,则会强制清空缓存刷新页面

  • replace() 可以使用一个新的页面替换当前页面,调用完毕也会跳转页面

    • 不会生成历史记录,不能使用回退按钮回退

window

  • 表示浏览器窗口
  • 直接定义全局的函数都是window的函数
  • window对象的函数或对象可以省略window关键字
  • 属性
    1. document:获取文档对象
    2. innerheight:获取显示区高度
    3. innerwidth:获取显示区的宽度

方法

  1. open(url,窗口名字,弹出窗口的特征(位置,大小等)):打开窗口,返回一个window对象.
  2. close():关闭窗口
  3. alert():警告框
  4. confirm():确认框,返回boolean
  5. prompt: 输入框
  6. setTimeout(function,delaytime): 延时一段时间后,执行函数只执行一次,返回number类型
  7. clearTimeout(id);清楚timeout
  8. setInterval(function,delaytime):周期性执行,返回类型
  9. clearInterval(intervalId);清除interval
  • 示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    console.log(window.innerHeight);
    console.log(window.innerWidth);

    //打开新窗口
    var newWindow = window.open(
    "http://www.baidu.com",
    "baidu",
    "width=200px,height=200px,left=200px,top=200px",
    );
    //关闭窗口
    newWindow.close();

    var bool = confirm("确认删除吗?");
    console.log(bool);

    var name = prompt("请输入您的姓名", "张三");
    console.log(name);

    //只执行一次
    var timeoutId = setTimeout(function () {
    console.log("boom");
    }, 2000);
    //取消timeout
    clearTimeout(timeoutId);

    var i = 10;
    var id = setInterval(function () {
    i--;
    console.log(i);
    }, 1000);

    clearInterval(id);

定时器

  • 定时调用 :setInterval() ,可以将一个函数,每隔一段时间执行一次

  • 参数:

    • 回调函数,该函数会每隔一段时间被调用一次
    • 每次调用间隔的时间,单位是毫秒
  • 返回值:

    • 返回一个Number类型的数据
    • 这个数字用来作为定时器的唯一标识
  • clearInterval()可以用来关闭一个定时器

    • 方法中需要一个定时器的标识作为参数,这样将关闭标识对应的定时器
  • clearInterval()可以接收任意参数,

    • 如果参数是一个有效的定时器的标识,则停止对应的定时器
    • 如果参数不是一个有效的标识,则什么也不做
1
2
3
4
5
6
7
8
var num = 1;
var timer = setInterval(function () {
count.innerHTML = num++;
if (num == 11) {
//关闭定时器
clearInterval(timer);
}
}, 1000);

延时调用

  • setTimeout

  • 延时调用一个函数不马上执行,而是隔一段时间以后在执行,而且只会执行一次

  • 延时调用和定时调用的区别,定时调用会执行多次,而延时调用只会执行一次

  • 延时调用和定时调用实际上是可以互相代替的,在开发中可以根据自己需要去选择

    1
    2
    3
    4
    //应用:10秒倒计时广告
    var timer = setTimeout(function () {
    console.log("10秒倒计时广告结束");
    }, 3000);
  • 使用clearTimeout()来关闭一个延时调用:clearTimeout(timer);

JSON

  • JavaScript Object Notation JS对象表示法,JS中的对象只有JS自己认识,其他的语言都不认识。

    • 键值对,用:冒号连接, 用逗号,分隔多个属性

    • 属性值key可以不使用引号

      1
      2
      3
      4
      5
      6
      7
      8
      <script>
      var jsonObj = {name:'zs' ,age:12};
      var person=[{name:'zs' ,age:12}];
      console.log(jsonObj);
      console.log(jsonObj.name);
      console.log(jsonObj.age);
      console.log(person[0].age);
      </script>
  • JSON就是一个特殊格式的字符串,这个字符串可以被任意的语言所识别,并且可以转换为任意语言中的对象,JSON在开发中主要用来数据的交互JSON和JS对象的格式一样,只不过JSON字符串中的属性名必须加双引号,其他的和JS语法一致

  • JSON分类: 对象 {} ,数组 []

  • JSON中允许的值:

    1. 字符串 2. 数值 3. 布尔值 4. null 5. 对象 6. 数组
  • 举例:

    1
    2
    3
    4
    5
    6
    var arr = '[1,2,3,"hello",true]'; //数组

    var obj2 = '{"arr":[1,2,3]}'; //对象

    var json =
    '[{"name":"孙悟空","age":18,"gender":"男"},{"name":"孙悟空","age":18,"gender":"男"}]'; //对象数组

区别

  • js是一个对象

    • json :字符串

    • js对象不要引号

    • json的key必须用引号

    • js对象不能传输

    • json用于传输

注意

  • JSON这个对象在IE7及以下的浏览器中不支持,所以在这些浏览器中调用时会报错

  • eval():这个函数可以用来执行字符串形式的js代码,并将执行结果返回

    • 如果使用eval执行的字符串中含有{},会将{}当成代码块。
    • 如果不希望当成代码块解析,这需要在字符串前后加上()
    • 虽然功能强大,首先执行性能比较差,然后有安全隐患,开发中尽量避免使用
  • 解决办法,引入一个js文件(功能就是创建JSON对象)

    1
    2
    3
    4
    5
    6
    7
    var str1 = 'alert("hello")';
    eval(str1); //会自动执行代码,弹出hello
    var str2 = '{"name":"孙悟空","age":18,"gender":"男"}';
    var obj = eval("(" + str2 + ")");
    console.log(obj);
    // {name: "孙悟空", age: 18, gender: "男"}
    typeof obj; //"object"

json > js对象

  • JSON.parse()
  • 可以将以JSON字符串转换为js对象
  • 它需要一个JSON字符串作为参数,会将该字符串转换为JS对象并返回
1
2
3
var o = JSON.parse(json);
var o2 = JSON.parse(arr);
//console.log(0[1].name)

JS对象 > JSON

  • JSON.stringify() 可以将一个JS对象转换为JSON字符串

    • -ify/fy,表示”使……化。
  • 需要一个js对象作为参数,会返回一个JSON字符串

    1
    2
    3
    4
    var obj3 = { name: "猪八戒", age: 28, gender: "男" };
    var str = JSON.stringify(obj3);
    console.log(str);
    // "{"name":"猪八戒","age":28,"gender":"男"}"

js实现复制到剪切板

  • 第一种,通过clipboard.js插件实现(推荐)clipboard传送门

  • 第二种,纯js实现:

    1
    2
    3
    4
    5
    6
    7
    8
    document.getElementById("copy-text-btn").onclick = function () {
    //获取文本并去掉空格
    var ssrsss = document
    .getElementById("text-content")
    .innerText.replace(/\ +/g, "");
    var flag = copy(ssrsss); //传递文本
    alert(flag ? "复制成功" : "复制失败");
    };
    • 使用input接收
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    function copy(text) {
    const input = document.createElement("input"); //创建input对象
    document.body.appendChild(input); //添加元素
    input.setAttribute("value", text);
    input.select();

    try {
    var flag = document.execCommand("copy"); //执行复制
    // console.log("复制成功");
    } catch (eo) {
    var flag = false;
    }
    document.body.removeChild(input); //删除元素
    return flag;
    }
    • 使用textarea文本框
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    function copyText(text) {
    var textarea = document.createElement("textarea"); //创建input对象
    var currentFocus = document.activeElement; //当前获得焦点的元素
    var toolBoxwrap = document.getElementById("NewsToolBox"); //将文本框插入到NewsToolBox这个之后
    toolBoxwrap.appendChild(textarea); //添加元素
    textarea.value = text;
    textarea.focus();
    if (textarea.setSelectionRange) {
    textarea.setSelectionRange(0, textarea.value.length); //获取光标起始位置到结束位置
    } else {
    textarea.select();
    }
    try {
    var flag = document.execCommand("copy"); //执行复制
    } catch (eo) {
    var flag = false;
    }
    toolBoxwrap.removeChild(textarea); //删除元素
    currentFocus.focus();
    return flag;
    }

localStorage

  • HTML5中,新加入了一个localStorage特性,
  • 主要是用来作为本地存储来使用的,解决了cookie存储空间不足的问题(cookie中每条cookie的存储空间为4k)
  • localStorage中一般浏览器支持的是5M大小,这个在不同的浏览器中localStorage会有所不同。

优势与局限

  • 优势

    • localStorage拓展了cookie的4K限制
    • localStorage会可以将第一次请求的数据直接存储到本地,这个相当于一个5M大小的针对于前端页面的数据库,相比于cookie可以节约带宽,但是这个却是只有在高版本的浏览器中才支持的
  • 局限

    • 浏览器的大小不统一,并且在IE8以上的IE版本才支持localStorage这个属性
    • 目前所有的浏览器中都会把localStorage的值类型限定为string类型,这个在对我们日常比较常见的JSON对象类型需要一些转换
    • localStorage在浏览器的隐私模式下面是不可读取的
    • localStorage本质上是对字符串的读取,如果存储内容多的话会消耗内存空间,会导致页面变卡
    • localStorage不能被爬虫抓取到

localStorage与sessionStorage的区别

  • localStorage属于永久性存储
  • sessionStorage属于当会话结束的时候,sessionStorage中的键值对会被清空

localStorage写入

  • 如果是使用IE8以下浏览器的话,那么就要UserData来作为存储

  • 首先在使用localStorage的时候,我们需要判断浏览器是否支持localStorage这个属性

    1
    2
    3
    4
    5
    6
    if (!window.localStorage) {
    alert("浏览器不支持localstorage");
    return false;
    } else {
    //主逻辑业务
    }
  • localStorage的写入有三种方法

    • 控制台上面打印出来的结果是:string
    • 存储进去的是int类型,但是打印出来却是string类型
    • 这个与localStorage本身的特点有关,localStorage只支持string类型的存储
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    if (!window.localStorage) {
    alert("浏览器不支持localstorage");
    } else {
    var storage = window.localStorage;
    //写入a字段
    storage["a"] = 1;
    //写入b字段
    storage.b = 1;
    //写入c字段
    storage.setItem("c", 3);
    console.log(typeof storage["a"]);
    console.log(typeof storage["b"]);
    console.log(typeof storage["c"]);
    }
  • localStorage的使用也是遵循同源策略

localStorage读取

  • 官方推荐的是getItem\setItem这两种方法对其进行存取
1
2
3
4
5
6
7
8
9
10
11
12
13
14
if (!window.localStorage) {
alert("浏览器不支持localstorage");
} else {
var storage = window.localStorage;
//第一种方法读取
var a = storage.a;
console.log(a);
//第二种方法读取
var b = storage["b"];
console.log(b);
//第三种方法读取
var c = storage.getItem("c");
console.log(c);
}

localStorage的删改

  • 改和更改全局变量的值一样

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    if (!window.localStorage) {
    alert("浏览器不支持localstorage");
    } else {
    var storage = window.localStorage;
    //写入a字段
    storage["a"] = 1;
    console.log(storage.a);

    /*分割线*/

    storage.a = 4;
    console.log(storage.a); //a键已经被更改为4
    }
  • localStorage的删除

    • clear()将localStorage的所有内容清除

      1
      2
      3
      4
      5
      6
      var storage = window.localStorage;
      storage.a = 1;
      storage.setItem("c", 3);
      console.log(storage);
      storage.clear();
      console.log(storage);
    • removeItem(key)将localStorage中的某个键值对删除

      1
      2
      3
      4
      5
      6
      var storage = window.localStorage;
      storage.a = 1;
      storage.setItem("c", 3);
      console.log(storage);
      storage.removeItem("a");
      console.log(storage.a);

localStorage的键获取

  • 使用key()方法,向其中填入索引即可获取对应的键

    1
    2
    3
    4
    5
    6
    7
    var storage = window.localStorage;
    storage.a = 1;
    storage.setItem("c", 3);
    for (var i = 0; i < storage.length; i++) {
    var key = storage.key(i);
    console.log(key);
    }

JS对象存入localStorage

  • 我们可以使用JSON.stringify()这个方法,来将JS对象转换成为JSON字符串

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    if (!window.localStorage) {
    alert("浏览器不支持localstorage");
    } else {
    var storage = window.localStorage;
    var data = {
    name: "xiecanyong",
    sex: "man",
    hobby: "program",
    };
    var d = JSON.stringify(data);
    storage.setItem("data", d);
    console.log(storage.data);
    }
  • 读取之后要将JSON字符串转换成为JSON对象,使用JSON.parse()方法

    1
    2
    3
    4
    //将JSON字符串转换成为JSON对象输出
    var json = storage.getItem("data");
    var jsonObj = JSON.parse(json);
    console.log(typeof jsonObj); // Object对象