一、javascript的介绍
(一)javascript的诞生
1994 年,网景公司(NetScape)发布了Navigator浏览器0.9版, 这是历史上第一个比较成熟的浏览器,引起了广泛关注。但是,这个版本的浏览器只能用来浏览,不具备与访问者互动的能力。。。。网景公司急需要一门网页脚本语言,使得浏览器可以与网页进行互动。
1995年4月,网景公司录用了34岁的系统程序员Brendan Eich, 他只用10天时间就把Javascript设计出来。布兰登·艾奇
(二)javascript的特点
- javascript是一个轻量级的语言
- javascript是可以插入HTML页面的编程代码
- javascript支持目前所有的浏览器
- 解释执行不需要编译
- 基于对象,内置大量的现成对象,编写少量的程序就可以完成目标
(三)javascript的组成
- ECMAScript javascript的语法标准
- DOM(Document Object Model)文档对象模型: javascript 操作网页元素的API
- BOM(Browser Object Model) javascript 操作浏览器部分功能的API
(四)javascript 和 Html css 的关系
- Html 用来编写网页的结构
- css 美化网页添加样式
- javacript 实现网页和客户之间的沟通,让网页有活力
二、javascript的书写位置
1、在html标签中使用 行内式
2、在HTML内部使用
<script>脚本内容</script>标签,可以放在任意的地方 页内式
- head标签中使用
- body标签中使用
3、外部调用
javascript在script标签的src属性中设置 <script src="脚本的路径"></script>在外部的脚本中不能包括script标签。 外链式
4、js代码书写需要注意的问题:
三、javascript显示数据的方式
1、使用 window.alert() 弹出警告框
2、使用document.write() 方法将内容写到html文档中
3、使用innerHTML写入到HTML元素。
4、使用console.log()写入到浏览器的控制台。
F12 启用调试模式, 在调试窗口中点击 "Console" 菜单。console.warn("警告输出"),console.error('这是一个错误')
5、用户输入 prompt()语句
prompt()语句就是专门用来弹出能够让用户输入的对话框。用一个变量来接收值,且不论用户输入的是什么都是一个字符串。
6、confirm
在网页中弹出提示框,显示信息,一般和if 判断来配合使用,相比alert多了一个取消的按钮。
7、javascript显示方式的说明和对比
(1) console.log()和alert相比
(2) document.write 和 innerHTML
(3) alert和prompt的区别
四、javascript的语法
js 基本的代码规范:
- javascript对换行、缩进、空格不敏感。
- 每条语句的末尾都要加上分号,除了if、for、function语句结尾处不加分号,如果不加分号,压缩之后将不能运行。
- 所有的符号都是英文的。
- js中的字符串可以使用单引号,也可以使用双引号,一般使用双引号;
- 区分大小写
- 变量是弱类型的,定义变量时要用var运算符声明变量,可以将它初始化为任意值。因此,可以随时改变变量所存数据的类型(尽量避免这样做)。
- javascript的注释
- 单行 // 单行注释可以嵌套单行、多行注释
- 括号表示代码块,代码块表示一系列应该按顺序执行的语句,这些语句被封装在左括号({)和右括号(})之间。
五、javascript的字面量
“直接量”即常量,就是一些不可改变的值,也称为“字面量”,看见什么就是什么。 字面量的种类
- 数字(number)字面量,可以是整数或者是小数,或者是科学计数(e)。
- 字符串(String)字面量 可以使用单引号或双引号
- 表达式字面量 用于计算
- 数组(Array)字面量 定义一个数组
- 对象(Object)字面量 定义一个对象
- 函数(Function)字面量 定义一个函数
六、变量
变量表示一些可以变化的数据,当一个数据的值经常变化或是不确定时,就应该用变量来表示。 变量的作用:用来操作数据的(可以读取,可以存储)
(一)声明变量
- 变量使用前必须用var运算符进行声明,且不需要声明变量的类型。
- 可以用一个var声明多个变量,变量之间用逗号分隔。
- 可以用同一个 var 语句声明的变量不必具有相同的类型。
- var声明的变量并不一定要初始化一个值。
- 变量可以存放不同类型的值。这是弱类型变量的优势,如可以把变量初始化为字符串类型的值,之后把它设置为数字值。
- 变量声明不是必须的。
首先,sTest 被声明为字符串类型的值 "hello"。接下来的一行,用变量 sTest2 把 sTest 与字符串 "world" 连在一起。变量 sTest2并没有用var运算符定义,这里只是插入了它,就像已经声明过它一样。 ECMAScript的解释程序遇到未声明过的标识符时,用该变量名创建一个全局变量,并将其初始化为指定的值。这是该语言的便利之处,不过如果不能紧密跟踪变量,这样做也很危险。最好的习惯是像使用其他程序设计语言一样,总是声明所有变量。
(二)变量的命名规范
变量名需要遵守两条简单的规则:
- 第一个字符必须是字母、下划线(_)或美元符号($),不能以数字开头。
- 余下的字符可以是下划线、美元符号或任何字母或数字字符;
- 变量名一般都是小写;
下面的变量都是合法的:
- 保留字不能用作变量名
-
几种常见的命名方式:
1、Camel 标记法:首字母是小写的,接下来的字母都以大写字符开头。例如:
2、Pascal 标记法 首字母是大写的,接下来的字母都以大写字符开头。例如:
3、匈牙利类型标记法:
在以Pascal标记法命名的变量前附加一个小写字母(或小写字母序列),说明该变量的类型。例如,i 表示整数,s 表示字符串,如下所示“
(三)变量值交换
1、第一种方法:利用临时变量进行交换
2、第二种方法: 一般用于数字交换
3、第三种方法: 位运算交换
(四)变量值的分类
在 ECMAScript 中,变量可以存在两种类型的值,即原始值和引用值。又可以称为基本数据类型(简单类型和值类型)和复杂类型,
原始数据类型有:number string null undefined boolean object 原始值(基本数据类型):number string null undefined boolean 引用值(复杂数据类型):object
原始值(基本数据类型) 存储在栈(stack)中的简单数据段,也就是说,它们的值直接存储在变量访问的位置。
引用值(复杂数据类型) 存储在堆(heap)中的对象,也就是说,存储在变量处的值是一个指针(point),指向存储对象的内存处。
为变量赋值时,ECMAScript 的解释程序必须判断该值是原始类型,还是引用类型。要实现这一点,解释程序则需尝试判断该值是否为 ECMAScript 的原始类型之一,即 Undefined、Null、Boolean、Number 和 String 型。由于这些原始类型占据的空间是固定的,所以可将他们存储在较小的内存区域 - 栈中。这样存储便于迅速查寻变量的值。
在许多语言中,字符串都被看作引用类型,而非原始类型,因为字符串的长度是可变的。ECMAScript 打破了这一传统。
如果一个值是引用类型的,那么它的存储空间将从堆中分配。由于引用值的大小会改变,所以不能把它放在栈中,否则会降低变量查寻的速度。相反,放在变量的栈空间中的值是该对象存储在堆中的地址。地址的大小是固定的,所以把它存储在栈中对变量性能无任何负面影响。如下图所示:

原始类型(基本数据类型)
ECMAScript 有 5 种原始类型(primitive type),即 Undefined、Null、Boolean、Number 和 String。
typeof运算符查看变量值的类型
typeof 运算符有一个参数,即要检查的变量或值。例如:
输出结果:

对变量或值调用 typeof 运算符将返回下列值之一:
- undefined - 如果变量是 Undefined 类型的
- boolean - 如果变量是 Boolean 类型的
- number - 如果变量是 Number 类型的
- string - 如果变量是 String 类型的
- object - 如果变量是一种引用类型或 Null 类型的
- function-函数
typeof 运算符对于 null 值会返回 "Object"。这实际上是 JavaScript 最初实现中的一个错误,然后被 ECMAScript 沿用了。现在,null 被认为是对象的占位符,从而解释了这一矛盾,但从技术上来说,它仍然是原始值。
各个原始类型(基本数据类型)详细介绍
1、Undefined 类型
值 undefined 并不同于未定义的值。但是,typeof 运算符并不真正区分这两种值。
如果对bb使用除typeof之外的其他运算符的话,会引起错误,因为其他运算符只能用于已声明的变量上。
当函数无明确返回值时,返回的也是值 "undefined"
调用函数时,应该提供的参数没有提供,该参数等于 undefined
对象没有赋值的属性
2、Null 类型
它只有一个专用值 null,即它的字面量。值 undefined 实际上是从值 null 派生来的,因此 ECMAScript 把它们定义为相等的。
尽管这两个值相等,但它们的含义不同。undefined 是声明了变量但未对其初始化时赋予该变量的值,null则用于表示尚未存在的对象。如果函数或方法要返回的是对象,那么找不到该对象时,返回的通常是 null。想让一个变量的值是Null时,必须手动指定 var a = Null;
3、Boolean 类型
它有两个值 true 和 false (即两个 Boolean 字面量)。即使 false 不等于 0,0 也可以在必要时被转换成 false,这样在 Boolean 语句中使用两者都是安全的
任何的非0数值都是true,包括正负无穷,只有0和NaN是false 任何的非空字符串都是true,只有空字符串是false 任何的对象都是true,除了Null和 undefined是false,空数组[],和空对象{}是true
4、Number 类型
ECMA-262 中定义的最特殊的类型是 Number 类型。这种类型既可以表示 32 位的整数,还可以表示 64位的浮点数。直接输入的(而不是从另一个变量访问的)任何数字都被看做 Number 类型的字面量。
- javascript 可正常计算的范围:小数点前16位,后16位。
- 八进制数和十六进制数
js 可以表示不同进制的数字,得看浏览器的支持
整数也可以被表示为八进制(以8为底)或十六进制(以16为底)的字面量。八进制字面量的首数字必须是 0,其后的数字可以是任何八进制数字(0-7),
要创建十六进制的字面量,首位数字必须为 0,后面接字母 x,然后是任意的十六进制数字(0 到 9 和 A 到 F)。这些字母可以是大写的,也可以是小写的。
尽管所有整数都可以表示为八进制或十六进制的字面量,但所有数学运算返回的都是十进制结果。
- 浮点数
要定义浮点值,必须包括小数点和小数点后的一位数字(例如,用 1.0 而不是 1)。这被看作浮点数字面量。
对于浮点字面量的有趣之处在于,用它进行计算前,真正存储的是字符串
- 科学计数法
对于非常大或非常小的数,可以用科学计数法表示浮点数,可以把一个数表示为数字(包括十进制数字)加 e(或 E),后面加乘以 10 的倍数。
该符号表示的是数 56180000。把科学计数法转化成计算式就可以得到该值:5.618 x 107。
- 特殊的 Number 值
前两个是 Number.MAX_VALUE 和 Number.MIN_VALUE,它们定义了 Number 值集合的外边界。所有ECMAScript数都必须在这两个值之间。不过计算生成的数值结果可以不落在这两个值之间。 最后一个特殊值是 NaN,表示非数(NotaNumber)。NaN是个奇怪的特殊值。一般说来,这 种情况发生在类型(String、Boolean 等)转换失败时。例如,要把单词 blue 转换成数值就会失败,因为没有与之等价的数值。与无穷大一样,NaN也不能用于算术计算, 是一个非法的数字,当对数值进行计算,没有结果返回,则返回NaN,NaN 的另一个奇特之处在于,它与自身不相等,这意味着NaN也不等于NaN。
- NaN 属性是代表非数字值的特殊值。
含义:表示非数字, 主要用在将字符串解析成数字出错的场合。
一些数学函数的运算结果也会出现NAN
0除0也会是NaN 1/0是Infinity
运算规则:
NaN不等于任何值,包括它本身NaN === NaN // false
Nan在布尔运算时被当作是false Boolean(NaN) // false
NaN与任何数(包括它自己)的运算,得到的都是NaN
小结:
(1)无论是小数还是整数都是数字类型
(2)不要用小数去验证小数
(3)不要用NaN判断是不是Nan,而是用isNan(值或者是变量句)
(4)想表示十进制就是正常的数字
(5)想表示八进制以0开头
(6)想表示十六进制以0x开头
(7)像010这样的字符串,有些浏览器会当成是8进制,有些则会当成是10进制,为了保证准确性,在进行转换时,parseInt()时,用第二个参数明确具体的进制数。
5、String 类型
String 类型的独特之处在于,它是唯一没有固定大小的原始类型。可以用字符串存储 0 或更多的 Unicode 字符, 字符串字面量是由双引号(")或单引号(')声明的。而Java则是用双引号声明字符串,用单引号声明字符。但是由于 ECMAScript 没有字符类型,所以可使用这两种表示法中的任何一种。
只要有一个是字符串,其他的是数字,那么结果也是拼接,不是相加
字符串 - 或 * 数值 = 数值 如果有一个是字符串,另一个不是字符串,使用 - 或 * 号,此时会发生计算
输出结果:

如果把a改为字母 var a = 'e'; 则输出结果为:

如果把-换成*乘号,var c = b * a; 则输出结果为:

类型转换
1、 转换成字符串
- toString()方法
需要注意的地方:
null 和 undefined 没有toString()的方法,强行调用会报错 toString 不会改变原变量的值,它只会将转化的结果返回
- String() 函数
有时候有些值没有toString()的方法,比如null和undefined
如果Number 和 Boolean 用String函数进行字符串的转换,实际上是调用了toString的方法 对于null和undefined来说,没有toString的方法,会在内部产生一个新的字符串
- 任何数据和+连接在一起都会转为字符串,其内部的原理和String一样
2、转换成数字
parseInt() parseFloat() 和 Number()。
- 注意的地方
-
parseInt()把值转换成整数,parseFloat()把值转换成浮点数。只有对String类型调用这些方法,它们才能正确运行;对其他类型都是先转化成字符串(string()方法)后再进行转换。他的返回值只有两种,一种是十进制的整数,一种是NaN。
-
Number()函数中无论混合字符串中是否存在有效的整数,都会返回NaN,利用parseInt()和parseFloat()可以提取字符串中的有效整数。
-
parseInt()和parseFloat()的区别是,前者可以提取有效的整数,后者可以提取有效的小数。
-
对非String使用parseInt()或者parseFloat(),会将其转换成String然后再操作
-
- Number()函数
1、字符串转数字
如果是纯数字字符串,则直接将其转换为数字
如果字符串中含有非数字的内容,则转换为NaN
**如果字符串是一个空串,或是一个全部是空格的字符串,则转换为0 **
2、undefined 转数字 NaN
3、null转数字 0
4、布尔转数字 true转成1 false转成0
-
parseInt() 把值转换成整数
-
带有自动净化的功能;只保留字符串最开头的数字,后面的中文自动消失
parseInt()方法首先查看位置0处的字符,判断它是否是个有效数字;如果不是,该方法将返回 NaN,不再继续执行其他操作。但如果该字符是有效数字,该方法将查看位置 1 处的字符,进行同样的测试。这一过程将持续到发现非有效数字的字符为止,此时 parseInt() 将把该字符之前的字符串转换成数字。
-
自动带有截断小数的功能:取整,不四舍五入
字符串中包含的数字字面量会被正确转换为数字,比如 "0xA" 会被正确转换为数字 10。不过,字符串 "22.5" 将被转换成 22,因为对于整数来说,小数点是无效字符。
-
parseInt()方法还有基模式,可以把二进制、八进制、十六进制或其他任何进制的字符串转换成整数。
-
输出结果:

-
parseFloat() 把值转换成浮点数
- 会解析第一个,遇到第二个或者非数字结束;
- 如果第一位不是有效数字,什么也提取不到;
- 不支持第二个参数,只能解析10进制数;
- 如果解析内容里只有整数,解析成整数;
七、运算符
- 作用:
运算符是告诉程序执行特定算术或逻辑操作的符号, 例如告诉程序, 某两个数相加, 相减等
-
分类
- 按照功能分:算术、位、关系、逻辑
- 按照操作个数分:
- 单目运算 只有一个操作数:如i++
- 双目运算 有两个操作数:如a+b
- 三目运算 也称为问号表达式 如:a > b ? 1:0
-
结合性 JavaScript中各种运算符的结合性分为两种: 左结合性(自左至右) 和 右结合性(自右至左)
- 自左至右,即先左后右 例如表达式: x - y + z; 则y 应先与“-”号结合,执行 x-y 运算,然后再执行+z 的运算。 这种自左至右的结合 方向就称为“左结合性”。
- 自右至左,即先右后左 例如:如x = y = z = 10 由于“=”的 右结合性,应先执行z = 10; 再执行y = z 再执行x = y运算。
(一)加法运算符 +
- 非Number类型的值,除字符串外,都会先转为Number类型的值后再进行计算
- 任何值和NaN进行运算时,结果都是NaN
- 任何值和字符串进行加法运算,都会先转为字符串,然后和字符串进行拼接
(二)减法运算符 -
- 所有的非Number类型(包括字符串)的数据类型,都会将非Number数据类型先转为Number后再进行计算
- 任何数据类型和NaN进行减法运算时,结果都是NaN
(三) 乘法运算 *
规律和减法一样
(四)除法运算符 /
规律和减法一样
(五)取余运算符 %
m % n 求余 相当于 m / n 取余数
- m 等于0 返回 0
- n 等于0 返回 NaN
- m > n 正常取余
- m < n 结果是m
- 其他的规则和减法一样
(六)一元运算符
只有一个操作数的运算符 + -
- +号不会对数字产生任何的影响,类似与数字中的正号
- 对非Number类型的值,会调用Number()函数先进行转换,然后再运算
- -号相当于数字中的负数,对数字进行取反操作
(七)赋值运算符
赋值运算符可以分为简单赋值运算符和复合赋值运算符
- 简单赋值运算符
- 格式:变量名 = 数据
- =的左边只能是变量
- 多个赋值运算符可以组成赋值表达式,具有右结合性
- 复合赋值运算符
-
复合赋值表达示运算
- 格式:a *= 1 + 2
- 由于赋值运算符是右结合性,所以会先计算=右边的,然后再进行计算 相当于 a = a * (1 + 2)
(八) 自增自减运算符
1、介绍
javascript提供了 ++ -- 这两种自增和自减的运算符来简化 i = i + 1, i = i - 1 这样的操作
2、自增、自减 求值的过程
- 无论运算符在前面还是后面(前缀还是后缀)变量自身都会发生改变
- 后缀表达式 i ++ , i -- 先用i的值做为整个表达式的值,再进行加1或减1的操作,即:先用后变
- 前缀表达式 ++ i, -- i 先自身加1或减1,然后再将i的值做为表达式的值,即:先变后 用
(九)关系运算符
关系运算符的返回值,只有两个,要么是真(true)要么是假(false)
- javascript 支持的关系运算符

- 对于非数值类型进行比较时,会转换为数值再进行比较
- 如果两侧都是字符串,不会转换为数字进行比较,而是分别比较字符串的Unicode编码的大小
- 比较编码时是从左到右一位一位进行比较
- 如果两位相同,则会比较下一位,可以用来做英文的排序
- 比较中文没有意义
- null、 undefined、 NaN比较
- 注意的地方
比较两个字符串类型的数字,结果可能有偏差,所以需要提前转型;
(十)逻辑运算符
1、&& (与运算)
- 运行结果 条件A && 条件B
先去判断条件A成不成立,如果A成立了才去判断B是否成立,如果A不成立则不会去判断B
两个条件为真才为真,有一个为假就为假
- 短路测试
条件 && 表达式 条件为真时,后面的表达式执行
- 注意的地方
- 对于非Boolean类型的数值,逻辑与会自动将其转换为Boolean类型来判断;
- 如果条件A成立,不管条件B成立与不成立都会返回条件B;
- 如果条件A不成立,则返回条件A本身;
2、 || (或运算)
- 运行结果 条件A || 条件B
有一个为真就为真,两个为假才为假
如果A成立了,则不会去判断条件B,只有在A不成立的时候才会去判断条件B
- 短路测试
条件 && 表达式 条件为假时,后面的表达式执行
- 注意的地方
- 对于非Boolean类型的值,逻辑或会将其自动转为布尔类型的值来判断;
- 如果条件A不成立,则不管条件B成不成立都会返回条件B本身的数值;
- 如果条件A成立,则返回条件A本身的数值;
3、 !(非运算)
- 运行结果 !条件A
对条件A进行取反 比如:条件A成立true,取反后为false
- 注意的地方
- 对一个值进行两次取反,它不会发生变化;
- 对非布尔值进行操作,则先将其转换为Boolean,然后再进行取反,所以将一个数值转换为Boolean,除了Boolean()函数外,还可以使用 !!数值, 实现的原理和Boolean(数值)是一样的;
(十一)逗号运算符
逗号表达式就是把多个表达式连接起来,组成一个表达式。
- 结果
从左往右计算,一直到最后一个,整个表达式的值也是最后一个表达式的值。
-
使用注意事项
- 程序中使用逗号表达式,通常是求表达式内各个表达式的值,并不一定要求,整个逗号表达式的值;
- 并不是所有出现逗号的地方都组成逗号表达式,例如在变量说明中,函数参数表中的逗号只是分隔作用;
(十二)三目运算符
- 格式:
条件表达式 ?语句1:语句2;
- 求值规则
条件表达式为真时,执行语句1;为假时执行语句2.
一个案例:
-
注意的地方
- 条件运算符?:是一对运算符,不能分开单独使用
- 如果条件表达式的求值结果不是一个Boolean,则会转换为Boolean值后再运算
(十三)运算符的优先级
- 运算符的优先级共分为15级,1最高,15最低;
- 计算规则
- 先计算优先级高的;
- 如果优先级一样,则谁在左边先算谁
- 可以使用()来改变优先级
- 优先级图示

八、流程控制
(一)if 语句
一个分支,要么执行,要么不执行
- 语法
- 执行过程
如果条件是true,则执行代码块,如果是false,不会执行代码块
(二)if else 语句
两个分支,只能执行一个分支,像这种情况也可以使用三元表达式
- 语法
- 执行过程
如果表达式的结果是true,执行代码块1,如果结果是false,则执行代码块2
(三)if else if else if .. else 语句
多个分支,最终也执行一个
- 语法
- 执行过程
先判断表达式1的结果,如果是true,就执行代码块1,后面的不会执行,如果结果是false,则会判断表达式2的结果,如果是true,就执行代码块2,后面的不执行,如果是false,则会继续判断下一个表达式,依此类推,最终,如果else if的表达式结果都是false,则执行最后的else代码块的语句。
(四) switch case 语句
多个分支,最终也执行一个(最终执行几个由break决定)
- 语法
- 执行过程
获取表达式的值,和值1进行比较,如果相同,则执行代码1,遇到break跳出,后面的代码不执行;如果和值1不相同,则和值2进行比较,依此类推,如果表达式的值和case的值都不一样,就执行default代码5的,跳出。
break的使用
九、循环
(一)while 循环
- 语法
- 执行过程
先判断循环条件是true还是false,如果条件是true,则执行循环体和计数器,再次判断循环条件,如果条件成立,就执行循环体,否则就退出循环。
(二)do while 循环
- 语法
- 执行过程
先执行一次循环体,然后判断条件是true还是false,如果是false,则跳出循环,如果是true,则继续执行循环体,至到条件不满足,跳出循环体,
-
while 和 do while的区别
- while 是先判断,后循环,有可能一次循环都不执行;
- do-while 是先循环,后判断,至少执行一次循环;
(三)for 循环
- 语法
- 执行过程 先执行一次表达式1,然后判断表达式2的条件成不成立。
- 如果成立,则执行一次循环体,然后执行表达式3,再判断表达式2成不成立,依此类推,至到表达式2不成立。跳出循环;
- 如果不成立,则跳出循环;
(四) break 语句
如果在循环中,遇到了break,则立即跳出当前所在的循环(注意是当前的循环,如果还有外层循环,是不会跳出的)
(五)continue 跳出本次循环
在循环中遇到continue关键字,直接跳出本次循环,进入一下次循环。
十、数组
- 数组:变量只能存储一个值,所谓的数组就是将多个元素(通常是同一类型)按一定顺序排列放到一个集合中,那么这个集合我们就称为数组。
- 数组的作用:可以一次性存储多个数据;
- 数组的所有方法来源于:
Array.prototype
-
数组的定义
1、通过构造函数创建数组;
2、通过字面量的方式创建数组;
3、数组的读和写
arr[num] 不可以溢出读,结果是undefind,不会报错
arr[num] = xxx 可以溢出写,会把数组的长度撑长到num,前面的数据是undefind。
- 数组元素:数组中存储的每个数据,都可以叫数组的元素,比如:存储了3个数据,数组中3个元素
- 数组的长度:就是数组的元素的个数,比如有3个元素,就说这个数组的长度是3;
- 数组索引(下标):用来存储或者访问数组中的数据的;数组名[下标]
- 注意点:
- 无论是构造函数的方式还是字面量的方式定义的数组,如果有长度,那么默认的是undefined;
- 构造函数的方式创建数组的时候,如果在Array(一个数字)————>数组的长度(数组元素的个数);
- 如果在Array(多个值),这个数组中就有数据了,数组的长度就是这些数据的个数;
- 数组的索引和数组长度的关系:就是长度减1,就是最大的索引;
冒泡排序:

伪数组
arguments对象是所有(非箭头)函数中都可用的局部变量。你可以使用arguments对象在函数中引用函数的参数。arguments对象不是一个 Array 。它类似于Array,但除了length属性和索引元素之外没有任何Array属性。例如,它没有 pop 方法。
arguments.length 可以获取函数在调用时,传入了几个参数,还可以使用arguments对象可以获取传入的每个参数的值(数组形式)函数名.length:可以获取形参的个数;
类数组的构成
上面的就叫一个类数组,必须有几个组成部分
1、属性要为索引(数字)必须有length属性,最好加上push。
2、好处,可以像数组一样用,也可以像对象一样用,DOM生成的类数组的东西,全是类数组。
十一、函数
函数:把一坨重复的代码封装,在需要的时候直接调用即可
函数的作用:代码的重用。
arguments.callee
指向的是函数的引用,也就是函数本身的代码,在那个函数里就指代那个函数本身
function.caller
函数自己的属性,在那个环境里调用,就是谁

预解析代码:
递归
找规律(公式),找出口(已知的条件)
阶乘的公式:n*(n-1)
斐波那契数列:(n-1)+(n-2);
十二、面向对象
- 编程思想:把一些生活中做事的经验融入到程序中;
- 面向过程:凡事都要亲力亲为,每件事的具体过程都要知道,注重的是过程;
- 面向对象:根据需求找对象,所有的事都用对象来做,注重的是结果;
- 面对对象的三大特性:封装、多态、继承;
- js不是面对对象的语言,是一门基于对象的语言,但是可以模拟面向对象的思想;
- 什么是对象:看的见,摸的到,具体特指的某个东西,比如:汽车就是不是一个对象,是一个类别,而挂甘A10011的就是对象。有属性和方法,具体特指的某一个事物;
创建对象的三种方式
1、调用系统的构造函数创建对象
2、工厂模式创建对象
3、自定义构造函数创建对象(结合第一种和需求通过工厂模式创建对象)
4、字面量的方式创建对象;
访问对象属性方法的另一种写法
obj.prop与obj["prop"]
当执行obj.prop的时候,内部会隐式的转化成obj["prop"]的方式来执行,obj[]的这种形式,方括号里的必须是字符串
属性名是字符串拼接的情况
知识点
- 对象是一组无序属性的集合,属性的值可以是任意的数据类型
-
json格式的数据:一般都是成对的,是键值对,json也是一个对象,数据都是成对的,一般json格式的数据无论是键还是值都是用双引号括起来的。
JSON.parse():string —> json
JSON.stringify():json —>string
- 判断一个对象里有没有指定属性
- 在对象中一个方法调用另一个方法
对象的枚举
for in
会延伸到原型链上的属性,但是不会打印Object上的东西。
hasOwnProperty(属性名) ,判断一个属性是自己的还是原型链上的,是自己的为true
in
判断整个原型链上有没有这个属性,有就是true,
"lastName" in obj则为true
instanceof
A instanceof B A对象是不是B构造函数构造出来的,实际上是看A的原型链上有没有B的原型
判断数据的类型
对象的深浅拷贝
浅拷贝
总结起来,浅拷贝就是只能拷贝原始值,只是拷贝了引用值的指向,所以引用值一个改变也会影响另一个的改变。
深拷贝
十三、内置对象
对象分为三种:内置对象、自定义对象、浏览器对象
内置对象:系统提供的
自定义对象:自己写的对象
浏览器对象:浏览器的
实例对象,通过构造函数创建出来的,实例化的对象;
静态对象,不需要创建,直接就是一个对象,方法(静态方法),直接通过这个对象名子调用。
实例方法必须通过实例化后的对象调用的;对象.方法();
静态方法必须通过大写的构造函数这样的调用的方式调用的;构造函数.方法()
(一)Math
Math 是一个内置对象,具有数学常数和函数的属性和方法,不是一个构造函数,所有的属性和方法都是静态的。
Math 对象属性
| 属性 | 描述 |
|---|---|
| E | 返回算术常量 e,即自然对数的底数(约等于2.718)。 |
| LN2 | 返回 2 的自然对数(约等于0.693)。 |
| LN10 | 返回 10 的自然对数(约等于2.302)。 |
| LOG2E | 返回以 2 为底的 e 的对数(约等于 1.414)。 |
| LOG10E | 返回以 10 为底的 e 的对数(约等于0.434)。 |
| PI | 返回圆周率(约等于3.14159)。 |
| SQRT1_2 | 返回返回 2 的平方根的倒数(约等于 0.707)。 |
| SQRT2 | 返回 2 的平方根(约等于 1.414)。 |
Math 对象方法
| 方法 | 描述 |
|---|---|
| abs(x) | 返回数的绝对值。 |
| acos(x) | 返回数的反余弦值。 |
| asin(x) | 返回数的反正弦值。 |
| atan(x) | 以介于 -PI/2 与 PI/2 弧度之间的数值来返回 x 的反正切值。 |
| atan2(y,x) | 返回从 x 轴到点 (x,y) 的角度(介于 -PI/2 与 PI/2 弧度之间)。 |
| ceil(x) | 对数进行上舍入。 |
| cos(x) | 返回数的余弦。 |
| exp(x) | 返回 e 的指数。 |
| floor(x) | 对数进行下舍入。 |
| log(x) | 返回数的自然对数(底为e)。 |
| max(x,y) | 返回 x 和 y 中的最高值。 |
| min(x,y) | 返回 x 和 y 中的最低值。 |
| pow(x,y) | 返回 x 的 y 次幂。 |
| random() | 返回 0 ~ 1 之间的随机数。 |
| round(x) | 把数四舍五入为最接近的整数。 |
| sin(x) | 返回数的正弦。 |
| sqrt(x) | 返回数的平方根。 |
| tan(x) | 返回角的正切。 |
| toSource() | 返回该对象的源代码。 |
| valueOf() | 返回 Math 对象的原始值。 |
(二)Date
(三)String
String是一个对象,字符串可以看成是字符组成的数组,但是JS中没有字符类型,字符是一个一个的,在别的语言中是用单引号括起来的,在JS中字符串可以使用单引号或者双引号,因为字符串可以看成是数组,所以能用for循环进行遍历。
字符串的特性:不可变性。单独写是基本的数据类型(栈)通过new构造函数的方式创建的是引用类型(堆 栈)javascript会将基本的数据类型的字符串转化为字符串对象,来使用字符串对象的方法。
字符串的重新赋值,看起来是字符串发生改变了,实际上是指向改变了,并不是值改变了,原来的值还在内存中。
案例:
(四)Array
- 判断变量是不是数组类型两种方式
1、instanceof
2、使用数组的静态方法Array.isArray()方法
- 常用的一些方法
- 改变原数组的:push, pop, shift, unshift, sort, reverse, splice
- 不改变原数组:concat, (join —可逆> split),toString, slice
技巧:
(五)包装类
基本包装类型
- 普通变量不能直接调用属性或者方法;
- 对象可以直接调用属性和方法;
**基本包装类型:本身是基本类型,但是在执行代码的过程中,如果这种类型的变量调用了属性或者是方法,那么这种类型就不再是基本类型了,而是基本包装类型,这个变量也不再是普通的变量了,而是基本包装类型对象 **
string number boolean 是基本类型,也是基本包装类型
Web API
一、API相关的概念
** 什么是API **
API是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。
- 任何开发语言都有自己的api
- API的特征输入和输出
- API的使用方法(console.log())
** 什么是WEB API **
浏览器提供一套操作浏览器功能和页面的API(BOM和DOM)
二、DOM
DOM 就是把页面看成是一个文档,学习DOM就是学习操作文档里的元素。DOM又称为文档树模型
DOM树:把html页面或者是xml文件看成是一个文档,文档就是一个对象,这个文档中所有的标签都是元素,元素也可以看成是对象,标签(元素、对象)有很多,还有嵌套关系组成的这种层次结构,可以模拟成树形结构图,简称:树状图,就是dom树
DOM对象:通过DOM方式获取的元素得到的对象
文档 一个网页可以称为文档
节点(node):页面中所有的内容都是节点(包括标签、属性、文本(文字、换行、空格、回车)、注释等)
元素(elementt):页面中所有的标签都是元素,元素可以看成是对象。
根元素:html标签
页面中的顶级对象:document
属性 标签的属性
HTML文件是用来展示信息,展示数据的 XML:侧重于存储数据
HTML 文件看成是一个文档(document),把这个文档也可以看成是一个对象,文档中所有的标签都可以看成是一个对象
DOM结构树(继承关系)

DOM结构树上相关联的有这个继承的关系,例如在HTMLElement.abc=123,那么在它的分支下的任何一个拥有继承关系的分支上,都会有这个属性。比如在页面中选中一个元素,那么这个元素身上也有abc=123这个属性。
document.__proto__ ==> HTMLDocument HTMLDocument.__proto__ ==>Document Document.__proto__ ==> NodeNode.__proto__==> EventTarget EventTarget.__proto__ ==>Object
三、DOM 常见的操作
- 获取元素
- 动态创建元素
- 对元素进行操作(设置其属性或调用其方法)
- 事件(什么时机做相应的操作)
1、getElementByid方法定义在Document.prototype上,即Element节点上不能使用。
2、getElementsByName方法定义在HTMLDocument.prototype上,即非html中的document不能使用(xml documentElement)
3、getElementsByTagName方法定义在Document.prototype和Element.prototype上,换句话说就是获取到的元素可以继续调用getElementsByTagName这个方法。
4、HTMLDocument.prototype定义了一些常用的属性,body.head分别指代HTML文档中的<body><head>标签
5、Document.prototype上定义了documentElement属性,指代文档的根元素,在HTML文档中,他总是指代 <html>元素。
6、getELementsByClassName、querySelectorAll、querySelector在Docuement.prototype,Element.prototype类中均有定义。
获取页面元素的方法
除了id,其他的选择器取出来的都是一组的,基本上全部是类数组
1、根据id属性获取元素 返回的是一个元素对象 getElementById("id")
2、根据标签名获取元素 返回的是元素对象组成的伪数组 getElementsByTagName("标签的名子")
下面的几个,有的浏览器不支持
3、根据表单的name属性获取元素,返回的是元素对象组成的一个伪数组 getElementsByName("name属性")
4、根据类样式的名子来获取元素,返回的是元素对象组成的伪数组 getElementsByClassName("类名子")
5、根据css选择器获取元素,返回来的是一个元素对象 querySelector("选择器名字"),并不常用,选择出来的东西不是时事的
6、根据css选择器获取元素,返回的是元素对象组成的伪数组 querySelectorAll("选择器的名字")
四、事件
事件的三要素
-
事件源:被触发事件的元素
-
事件类型:事件的触发方法(如鼠标经过、鼠标点击)
- 鼠标事件
click(点击)、mousedown(鼠标按下),mouseup(鼠标抬起),一个鼠标的click点击事件分开来看就是是先down,再up,形成一个click事件。
mousemove:鼠标移动事件
contextmenu:鼠标右键产生菜单事件。
mouseover进入,mouseout离开,mouseenter、mouseleave
- mouseover和mouseout在父元素和其子元素都可以触发,当鼠标穿过一个元素时,触发次数得依子元素数量而言。
- mouseenter和mouseleave只在父元素触发,当鼠标穿过一个元素时,只会触发一次。
- mouseover和mouseout比mouseenter和mouseleave先触发
因此一般mouseover和mouseout一起使用,mouseenter和mouseleave一起使用,
必须是事件mousedown和mouseup事件来判断,用事件参数对象button的属性值来区分鼠标的左右键:0/1/2,左/中键/右键,click事件只能监听左键。
-
键盘事件
-
和鼠标的click事件不一样,keydown+ keyup != keypress,
-
keydown>keypress>keyup
-
keydown和keypress的区别
-
keydown的事件参数参数对象的charCode属性值为0,而keypress的charCode是每个字母的ASCII码,而两个的which都有值,对应的是每个键的值,但是大小写也是一样的,所以字符用keypress,而操作类的用keydown.
-
keydown可以响应任意键盘按键,keypress只可响应字符类键盘按键
-
keypress返回ASCII码,可以转换成相应字符。
-
-
-
文本操作事件
- input(输入一次触发一次),change(鼠标聚焦,与失去聚点,两次input的value值发生改变时才触发)
- focus获得焦点触发, blur失去焦点后触发,
-
窗休操作类(window上的事件)
- scroll 页面滚动条发生滚动触发
- load 整个文档解析完毕后才触发,效率低。
-
事件的外理程序:事件触发后要执行的代码(函数形式)
点击操作: 就是一个事件。
事件:就是一件事,比如 按键被点击,弹出对话框,点击就是事件的名子
触发:被点了,就是触发了
响应:弹框了就是响应
事件源:按键就是事件源
事件绑定的特性 一但绑定 这个元素 就一直有这个事件了,即使事件中修改了这个元素的id,事件也会继续有这个事件。
事件源对象:event.target 火狐只有这个,event.srcElement ie只有这个,这两个chrome都有
var target = event.target || event.srcElement;
事件参数对象:window.event和e都是事件参数对象,一个是Ie的标准,一个是火狐的标准,事件参数e在ie8的浏览器中是不存在,此时用window.event来代替。var event = e ||window.event;
事件委托:通过事件的冒泡把子元素的事件传传递给父元素,父元素再通过事件源对象操作每个子元素
优点:1、性能不需要循环所有的元素一个个绑定事件
2、灵活,当有新的子元素时不需要重新绑定事件。
(一)点击事件 onclick
(二)鼠标进入和移出事件 onmouseover进入 onmouseout 移出
案例一:鼠标进入离开列表高亮显示
案例二:鼠标进入和移出显示二维码
事件响应代码中添加和移除类名的方式,显示或隐藏,注意多个类名的时候,要把之前的也要重新写上
案例三:鼠标经过高亮显示边框
注意,由于border会增加盒子的大小,鼠标经过时会显示跳,影响下面的布局,所以先在css里设置好边框大小,颜色和背景一样,鼠标经过时只改边框颜色就可以了
(三)焦点事件
进入焦点:onfocus 失去焦点:onblur
案例一:模拟搜索框焦点事件
案例二:验证密码长度
五、操作属性
能对属性进行赋值,也可以通过属性拿对对应的值
(一)非表单元素的属性
href、 title 、id、 src、 className
案例一:点击按钮显示图片
案例二:点击修改a标签的地址和热点文字
案例三 点击修改P标签的显示内容
案例四 点击修改多个P标签的文字
案例5 点击修改图片的alt title
案例6:点击修改所有文本框的值
案例7 为每一张图片添加点击事件
案例8:点击按键修改按钮本身的value属性
案例9:点击图片修改自身的宽高
案例10 按钮的排他功能
案例11 点击超连接切换图片
案例12 点击按钮切换图片-通过封装document.getElementById()的方式
(二)表单元素属性
- value 用于大部分表单元素的内容获取(option除外)
- type 可以获取input标签的类型(输入框或复选框等)
- disabled 禁用属性
- checked 复选框选中属性
- selected 下拉菜单选中属性
- name
- readonly 只读
案例1:点击修改性别和兴趣
案例2:点击按钮选择菜单
案例3:点击修改文本域
(三)样式操作
1、使用style方式设置的样式显示在标签行内
对象.style.属性 = 值;设置标签的
对象.style.classText = 值
获取:getComputedStyle,因为对象.style.属性只能拿到行间样式,拿不到css类里的属性。
window.getComputedStyle(ele, null).属性。计算样式只读,返回计算样式的值都是绝对值,没有相对单位,ie8及ie8以下不兼容。第二个参数是用来获取伪元素的,把伪元素名子放到第二个参数上。
在ie8及ie8以下,使用ele.currentStyle[属性]来获取只读属性,返回的计算样式的值不是经过转换的绝对值,
案例1:点击修改div的宽高背景颜色
案例2 点击隐藏或显示div
案例3 一个按钮解决div的隐藏与显示
2、类名操作
修改标签的className属性相当于直接修改标签的类名
对象.className = 值
案例1 通过类样式,点击设置div样式
案例2 通过类样式显示隐藏div
案例3 关灯效果
(四)阻止a链接浏览器默认跳转和其他的默认事件
- return false;
- 事件参数对象.preventDefault()方法;
- href="javacript:void(0);"
案例一:点击小图切换大图
案例二:美女相册
(五) innerText和textContent兼容性
- 设置标签中的文本内容,应该使用textContent属性,谷歌、火狐支持,ie8不支持
- 设置标签中的文本内容,应该使用innerText属性,谷歌、ie8支持,高版本的火狐支持,低版本的不支持
- 如果这个属性在浏览器中不支持,那么这个属性的类型是undefined,判断这个属性的类型是不是undefined,就知道浏览器支不支持。
(六)innerText和innerHTML区别
- innerText主要是设置文本的,设置标签内容,是没有标签的效果的,同时会把标签内的所有内容(包括包含的标签)都替换为新的内容 文本的形式
- innerHTML 可以设置文本内容,主要作用是在标签中设置新的html标签内容,是有标签的效果的,同时把标签内的所有内容(包括包含的标签)都替换成
- 新的内容 解析成html代码的形式
- innerText 获取的时候,会把标签内的所有的文本内容到取到。包括嵌套的标签里的内容,文本的形式
- innerHTML 获取的时候,会把标签内的所有内容,原样获取到,html代码的形式
(七)自定义属性
- 自定义属性:也叫隐式属性,本身html标签中没有这个属性,是自己添加的,用来存储一些数据。setAttribute(属性名,属性值)
- 在html标签中添加的自定义属性,是无法通过对象.属性获取的,因为自定义属性在标签中,并不在DOM对象中,所以需要使用getAttribute("自定义属性名子")来获取的,也可以拿到显示属性。
- 在html标签中设置自定义属性,是无法通过对象.属性=值来设置的,因为这种方法自定义属性在DOM对象上,不在标签中
- 删除自定义属性:removeAttribute("属性的名子") 用于移除自定义属性和标签的属性
- 判断有没有这个属性 hasAttribute(属性名) 返回布尔值。
案例一:自定义属性的获取
案例二:自定义属性的设置与获取
案例三:删除自定义属性和标签属性
案例四:tab切换案例的实现 排他思想
排他的步骤:1、先删除所有(恢复默认)2、再重新定义
六、节点
(一)节点的介绍
页面中的所有内容都是节点,包括标签、文本(文字、空格、换行等)、注释、属性
(三)节点的属性
可以使用标签.点出来,可以使用属性节点.出来,文本节点.点出来
- nodeType: 节点的类型 1 -- 标签,2--属性,3—文本,注释-8 , document-9
- nodeName:节点的名子:标签节点--大写的标签名子,属性节点--小写的属性名子,文本节点--#text
- nodeValue: 节点的值:标签节点--null, 属性节点--属性值,文本节点--文本内容
- attributes:元素节点的属性集合
(四)节点的层级
在页面中只有标签能做为父节点(或者叫父元素)
父节点obj.parentNode=(父元素)obj.parentElement;
元素层级中,只有children兼容ie9以下的浏览器
节点层级的十二行代码
案例一:利用节点 点击更改p标签的背景颜色
案例二:隔行变色 节点的方式
节点的兼容代码
案例三:切换背景图片
背景图片变量的拼接
案例四:全选和全不选逻辑
七、元素
为了提高用户的体验, 元素创建的三种方式:
- document.write("标签的代码及内容");
- 对象.innerHTML="标签及代码";
- document.createElement("标签的名子");
(一)document.write()
创建元素有缺陷,如果是在页面加载完毕后,此时通过这种方式创建元素,那么页面上存在的所有的内容被干掉了。
(二)对象.innerHTML = "内容"
innerHTML 返回dom的内容,如果 = 就是赋予dom内容
outerHTML 会返回 dom本身+自己的内容,如果 = 就是连自己也给替换了
innerText 返回dom的文本内容 如果=需要注意,这个dom内如果有其他的标签和内容,就会一同覆盖掉
(三)创建元素
document.createElement('标签名') 创建元素节点
document.createTextNode('文本') 创建文本节点
document.createComment('注释内容') 创建注释节点
1、先创建对象
document.createElement("标签名子") 返回的是一个对象
2、追加到父元素
父元素.appendChild(对象) 追加到父元素的最后
父元素.insertBefore(对象,节点),在父元素内那个子元素前插入
案例一:点击动态创建列表
案例二:动态创建表格
(四)元素相关的操作方法
- 追加子元素 父元素对象.appendChild("子元素");
- 插入子元素 父元素对象.insertBefore(新元素,在那个元素之前插入);
- 替换子元素 父元素对象.replaceChild(新元素,被替换的元素); 返回被替换的元素
- 删除子元素 父元素对象.removeChild(删除的元素); 返回值就是删除的元素
- 删除自身:子元素对象.remove(); 没有返回值
(五)为同一个元素绑定多个相同的事件
由于 ele.onXXXX=function(){}一个元素上只能绑定一个事件,后面的会把前面的覆盖。这时this指向的是dom元素本身
1、addEventListener()
程序this指向的是dom元素本身
2、attachEvent()
程序指向是window
3、兼容性代码
4、绑定事件的区别
总结绑定事件的区别:
addEventListener(); attachEvent();
-
相同点:
1、都可以为元素绑定多个事件;
-
不同点
1、方法名不一样;
2、参数的个数不一样,addEventListener三个参数,attachEvent两个参数;
3、浏览器的兼容性不一样,addEventListener 谷歌、火狐、ie11支持,ie8不支持;attachEvent 谷歌、火狐不支持,ie11不支持,ie8不支持;
4、this不同,addEventListener中的this是当前绑定事件的对象,attachEvent中的this是window;
5、addEventListener中的事件的类型(事件的名子)没有On,attachEvent中的事件的类型(事件的名子)有on;
(六)为元素解绑事件
1、对象.onclick = function ----> 对象.onclick = null;
2、对象.addEventListener("事件名子不带On", 命名函数,false)----> 对象.removeEventListener("事件名子不带On", 命名函数,false)
3、对象.attachEvent("on事件名子",命名函数) ----> 对象.detachEvent("on事件名子",命名函数)
注意点:
1、用什么方式绑定事件,就应该用对应的方式解绑事件,不能互换。
对象.on事件名子 = 事件处理函数 (绑定事件) 对象.on事件名子 = null;
2、如果需要解绑,就要在绑定的时候使用命名函数,不能使用匿名函数;
**解绑的兼容性代码 **
八、事件冒泡
事件冒泡:多个元素嵌套,有层次关系,这些元素都注册了相同的事件,如果里面的元素的事件触发了,外面元素的该事件也自动触发了。 父级的事件子级都继承,取消冒泡防止父级的事件贯穿到子级
阻止事件冒泡
1、window.event.cancelBubble = true; ie特有的,谷歌支持,火狐不支持
2、事件参数.stopPropagation(); 谷歌和火狐支持,ie8+;
兼容代码:
事件的三个阶段:
1、事件捕获阶段:从外向内
2、事件目标阶段:最开始选择的目标
3、事件冒泡阶段:从里向外
4、触发顺序:先捕获后冒泡
5、focus、blur、change、submit、reset、select等事件不冒泡
事件参数.eventPhase 查看事件阶段
为元素绑定事件:
addEventListener("没有on的事件类型",事件处理函数,控制事件阶段的),事件触发的过程中,可能会出现 事件冒泡的效果,为了阻止事件冒泡:
window.event.cancelBubble=true;谷歌、ie8支持,火狐不支持;window.event就是一个对象,是ie的标准。
e.stopPropagation();阻止事件冒泡 ==>谷歌和火狐支持
window.event和e都是事件参数对象,一个是Ie的标准,一个是火狐的标准,事件参数e在ie8的浏览器中是不存在,此时用window.event来代替。var event = e ||window.event;
事件的阶段有三个,通过e.eventPhase这个属性可以知道当前的事件是什么阶段的,如果 这个属性的值是:1--捕获阶段 2--目标阶段 3--冒泡阶段
一般默认都是冒泡阶段,很少用捕获阶段
BOM 相关操作
一、BOM介绍
浏览器的顶级对象:window
页面中的顶级对象:document
页面中所有的内容都是属于浏览器的,页面中的内容也是window。因为页面中所有的内容都是window的,window可以省略。
二、BOM的对话框
window.alert("内容") 弹框 每个浏览器的样式不一样,只是在测试的时候用
window.prompt("请输入帐号") 让用户输入 每个浏览器的样式不一样,只是在测试的时候用
var ret = window.confirm("你确定退出吗") 点确定的时候有返回值 true false 每个浏览器的样式不一样,只是在测试的时候用
三、加载事件
只要页面加载完毕,这个事件就会触发----页面所有的内容,标签、属性、文本、包括外部引入的js文件。
页面关闭后才触发的事件 谷歌不支持
页面关闭之前触发的 谷歌不支持
四、window 中的对象
(一)location对象
(二)history对象
(三)navigator对象
五、定时器
(一)setInterval() 反复
setInterval(参数1, 参数2)
参数1:函数
参数2:时间 毫秒 1000毫秒=1秒
返回值:就是定时器的ID;
执行过程:页面加载完毕后,过了1秒,执行一次函数的代码,又过了1秒,再执行函数,注意的是页面加载完毕,过了间隔的秒后,才执行定时器。
停止定时器:window.clearInterval(参数) 参数:要清理定时器id的值,所以内部的this指向的是window
案例一:最简单的轮播图
案例二 完整的轮播图
变速动画封装
(二)setTimeout()一次性
setTimeout(函数,时间);时间还是毫秒 返回值:还是该定时器的ID
执行过程:一次性的定时器
停止定时器:window.clearTimeoutl(参数) 参数:要清理定时器id的值,所以内部的this指向的是window
(三)直接通过document获取属性
九、一些属性和方法
(一)offset系列中的属性
值都是数字类型,元素的样式属性是无法直接通过:对象.style,属性来获取的(因为样式在style标签中设置的,只有在style属性中设置的才能获取)
- offsetLeft:距离左边位置的值,忽略自身是不是定位元素,如果父级是定位元素,那么距离是到父级的距离,如果不是定位元素,则是到外边框的距离。
- offsetTop:距离上边位置的值 规则同上
- offsetWidth:元素本身的宽,不管内容 元素的尺寸
- offfsetheight:元素的高,不管内容 元素的尺寸
offsetParent返回最近的有定位的父级,如果没有,返回body,body.offsetParent返回null
1、没有脱离标准的文档流
offsetLeft:父级元素margin+父级元素padding+父级元素的border+自己的margin
2、脱离了标准文档流
主要是自己的left和自己的margin
(二)scroll系列:卷曲--滚出去
-
scrollWidth 元素中内容的实际宽度,如果没有内容,就是元素的宽度
-
scrollHeight 元素中内容的实际的高,如果没有内容,就是元素的高
-
scrollTop:向上卷曲出去的距离,有了滚动条之后,从可视区无法看到部分的高度,也就是超出部分的高度
-
scrollLeft:向左卷曲出去的距离,有了滚动条之后,从可视区无法看到部分的宽度,也就是超出部分的高度
-
兼容性的问题:(都是查看滚动条的滚动距离)
-
window.pageXOffset或者window.pageYOffset IE8及IE8以下不兼容;
-
document.body.scrollLeft/Top
document.documentElement.scrollLeft/Top (ie8和ie8以下的浏览器兼容,但是具体那个好使是没有定论的,有可能ie7上面的好使,也有可能下面的好使,有一个规律,在一个浏览器上只要上面的有值,那么下面的一定为零,反之下面的有值,上面的就没值,相加之后就可以兼容ie8和ie8以下的浏览器了)
-
(三)client系列:可视区
- clientWidth:可视区域的宽(没有边框)边框内部的宽度
- clientHeight:可视区域的高(没有边框)边框内部的高度
- clientLeft:左边边框的宽度
- clientTop:顶部边框的宽度
- clientX:可视区域的橫坐标
- clientY:可视区域的纵坐标
查看可视区窗口的尺寸(可以看到的html代码,能看到的部分,不包括浏览器的导航栏,控制台等,页面的缩放会影响到可视区窗口的尺寸)
-
window.innerWith/innerHeightw3c标准的。 ie8及ie8以下不兼容 -
ie8及ie8以下兼容
document.documentElement.clientWidth/clientHeight标准模式下(有<!DOCTYPE html>这行的就是标准模式,没有就是怪异模式/混杂模式 向后兼容),任意浏览器都兼容document.body.clientWidth/clientHeight适用于怪异模式下的浏览器
案例图片跟着鼠标 兼容代码的封装过程
(四)查看元素的几何尺寸
dom元素.getBoundingClientRect()得到一个对象包,里面有所选择元素的几乎一切信息,和offset系列功能一样,没offset系列好用。
- 兼容性很好;
- 该方法返回一个对象,对象里面有left, top, right, bottom等属性。left和top代表该元素左上角的X和Y坐标,right和bottom代表元素右下角的X和Y坐标。
- height和width属性老版本IE并未实现。
- 返回的结果不是实时的;
(五)让滚动条滚动
window.scroll()window.scrollTo()- window.scrollBy()
- 三个方法功能类似,用法都是将x,y坐标传入,即实现让滚动轮滚动到当前位置。
- 区别:scrollBy()会在之前的数据基础之上做累加
十、闭包
(一) [[scope]]
每个javascript的函数都是一个对象,对象中有些属性可以访问,但是有些不可以,这些属性仅供javascript引擎存取,scope就是其中一个,scope就是我们所说的作用域,其中存储了运行期上下文的集合,就是ao和go
(二) 作用域链
scope中存储的运行期上下文对象的集合,这个集合呈链式链接,把这个链式连接叫做作用域链
(三) 运行期上下文
当函数执行时,会创建一个称为执行期上下文的内部对象,(AO/GO),一个执行期上下文定义了一个函数的执行环境,函数执行时,对应的执行上下文都是独一无二的,多次调用函数,会创建多个执行上下文,当函数执行完毕,所产生的执行上下文被销毁
查找变量:从作用域链的顶端依次向下查找
当一个函数a被定义的时候 [[scope]]存储的第0位的是GO
当一个函数a被执行的时候 [[scope]]存储的第0位就变成了AO,第一位就变成了GO。


(四) 闭包
当内部函数被保存到外部时,将会生成闭包,闭包会导致原有作用域不被释放,造成内存泄露
两个函数嵌套,把里面的函数保存到了外部全局,就行成了装饰,它保存着父级函数的作用域AO
给一个标签绑定一个事件,相当于是将事件外理函数保存在了js之外的标签属性上,那么也就行成了闭包,如果正好这个事件外理函数在一个循环的函数中,那么他就会保存着父级函数的AO,AO对象存储着变量的值,这个值会随着循环更新,停在循环最后一个值上,如果想要拿到循环时候的每个值,就需要在事件函数的外面加一个立即执行函数,这样事件函数就会存储立即执行函数的AO对象,而这个AO里的变量属性是每次跟着循环得到的值,这个值是不会变的
只要是运行期的上下文被保存到了函数的外部,都行成了闭包
(五)闭包的作用
-
实现共有变量
- 函数累加器
-
可以作缓存(存储结构)
-
实现封装,属性私有化
-
模块化开发,防止污染全局变量
十一、原型
定义:原型是function对象的一个属性,它定义了构造函数制造出的对象的公共祖先,通过该构造函数产生的对象,可以继承该原型的属性和方法,原型也是对象,没有属性和方法之前就是一个只有constructor属性值是函数本身的一个对象。
- 利用原型的特点和概念可以提取公共属性。
- 对象如何查看原型: 隐式属性
__proto__ - 对象如何查看对象的构造函数 constructor
- 访问一个对象的属性时,先在基本属性中查找,如果没有,再沿着
__proto__这条链向上找,这就是原型链。 - 如何区分一个属性到底是基本的还是从原型中找到的呢?——hasOwnProperty,特别是在for…in…循环中,一定要注意

- 原型的修改和删除,不能通过对象.属性的方式修改和删除,必须用
构造函数.prototype.属性的方式修改,删除也不能使用delete 对象.属性的方式删除,要使用delete 构造函数.prototype.属性的方式删除。
- 另一种写法, 这种方式和函数.prototype.属性 = 值 修改对象,一种是直接修改引用值。
- 绝大多数的对象最终都会继承自object.prototype,但是有一个例外,object.create(原型/null),使用null参数创建的对象是个例外。
总结:
- 任何函数都具有一个
prototype属性,prototype里有constructor属性 - 构造函数的
prototype对象默认都有一个constructor属性,指向prototype对象所在函数,可以修改
-
通过构造函数得到的实例对象内部会包含一个指向构造函数的
prototype对象的指针__proto__ -
所有实例都直接或间接继承了原型对象的成员
-
Object.create(原型)
-
undefined,null没有原型
-
call/apply 改变this指向 区别后面传的参数的形式不同。借用别人的函数,实现自己的功能
函数()=函数.call(参数1,参数2...) 参数1,改变this指向的对象,参数2以后正常的函数参数
函数()=函数.apply(参数1,[参数2...]) 参数1,改变this指向的对象,函数的正常参数要放在一个数组中。
区别:
call:需要把实参按形参的个数传进去
applay:需要传一个arguments
应用:
十二、继承
传统形式:原型链继承
过多的继承了没用的属性
借用构造函数
不能继承借用构造函数的原型
每次构造函数都要多走一个函数
共享原型
不能随便改动自己的原型
当Son的原型想增加东西的时候,势必造成Father的原型上也增加了东西
圣杯继承
十一、this指向
全局作用域里this指向window
call/apply可以改变函数运行时的this指向
普通函数中的this:window 相当于是window.函数(),(函数预编译过程中,this指向window)
对象方法中的this: 当前的实例对象;
定时器方法中的this:也是window
构造函数中的this:当前的实例对象
原型对象方法中的this:当前的实例对象;
jquery为什么能连续的点方法或属性,因为return this。
当new一个函数时,相当于是在函数里创建了一条下面的语句
var this = Object.create(函数.prototype)准确的来说是在这个对象里添加了this对象,而这个this对象里添加了__proto__:函数.prototype。
十二、try catch
不抛出错误,后续代码继续执行(try里的代码出错的那行以下不会再执行),把错误放到catch的参数e里。
e.name 的六种对应的信息:
1、EvalError:eval()的使用与定义不一致;
2、RangeError:数值越界
3、ReferenceError: 非法或者不能识别的引用数值 ,变量、函数 没声明就使用,
4、SyntaxError:发生语法解析错误;
5、TypeError:操作类型错误;
6、uRLError:URL处理函数使用不当;
十三、es5严格模式
不使用严格模式的情况下是:基于es3的+es5的新增方法,使用的,出现冲突,以es3的方法为主。
严格模式就是出现冲突的时候以es5的方法为主
"use strict" 写在逻辑的最顶端。全局的。局部的,写在函数代码的最顶端
不再兼容e3的一些不规范的语法,使用全新的es5规范
两种用法:
1、全局严格模式
2、局部函数内严格模式(推荐)
就是一行字符串,不会对不兼容严格模式的浏览器产生影响。
严格模式下,不支持with(改变作用域链,改变AO), arguments.callee, func.caller 变量赋值前必须声明,(隐式全局变量不能用了)局部this必须被赋值(Person.call(null/undefined,赋什么就是什么),拒绝重复属性和参数。
十三、小技巧工具方法
1、实现jquery连续调用方法
2、自定义的typeof
自定义的数组去重方法
性能
循环里添加匿名函数效率低,要改成命名函数,放在循环的外面,如果不是循环的方式添加事件,推荐使用匿名函数
异步加载js
js加载的缺点:加载工具方法没必要阻塞文档,js加载会影响页面效率,一旦网速不好,那么整个网站将等待js加载而不进行后续的渲染等工作。
有些工具方法需要按需加载,用到再加载,不用不加载
异步加载的三种方案:
1、defer异步加载,但是要等到dom文档全部解析完才会被执行,只有ie能用,也可以将代码写到内部
script type="text/javascript" src="tools.js" defer="defer"></script>
2、async w3c标准,异步加载,加载完就行,async只能加载外部脚本,不能把js写在script标签里。
script type="text/javascript" src="tools.js" aysnc="aysnc"></script>
3、执行时也不阻塞页面。
4、创建script,插入到dom中,加载完毕后callBack。
JavaScript之js加载时间
在js加载开始的时候,浏览器会记录js执行的这段过程。
在这里我们说一下两个事件的区别:DOMContentLoaded和load
浙公网安备 33010602011771号