根据尚学堂和尚硅谷的javascript教学视频所记录的笔记
壹、JavaScript基础
一、JavaScript的简介
1、起源
JavaScript诞生于1995年,它的出现主要是用于处理网页中的前端验证。
2、简史
- JavaScript是由网景公司发明,起初命名为LiveScript,后来由 于SUN公司的介入更名为了JavaScript。
- 1996年微软公司在其最新的IE3浏览器中引入了自己对JavaScript的实现JScript。
- 于是在市面上存在两个版本的JavaScript,一个网景公司的 JavaScript和微软的JScript。
- 为了确保不同的浏览器上运行的JavaScript标准一致,所以几 个公司共同定制了JS的标准名命名为ECMAScript。
3、实现
ECMAScript是一个标准,而这个标准需要由各个厂商去实现。 不同的浏览器厂商对该标准会有不同的实现
Chrome的v8实现方法是最快的。
我们已经知道ECMAScript是JavaScript标准,所以一般情况下这两个词我们认为是一个意思。 但是实际上JavaScript的含义却要更大一些。 一个完整的JavaScript实现应该由以下三个部分构成:
JavaScript是一种轻量级的脚本语言,可以部署在多种环境,最常见的部署环境就是浏览器。所谓“脚本语言”,指的是它不具备开发操作系统的能力,而是只用来编写控制其他大型应用程序的操作方法。
JavaScript的核心部分相当精简,只包括两个部分:
基本的语法构造(比如操作符、控制结构、语句)
标准库(就是一系列具有各种功能的对象比如Array、Date、Math等)。
除此之外,还有提供的额外API可以分成三大类:浏览器控制类、DOM类、Web类。
Javascript还拥有非常广泛的使用领域:
(1)浏览器的平台化(各个浏览器都支持)
(2)网页前端开发
(3)网页后端开发
(4)跨移动平台
二、JavaScript的基础知识
1、字面量:
字面量:英语叫做literals,有些书上叫做直接量。看见什么,它就是什么。我们先来学习数字的字面量,和字符串的字面量。剩余的字面量类型,我们日后遇见再介绍
- 数字字面量:直接数字
- 数字的字面量可以有三种进制:
-
10进制:普通的数字就是十进制
2进制:0b开头
8进制:如果以0开头、或者以0o开头、或者以0O开头的都是八进制,八进制只能用0~7来表示
16进制:如果以0x开头的都是十六进制。
-
- 数字的字面量可以有三种进制:
- 字符串字面量:直接输出字符串(用双引号或者单引号)
2、javascript的命名规范
- JavaScript语言的标识符对大小写敏感,所以a和A是两个不同的标识符。
-
首字母可以是任意字母以及美元符号和下划线。剩余可以是任意字母,美元符号,下划线和数字(不能使用数字来当做命名的首位)
-
不能使用javascript中的关键字(保留字)来命名变量
eg: arguments、break、case、catch、class、const、continue …… -
常用命名方式:驼峰命名法(首字母大写,其余字母小写)
3、Javascript的变量类型
Javascript中有六大数据类型,这六种数据类型也就是我们声明变量的类型。
- number 数字类型
- JS中所有的数字都是number类型的,不在细分为整形int、浮点型float这些乱七八糟的东西。
number类型的东西:所有数字(不分正负、不分整浮、不分大小、不分进制)、Infinity、NaN。 - number的最大数 Number.Max_Value(1.7976931348623157e+308) number如果超过了最大值则会返回一个 infinity (infinity 是一个字面量 使用 typeof检验infinity返回的也是 Number ,-infinity则相反)
- Number.Min_Value(5e-324):大于0的最小值。
- NaN:字面意思是 not a Number,同样它也是字面量,且用 typeof 检验返回Number。
- JS中所有的数字都是number类型的,不在细分为整形int、浮点型float这些乱七八糟的东西。
- string 字符(串)类型(单引号,双引号)
- boolean 布尔类型
- null 空类型
- null类型表示数据类型存在,但是并没有给变量(对象)赋值。一般null类型用于对象类型的初始化。如果变量(对象)的值为null,并不代表变量(对象)没有类型
- undefined 未定义类型
-
Undefined类型表示数据类型未知或者存在类型错误。如果变量的值为undefined,并不代表变量没有类型!
- undefined类型和null类型在页面中表现的效果是相同的,但是undefined用于变量类型,而null用于对象类型。两者必须不能混用!!!!
-
- object 对象类型
-
对象由花括号分隔。在括号内部,对象的属性以名称和值对的形式 (name : value) 来定义。属性由逗号分隔: var person={firstname:"Bill", lastname:"Gates", id:5566}; 上面例子中的对象person有三个属性:firstname、lastname 以及 id。 ps:空格和折行无关紧要。声明可横跨多行: var person={ firstname : "Bill", lastname : "Gates", id : 5566 }; 对象属性有两种寻址方式(获取对象属性所对应的值的方式): name=person.lastname; name=person["lastname"];
-
4、javascript运算符简介
- typeof 获取当前变量类型运算符(特殊)
- = 赋值运算符
- == 简要比较运算符(忽略变量类型)
-
var number1 = 10; var string1 = “10” console.log(number1==string1);//true
-
- === 标准比较运算符(计算变量类型)
5、注释
- 单行注释://
- 多行注释:/* … */
- 文档注释:/** … */
ps:不要在使用html中的注释方式来注释js的代码了,两者是不同的。
pss:虽然快速注释的快捷键是一样的,但是需要引起注意。
6、运算符
- 算数运算符
-
加法运算符:x+y
减法运算符:x - y
乘法运算符:x * y
除法运算符:x / y
余数运算符:x % y
自增运算符:++x 或者 x++
自减运算符:--x 或者 x--
-
- 赋值运算符
- x+=y //相当于x= x+y
x-=y //相当于x= x-y
x*=y //相当于x= x*y
x/=y //相当于x= x/y
x%=y //相当于x= x%y
- x+=y //相当于x= x+y
- 比较运算符
-
x==y //判断是否相等(忽略变量类型)
x===y //判断是否严格相等(计算变量类型)
x!=y //判断是否不相等(忽略变量类型)
x!==y //判断是否严格不相等(计算变量类型)
x<y //判断是否小于
x<=y //判断是否小于或者等于
x>y //判断是否大于
x>=y //判断是否大于或者等于
-
- 逻辑运算符
-
非运算符(!)
表达式的值为假的时候,运算结果为真 -
与运算符(&&)
当运算符两端的表达式值均为真时,运算结果为真,否则为假 -
或运算符(||)
当运算符两端的表达式值有一个为真,运算结果为真,都为假时结果才假
-
- 三目运算符
- 表达式1?表达式2:表达式3
7、流程控制语句
①、分支语句
- if条件语句
- if else条件语句
- if else if else条件语句
- switch语句
②、循环语句
- while循环
- do while循环
- for 循环
③、break和continue语句
8、强制类型转换——String
将其他格式转化为String
方法一:toString() 方法
null 和 undefined 没有 toString()方法,如果调他们的方法会报错。
方法二:String() 方法
将 null 转换为字符串 “null”,将undefined转化为字符串"undefined"
9、强制类型转换——Number
方法一:使用 Number()函数
1、如果字符串中有非数字,则转换为 NaN
2、如果字符串中是一个空串或者空格,则转化为 0
3、true = 1 , false = 0
4、null = 0 undefined = NaN
方法二:parseInt() parseFloat()
parseInt() 是将一个字符串有效的整数取出来然后转化为Number
10、强化转化为Boolean
除了 0 NaN 空串 null undefined 这五种情况是false,其余的都是true
三、字符串详解
1、字符串概述
定义:字符串就是用单引号或者双引号包裹起来的,零个或多个排列在一起的字符
强调1:字符串需要在一行内定义,分成多行会报错。但是如果必须分成多行,则在每一行的末尾使用反斜杠\作为连接符。
“you \
are \
so \
cute!”
强调2:也可以使用【(+)连接运算符】来连接多个字符串,模拟多行字符串。
2、字符串长度
- 测量字符串长度:length方法
- 字符索引:[]方法
- 获取指定位置字符:charAt()方法和charCodeAt()方法
- 字符串连接:concat()方法 现阶段和+作用相同
3、转义字符
常见转义字符有:
- \' 单引号
- \" 双引号
- \\ 反斜杠
- \n 换行
- \r 光标到首行
- \ttab (制表符)
\n \r <br />区别:
- \n 是换行,英文是New line,表示使光标下移一格
- \r 是回车,英文是Carriage return,表示使光标到行首
- <br /> 是浏览器换行
总结:\r\n表示源代码换行。 <br/>表示浏览器文字换行
4、字符串对象
语法:var newString = new String(‘Frankenstein’);
不要创建 String 对象。它会拖慢执行速度,并可能产生其他副作用:
5、字符串属性及方法
(1).length:返回字符串长度
(2).charAt(number):返回当前指定位置的字符
(3).charCodeAt:
(4).concat:连接字符串
(5).substring:截取字符串
作用是从num1位置开始截取,截止到num2位置结束之间的字符串。
语法:str.substring(num1,num2);
(6).substr:截取字符串(长度)
作用是从num1位置开始截取,num2表示要截取的字符串长度。
语法:str.substr(num1,num2);
(7).slice:截取字符串。
作用是从num1位置开始截取,num2表示截取结束的位置。
语法:str.slice(num1,num2);
substring、substr、slice三个方法第一个参数都表示字符串截取的开始位置。如果省略第二个参数,那么这三个方法表示 获取字符串本身一直到结束。
(8).indexOf:返回当前查找字符串的位置,如果没有返回-1
indexOf:查找一个字符串在另一个字符串的位置
语法:str.indexOf(‘subStr’);
(9).lastIndexOf:倒过来查找,没有找到返回-1
lastIndexOf:查找一个字符串在另一个字符串的位置
语法:str.lastIndexOf(‘subStr’);
indexOf和lastIndexOf还能接受第二个参数。
对于indexOf而言,表示从这个位置开始向后匹配。
而对于lastIndexOf而言,则表示从这个位置开始向前匹配。str.indexOf(‘subStr’,num);
str.lastIndexOf(‘subStr’,num);
(10).trim:去掉字符串两端的空格
trim()方法的作用是能够去掉字符串两端多余的空格。
语法:str.trim();
(11).toUpperCase和toLowerCase:大小写转换
toUpperCase方法能够把字符串中的英文字母全都转换成大写字母。
语法:str.toUpperCase();
toLowerCase方法能够把字符串中的英文字母全都转换成小写字母。
语法:str.toLowerCase();
(12).localeCompare:比较两个字符串大小
localeCompare方法的作用是根据本地的排序规则来进行比较。
如果计算结果大于0则表示str1大于str2。
如果计算结果等于0则表示str1等于str2。如果计算结果小于0则表示str1小于str2。
语法:str1.localeCompare(str2);
(13).match:返回一个指定字符串的数组
match方法的作用是查找原字符串是否匹配某个子字符串,返回结果是匹配的子字符串数组,如果没有找到则返回null。返回的数 组内容为:寻找的子字符串,子字符串位置和原字符串。
语法:str.match(substr);pa:match方法只能匹配到寻找到的第一个字符串。
(14).search:返回位置
search方法和match相似,都是查找子字符串在指定字符串中的位置。不同的的返回结果为下标。如果没有找到匹配串, 则返回 -1。
语法:str.search('subStr');
(15).replace:替换字符串
replace方法能够将【查找到的第一个指定字符串】替换成【目标字符串】。如果查找失败则不发生替换而是串 复制一份拷贝。
语法:str.replace(oldString,newString);ps:需要强调的是replace方法并不会对原本字符串产生任何影响,而是会生成一个新的字符串
(16).split:字符串切割,返回数组
split方法能够根据指定的符号将字符串进行分割,分割后的每一个子元素整合成一个数组返回。如果无法分割,那么返回的数组只有一个元素,这个元素就是字符串本身。
语法:str.split(symbol);
forEach方法(这个方法只支持在IE8及以上的浏览器)
<script>
var sz = ["艾希","盖伦","流浪","蛮王","赵信"];
/*
* 浏览器会在回调函数中传递三个参数
* 第一个参数:当前正在遍历的对象
* 第二个参数:正在遍历的元素索引
* 第三个参数:正在遍历的数组
*/
sz.forEach(function (value, index ,obj) {
console.log(value+"——"+index+"——"+obj);
});
</script>
6、javascript字符集
JavaScript使用Unicode字符集。也就是说,在JavaScript引擎内部,所有字符都用Unicode表示。
7、字符串Base64编码
Base64本身是一种加密方式,可以将任意字符转成可打印字符。
有时需要以文本格式传递二进制数据,那么也可以使用 Base64 编码。
而我们使用这种编码方法,主要不是为了加密,而是为了不出现特殊字符,简化程序的处理。
javascript中字符串提供了两个有关Base64编码的方法:
btoa():字符串或二进制值转为Base64编码
atob():Base64编码转为原来的编码encodeURIComponent():要将非 ASCII 码字符转为 Base64 编码
decodeURIComponent():将转码后的内容转为非ASCII内容
四、数组
1、数组的概念
数组(array)是按照一定顺序排列的一组值,每个值都拥有自己的编号,编号从0开始。整个数组用方括号来表示。
语法:var arr = [item1,item2,item3];
ps:item1、item2和item3是泛指,javascript中的数组元素可以是任何类型的数据。
2、数组的特点
- 数组的本质
- 数组的长度(arr.length)
- avascript中的数组元素可以是任何数据类型的。而在计算机中不同的数据类型数据是放在不同存储区的。在内存中的存储位置不连续的
- javascript数组在内存中的存储位置是不连续的,但是数组的下标是连续的
- length是一个可写属性。
如果设置length长度小于数组本身长度,那么多余元素舍弃。
如果设置length长度大于数组本身长度,那么缺少元素用空位补齐。
如果设置length长度不是合法数值,那么会报错Invalid array length
- 数组的遍历(for arr in arrs)
- 数组的空位
- 数组的'删除'(delete)
- var girlFriends = ['ZhangTianAi','LiuShiShi','SomeOne'];
delete girlFriends[1];
- var girlFriends = ['ZhangTianAi','LiuShiShi','SomeOne'];
3、数组的方法
(1)isArray:判断是否为数组
isArray方法是数组提供的用来专门判断当前对象是否为数组的方法。如果是数组返回true,否则返回false。
(2)valueOf:返回数组本身
valueOf方法归属于Object对象类型,作用是返回指定对象的原始值。在数组中作用是返回数组本身。(其他用法这里暂时不提)
语法:arr.valueOf()
(3)toString:将数组以字符串的形式返回
(4)push:向数组末尾追加数据,返回当前数组的长度
(5)pop:删除数组最后一个元素
(6)join:将数组转换为字符串,默认按逗号隔开
join方法能够以给定的参数做分隔符,将所有的数组元素组成一个字符串。如果不提供参数,默认使用逗号分隔。
语法:arr.join(separator)
(7)shift(): 在数组头部删除一个元素,并返回这个元素
(8)unshift():在数组头部添加一个元素,并返回添加元素后新数组的长度
(9)reverse():数组反转
(10)slice:数组截取
slice方法作用是能够根据指定的【起始点】和【结束点】来对数组进行截取,并生成一个新数组。新数组的内容是从起始下 标开始的元素到结束点下标的元素,但是不包括结束点下标的元素本身。
语法:arr.slice(index1,index2);ps:slice方法的参数可以是负值。-1代表最后一个元素,-2代表倒数第二个元素。
pss:如果只写一个参数,则表示从当前坐标开始截取一直到最后一个元素。
(11)splice:数组截取,并且可以插入新的元素(改变原数组)
splice方法和slice方法很相似,但是splice功能更强大一些。
splice方法的作用是在指定下标处截取一定长度的元素,再插入一些新元素,并将删除的元素构成一个新数组返回。splice方法会改变原本数组。语法:arr.splice(index,removeCount,addItem1,addItem2,…)
(12)sort:排序
按照Unicode编码来判断大小在进行排序,所以在比较的过程中发生错误。
var sz = [1,5,2,6,7,3,11];
sz.sort();
console.log(sz);
//它的排序结果 1, 11, 2, 3, 5, 6, 7
所以我们需要自己来编写排序。
var sz = [1,5,2,6,7,3,11];
/*
* 我们可以在 sort()中加入一个回调函数,来指定排序规则
* 回调函数中需要俩个形参,浏览器会分别使用数组的中的元素作为实参去调用回调函数
* 使用哪个元素调用不确定,但是肯定的是数组中的a一定在b前面
* - 浏览器会根据回调函数的返回值来觉得元素的顺序:
* 如果返回一个大于0的值,则元素会交换
* 如果返回一个小于0的值,则元素不会交换
* 如果返回一个等于0的值,则俩个元素相等,不交换
* */
sz.sort(function(a,b){
/* if(a>b)
return 1;
else if(a<b)
return -1;
else
return 0;*/
//简化
return a-b; //从小到大, 如果从大到小: return b-a;
});
console.log(sz);
(13)indexOf: 索引
(14)lastIndexOf: 反序索引
4、二维数组
如果数组的元素还是数组,那么我们就称外层数组是一个二维数组。
语法:var arr = [[item1,item2],[item3,item4]];
五、javascript的函数和对象
1、javascript对象
对象(object)是大括号定义的无序的数据集合,由键值对构成,键与值之间用冒号分隔,大括号末尾要使用分号表示对象定义结束。
对象是JavaScript的核心概念,也是最重要的数据类型。JavaScript的所有数据都可以被视为对象。此外,JavaScript 允许自定义对象。
语法:var obj = { key : value };
①、键名
键名也被称为属性(property),对象的所有属性都是字符串,所以加不加引号都可以。但是,如果属性不符合标识符的条件(比如第一个字符为数字,或者含有空格或运算符),则必须加上引号。
②、键值
键值是属性所对应的具体的值。javascript的对象的键值可以是任何数据类型。
var frank = {
name: "Frankenstein Add",
age: 18,
sex: "male"
ability: eat(); //eat()表示函数
};
ps:如果一个属性的值(ability)为函数,通常把这个属性称为“方法”。它可以像函数那样调用这个属性。
frank.ability();
③、对象的创建
- 直接使用大括号创建对象
- 使用new命令生成一个Object对象的实例
- 使用Object.create方法创建对象
ps:一般来说,第一种采用大括号的写法比较简洁,也是最常用的一种创建对象的写法。第二种采用构造函数的写法清晰地表示了意图,第三种写法一般用在需要对象继承的场合。
④、对象属性的读写
- 读取属性
- 语法:var obj = { key:value };
console.log( obj.key );
console.log( obj['key'] );
- 语法:var obj = { key:value };
- 写入属性
- 语法: var obj = {};
obj.key = value;
console.log( obj.key );
- 语法: var obj = {};
⑤、对象属性的操作
- 【Object.keys()】获取对象所有属性
- 【delete】删除一个属性( delete obj.property )
- 【in】检查对象是否包含一个属性( 'key' in obj )
- 【for in】遍历对象所有属性
- 【with】操作多个对象属性(已被禁用)
with(obj){
key1 = value1;
key2 = value2;
}
2、javascript函数
官方:函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块。
个人:函数是一组拥有某些特定功能的、能够被重复调用的、闭合代码块。(不权威)
语法:
function 函数名(函数参数1,函数参数2,..) {
函数内容语句//函数体
}
(1)闭包
闭包:能够读取其他函数内部变量的函数。
在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
闭包的最大用处有两个:
一个是可以读取函数内部的变量,
另一个就是让这些变量始终保持在内存中,即闭包可以使得它诞生环境一直存在
function changeNum(start) {
return function () {
return start++;
};
}
var inc = changeNum(5);
inc() // 5
inc() // 6
inc() // 7
*1.构造函数
构造函数是用于生成对线的函数,Object()就是一个构造函数
//创建一个构造函数
function MyClass(x,y) {
this.x = x;
this.y = y;
}
调用构造函数:
1)构造函数和普通的函数声明形式相同
2)构造函数通过 new 关键字来调用, new关键字会创建一个新的对象并返回
3)通过 new 关键字 调用构造函数内的this 引用引用了(被新生成的)对象
*2.call() 和 apply()
- 这俩个方法都是函数对象的方法,需要通过函数对象来调用
- 当对函数调用 call() 和 apply() 都会调用函数执行
- 在调用 call() 和 apply() 可以将一个对象指定为第一个参数,此时这个对象会成为函数执行时的this
- call() 方法可以将两个实参在对象之后一次传递
- apply() 方法需要将参数封装在一个数组中统一传递
六、内置对象
1、内存
①、值传递和地址传递
原始数据类型(数值、字符串、布尔值)的内容传递方式是值传递(pass by value)
而复合数据类型(数组、对象、其他函数)的内容传递是地址传递(pass by reference)
②函数的同名参数
如果函数有同名的参数,则取最后出现的那个参数值。
function func(num, num) {
console.log(num);
}
func(1, 2) // 2
③、arguments对象
由于JavaScript允许函数有不定数目的参数,所以我们需要一种机制来在函数体内部读取所有参数。这就是arguments对象的由来。
arguments对象包含了函数【运行时】的所有参数。
arguments[0]就是函数的第一个参数,arguments[1]是第二个,以此类推。这个对象只有在【函数内部】才可以使用。
var func = function(one) {
console.log(arguments[0]);
console.log(arguments[1]);
console.log(arguments[2]);
}
func(1, 2, 3);
arguments对象除了可以读取参数,还可以为参数赋值
④、eval函数
eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码。(eval命令的作用是,将字符串当作语句执行。)
语法:eval(string)
⑤、instanceof类型检测
typeof用来检测基本数据类型简直是神器,但是如果是引用数据类型,则需要使用instanceof操作符。
instanceof 用于判断一个变量是否某个对象的实例。
⑥、javascript垃圾回收机制
对于其他语言来说,如C,C++,需要开发者手动的来跟踪并管理内存。
而JS的垃圾回收机制使得JS开发人员无需再关系内存的情况,所有的内存分配以及回收都会由垃圾回收器自动完成,执行环境会对执行过程中占有的内存负责。
其原理就是找出那些不在被使用的变量,然后释放其所占有的内存。回收器一般是按照固定的时间间隔或者预设的时间进行处理的。
2、Math对象
①、Math对象属性:
- Math.E: 常数e。 // 2.718281828459045
- Math.LN2: 2的自然对数。// 0.6931471805599453
- Math.LN10: 10的自然对数。// 2.302585092994046
- Math.LOG2E: 以2为底的e的对数。// 1.4426950408889634
- Math.LOG10E: 以10为底的e的对数。// 0.4342944819032518
- Math.PI: 常数Pi。// 3.141592653589793
- Math.SQRT1_2: 0.5的平方根。// 0.7071067811865476
- Math.SQRT2: 2的平方根。// 1.4142135623730951
②、Math对象的方法
【Math.round()方法】:四舍五入
【Math.floor()方法】:返回小于参数值的最大整数。(向下取整)
【Math.ceil()方法】:返回大于参数值的最小整数。(向上取整)
【Math.abs()方法】:返回参数值的绝对值
【Math.max()方法】:返回最大的参数
【Math.min()方法】:返回最小的参数
【Math. pow()方法】:返回以第一个参数为底数、第二个参数为幂的指数值
【Math. sqrt()方法】:返回参数值的平方根。如果参数是一个负值,则返回NaN
【Math. log()方法】:返回以e为底的自然对数值。
【Math. exp()方法】: 返回常数e的参数次方。
【三角函数方法】
Math.sin方法返回参数的正弦
Math.cos方法返回参数的余弦
Math.tan方法返回参数的正切。
Math.asin方法返回参数的反正弦
Math.acos方法返回参数反余弦
Math.atan方法返回参数反正切
【Math. random()方法】:返回0到1之间的一个伪随机数。可能等于0,但是一定小于1。
③、Date对象
Date对象是JavaScript提供的日期和时间的操作接口。
在JavaScript内部,所有日期和时间都储存为一个整数。
这个整数是当前时间距离1970年1月1日00:00:00的毫秒数,正负的范围为基准时间前后各1亿天
同Math对象一样,javascript也为Date对象提供了很多内置的方法。
①、Date()函数
// 无论有没有参数,直接调用Date总是返回当前时间
②Date(日期字符串|日期参数)构造函数
Date对象是一个构造函数,对它使用new命令,会返回一个Date对象的实例。
【如果不加参数,生成的就是代表当前时间的对象。】
语法:var date1 = new Date();
【如果添加一个日期字符串作为参数,返回字符串所对应的时间。】
语法:var date2 = new Date("January 6, 2013");
一些其他合法的日期字符串写法
new Date(datestring)
new Date("2013-2-15")
new Date('2013/2/15')
new Date("2013-FEB-15")
new Date("FEB, 15, 2013")
new Date("FEB 15, 2013")
new Date("Feberuary, 15, 2013")
new Date("Feberuary 15, 2013")
new Date("15, Feberuary, 2013")
Sun Jan 06 2013 00:00:00 GMT+0800 (中国标准时间)
【如果添加日期参数,返回字符串所对应的时间。】
语法:var date2 = new Date(year, month, day, hours, minutes, seconds, ms)
使用日期参数时,年月必须写,其他则默认和可以省略,省略为0。
③、日期计算
两个日期对象进行减法运算,返回的就是它们间隔的毫秒数。
两个日期对象进行加法运算,返回的就是连接后的两个字符串。
var d1 = new Date(2000, 2, 1);
var d2 = new Date(2000, 3, 1);console.log(d2-d1);//2678400000
console.log(d2+d1);//Sat Apr 01 2000 00:00:00 GMT+0800 (中国标准时间)Wed Mar 01 2000 00:00:00 GMT+0800 (中国标准时间)
④、日期对象的get*系列方法
getTime():返回实例对象距离1970年1月1日00:00:00对应的毫秒数,等同于valueOf方法。
getDate():返回实例对象对应每个月的几号(从1开始)。
getDay():返回星期几,星期日为0,星期一为1,以此类推。
getYear():返回距离1900的年数。
getFullYear():返回四位的年份。
getMonth():返回月份(0表示1月,11表示12月)。
getHours():返回小时(0-23)。
getMilliseconds():返回毫秒(0-999)。
getMinutes():返回分钟(0-59)。
getSeconds():返回秒(0-59)。
贰、javascript DOM
1、DOM Documen节点
DOM全称为Document Object Model,即文档对象模型。它是一套用来管理控制html文档的规则。而Document节点则是一种具象化的表现形式。假设我们把整个html文档看成是一个对象,那么这个对象就是Document节点。而我们如何操作控制这个对象的标准,就是DOM。
ps:dom中规定html页面中的所有元素都是节点。
document节点又被叫做document对象。每个载入浏览器的 HTML 文档都会成为 document对象。document对象使我们可以从脚本中对HTML页面中的所有元素进行访问。document是html文档的根节点,每张网页都有自己的document节点。window.document属性就指向这个节点。也就是说只要浏览器开始载入HTML文档,这个节点对象就存在了,可以直接调用。
2、Document节点属性
javascript为document节点提供了很多属性方便我们更好地使用。相对用得比较多的有下面这些:
- doctype,documentElement,body,head:返回文档内部的某个节点。
- documentURL,URL,domain,lastModified,location,title,readyState:返回文档指定信息。
- anchors,forms,images,links,scripts:返回文档内部特定节点的集合。
1、doctype,documentElement,body,head:返回文档内部的某个节点。
①、【doctype】
对于HTML文档来说document对象一般有两个子节点,第一个子节点就是doctype。doctype节点是一个对象,包含了当前文档类型信息。如果网页没有声明DTD,该属性返回null。对于HTML5文档,doctype节点就代表<!DOCTYPE html>。
语法:document.doctype
②、【documentElement】
document.documentElement属性,表示当前文档的根节点。它通常是document节点的第二个子节点,紧跟在document.doctype节点后面。对于HTML网页,该属性返回HTML节点。但是对我们来说一般都是通过documentElement节点来访问页面当中的其他子节点。
语法:document.documentElement
③、【body】
body属性返回当前文档的body或frameset节点,如果不存在这样的节点,就返回null。这个属性是可写的,如果对其写入一个新的节点会导致原有的所有子节点被移除。但是我们暂时不作考虑,稍后讲过通过节点改写html页面后我们再来考虑。
语法:document.body
④、【head】
head属性返回当前文档的head节点。如果当前文档有多个head,则返回第一个。
语法:document.head
2、documentURI,URL,domain,lastModified,location,title,readyState属性
①、【documentURI】
documentURI属性返回当前文档的网址。 documentURI属性所有文档都具备。
语法:document.documentURI
②、【URL】
documentURI属性返回当前文档的网址。URL属性只有HTML文档才具备。只读
语法:document.URL
ps:IE浏览器不支持documentURI属性
pss:document.documentURI===document.URL//true
③、【domain】
domain属性返回当前文档的域名。
例如某张网页的网址是 http://www.example.com/hello.html ,domain属性就等于 www.example.com 。如果无法获取域名,该属性返回null。
语法:document.domain
④、【lastModified】
lastModified属性返回当前文档(网页)最后修改的时间戳,格式为字符串。
语法:document.lastModified
注意,lastModified属性的值是字符串,所以不能用来直接比较。如果想要比较两个文档谁的日期更新,需要用转成时间戳格式进 行比较。
if (Date.parse(doc1.lastModified) > Date.parse(doc2.lastModified)) {
// ...
}
ps:Date.parse方法能够将时间格式字符串转换成时间戳格式
⑤、【location】
location属性返回一个只读对象,提供了当前文档的URL信息。
返回完整的URL:document.location.href
返回当前遵守协议:document.location.protocol
返回当前页面域名+端口号:document.location.host
返回当前页面域名:document.location.hostname
返回当前页面端口号,如果不存在则返回空:document.location.port
返回当前页面在服务器中路径:document.location.pathname
返回当当前页面URL中的查询字符串:document.location.search
跳转到另一个网址:document.location.assign(‘http://www.google.com’)
location中有关的其他内容:
以下方法效果相同,都能够改变当前页面的url:
location.assign('传递一个url');
window.location = '传递一个url';
location.href = '传递一个url'; <常用>reload():重新加载当前显示的页面。
location.reload(false): // 优先从本地缓存重新加载
location.reload(true)://优先从服务器重新加载location对象的search属性代表URL的查询字符串(包括?)
// 查询字符串为 ?id=x&sort=name
var search = window.location.search;
search = search.slice(1); // 得到 'id=x&sort=name'
search = search.split('&'); // 得到数组 ['id=x', 'sort=name']
⑥、【title】
title属性返回当前文档的标题,该属性是可写的。
语法:document.title
document.title = '新标题';
⑦、【characterSet】
characterSet属性返回渲染当前文档的字符集,比如UTF-8、ISO-8859-1。
语法:document.characterSet
⑧、【readyState】
readyState属性返回当前文档的状态。
共有三种可能值:
加载HTML代码阶段(尚未完成解析)是“loading”,
加载外部资源阶段是“interactive”,
全部加载完成是“complete”。
if (document.readyState === ‘complete') {
console.log(‘当前网页已经加载完毕');
}
//但是很显然这种判断方式只能判断一次,如果页面在判断时没有加载完成,那么就无法确定页面的究竟何时加载完毕。因此为了解决这个问题,我们可以采用下列写法:
// 轮询检查
var interval = setInterval(function() {
if (document.readyState === 'complete') {
console.log('now web is loading complete!');
clearInterval(interval);
// ...
}
}, 100);ps:setInterval(code,millimSec)可以按照一定时间间隔重复调用代码块,时间间隔单位是毫秒。
3、anchors,forms,images,links,scripts:返回文档内部特定元素的集合。
这些集合都是动态的,原节点有任何变化会立刻反映在集合中。
【anchors】
anchors属性返回 网页中所有指定了name属性的a节点元素 。
【forms】
forms属性返回 网页中所有表单 。
【images】
images属性返回 网页中所有图片
【links】
links属性返回 网页中所有链接元素(即带有href属性的a标签)
【scripts】
scripts属性返回 网页中所有的脚本
3.Document节点操作页面元素
1、选中页面元素
①、【querySelector()】 IE8不支持getElementsByClassName() ,但是支持 querySelect();
方法返回匹配指定的CSS选择器的元素节点。如果有多个节点满足匹配条件则返回第一个匹配的节点。如果没有发现匹配的节点则返回null。
ps:querySelector是匹配的选择器,那么如果是选择器为id时参数应该是"#id名"
使用该方法会返回唯一的一个元素,如果满足条件的元素有多个,那么它会返回第一个元素。
document.querySelectorAll()
该方法和 querySelector() 用法类似,不同的是它会将符合条件的元素封装到一个数组里面,即使符合条件的元素只有一个,也会返回一个数组。
【getElementById()】返回匹配指定ID属性的元素节点
【getElementsByTagName()】返回所有指定标签的元素
【getElementsByClassName()】//返回符合指定类名的所有元素 (不支持IE8及以下浏览器)
【getElementsByName()】 用于选择拥有name属性的HTML元素
pss:必须保证在执行选中元素操作之前,元素已经被创建完毕!
2、 创建页面元素节点、属性
【createElement()】生成html元素节点
语法:document.createElement("标签名");
var newp = document.createElement(“p”);
document.body.appendChild(newp);
因为直接创建一个按钮根本没办法直观看到,因此通过.appendChild方式添加到body当中。.appendChild()方法的作用能够将代码创建的元素添加到指定位置。
但是这样创建的元素并没有内容,也不存在属性,在页面开发的过程中实用性是极差的。因此如果需要创建一个带有内容或者带有属性的元素就需要用到下面的两个方法来配合。【createTextNode()】生成文本节点,参数为所要生成的文本节点的内容
var newp = document.createElement(“p”);
var p_text = document.createTextNode(“这是p的文本节点内容”);
newp.appendChild(p_text);
document.body.appendChild(newp);
【createAttribute()】生成一个新的属性对象节点,并返回它var newp = document.createElement("p"); var p_text = document.createTextNode("here is p text Node");
newp.appendChild(p_text);
var p_style = document.createAttribute("style");p_style.value = "color:cyan;";
newp.setAttributeNode(p_style);
document.body.appendChild(newp);
3、操作页面元素属性
【元素节点特性方法getAttribute()、setAttribute()和removeAttribute() 】
操作Element节点的CSS样式,最简单的方法之一就是使用节点对象的getAttribute方法、setAttribute方法和removeAttribute方法,读写或删除HTML元素的style属性。
语法:getAttribute('属性名');
setAttribute('属性名','属性值');
removeAttribute('属性名');
【元素节点的style属性】
Element节点本身还提供style属性,用来操作CSS样式。style属性指向一个对象,用来读写页面元素的行内CSS样式。
元素的style对象对应元素的style属性,style对象中的样式与元素style属性中的样式名是一一对应的,但是需要一点点改写规则:
- 将横杠从CSS属性名中去除,然后将横杠后的第一个字母大写
- CSS属性名是JavaScript保留字的,在属性名之前需要加上字符串“css”
- style对象的属性值都是字符串,而且包括单位。
1、通过JS修改元素的的样式
语法:元素.style.样式名 = 样式值
Style属性设置的样式是行内样式,而行内样式有较高的优先级,所以会优先显示,如果在样式中写了 ! important 则此时样式会有更高的优先级,即使通过JS也不能修改样式,会导致JS修改样式失败,所以 尽量不要在样式里面添加 !important.
2、通过style读取元素的属性
语法:元素.style.属性
通过style设置和读取的都是内联样式, 无法读取样式表中的样式。
【元素节点的style属性的cssText写法】
style对象的cssText属性可以用来读写或删除整个style属性。因此刚才的写法可以改写成:
var divStyle = document.querySelector('div').style;
divStyle.backgroundColor = 'red';
divStyle.border = '1px solid black';
divStyle.width = '100px';
divStyle.height = '100px';
divStyle.cssFloat = 'left';
divStyle.cssText = 'background-color:red;border:1px solid black;height:100px;width:100px;';
ps:删除整个style属性可以用(divStyle.cssText='' '';)这种写法。
pss:cssText对应的是HTML元素的style属性,所以不用改写CSS属性名
【元素节点的style属性方法setProperty()、getPropertyValue()和removeProperty()】
style对象提供了三个方法来读写行内css规则:
- setProperty(propertyName,value):设置某个CSS属性。
- getPropertyValue(propertyName):读取某个CSS属性。
- removeProperty(propertyName):删除某个CSS属性。
3、获取元素节点的子节点(通过具体的元素节点调用)
1. getElementsByTagName() 方法
返回当前节点的指定标签名后代节点
2. childNodes 属性
表示当前节点的所有子节点(包含文本节点)
注:在 IE8及以下的浏览器中,不会将空白文本当做子节点。
3. firstChild 属性
获取元素的第一个子节点(包括文本节点)
firstElementChild 获取当前元素的第一个子节点(不包括文本节点) but IE8及以下浏览器不支持
4. lastChild 属性
4、获取元素节点的兄弟节点(通过具体的元素节点调用)
1. parentNode 属性
2. previousSibling 属性 有可能会获取到文本节点。 previousElementSibling 可以 但是 IE8及以下浏览器不支持
3. nextSibling 属性 同上
4.获取元素的属性
1、currentStyle 只有IE支持
语法:元素.currentStyle.样式名
它可以读取当前元素正在显示的样式,如果当前模块没有设置样式,那就读取它的默认值。
2、getComputeStyle IE8及其以下浏览器不支持
这个方法是 Window的方法可以直接使用,
需要俩个参数:
第一个参数:要获取样式的元素。
第二个参数:可以传一个伪元素,但一般都传null
该方法会返回一个对象,对象中封装了当前元素所对应的样式,可以通过 对象。样式名 来读取样式,如果读取的样式没有设置,则会获得真实的值,而不是默认值。 比如:没有设置 width 他不会获取到 auto ,而是获取到一个长度。
我们可以写一个函数,兼容IE8及以下浏览器
//定义一个函数,获取元素的样式, 兼容 IE8及以下浏览器
//obj 元素 name :需要获取的属性
function getStyle(obj,name){
if(window.getComputedStyle)
return getComputedStyle(obj,null)[name]
else
return obj.currentStyle(name);
//简化
// return window.getComputedStyle ? getComputedStyle(obj,null)[name] :obj.currentStyle(name);
}
5、其他的样式相关的属性
注意:以下样式都是只读的
clientHeight
- 元素的可见高度,指元素的内容区和内边距(padding)的高度
clientWidth
- 元素的可见宽度,指元素的内容区和内边距(padding)的宽度
offsetHeight
- 整个元素的高度,包括内容区、内边距、边框
offfsetWidth
- 整个元素的宽度,包括内容区、内边距、边框
offsetParent
- 当前元素的定位父元素
- 离他最近的开启了定位的祖先元素,如果所有的元素都没有开启定位,则返回body
offsetLeft
offsetTop
- 当前元素和定位父元素之间的偏移量
- offsetLeft水平偏移量 offsetTop垂直偏移量
scrollHeight
scrollWidth
- 获取元素滚动区域的高度和宽度
scrollTop
scrollLeft
- 获取元素垂直和水平滚动条滚动的距离
判断滚动条是否滚动到底
- 垂直滚动条
scrollHeight - scrollTop = clientHeight
- 水平滚动
scrollWidth - scrollLeft = clientWidth
叁、javascript Node(节点)
一、Node概述
【DOM】
DOM是文档对象模型的简称。它的基本思想是:
把结构化文档解析成一系列的节点,再由这些节点组成一个树状结构(DOM Tree)。
所有的节点和最终的树状结构,都有规范的对外接口,以达到使用编程语言操作文档的目的(比如增删内容)。
所以,DOM可以理解成文档的编程接口。
【Node】
node是DOM的最小组成单位,一个文档的树形结构就是由各种不同类型的节点组成。
对于HTML文档,node主要有以下六种类型:
二、Node属性
- 通用属性:nodeName、nodeType
- 返回当前node的相关节点属性:ownerDocument、nextSibling,previousSibling,parentNode,parentElement
- 返回node内容属性:textContent,nodeValue
- 返回当前node子节点相关属性:childNodes,firstChild,lastChild
1.通用属性:nodeName、nodeType
nodeName属性返回节点的名称,nodeType属性返回节点的常数值
类型 | nodeName | nodeType |
DOCUMENT_NODE | #document | 9 |
ELEMENT_NODE | 大写的HTML元素名 | 1 |
ATTRIBUTE_NODE | 等同于Attr.name | 2 |
TEXT_NODE | #text | 3 |
DOCUMENT_FRAGMENT_NODE | #document-fragment | 11 |
DOCUMENT_TYPE_NODE | 等同于DocumentType.name | 10
|
2、返回当前node的相关节点属性:ownerDocument、nextSibling,previousSibling,parentNode,parentElement
【ownerDocument】
ownerDocument属性返回当前节点所在的顶层文档对象,即document对象。
ps:document对象本身的ownerDocument属性,返回null。
【nextSibling】
nextSibling属性返回紧跟在当前节点后面的第一个同级节点。如果当前节点后面没有同级节点,则返回null。
var el = document.getElementById('div-01').firstChild;
var i = 1;while (el) {
console.log(i + '. ' + el.nodeName);
el = el.nextSibling;
i++;
}
上面代码遍历div-01节点的所有子节点。
ps:从上述代码中能够得到的是,该属性还包括文本节点和空白节点。因此如果当前节点后面有空格,该属性会返回一个文本节点,内容为空格。
【previousSibling】
previousSibling属性返回当前节点前面的第一个同级节点。如果当前节点前面没有同级节点,则返回null。
ps:对于当前节点前面有空格,则previoussibling属性会返回一个内容为空格的文本节点。
pss:回车也算是文本节点
【parentNode】
parentNode属性返回当前节点的父节点. 如果当前节点没有父节点,则返回null(document节点)。
ps:一般情况下,一个节点的父节点只可能是三种类型:element节点、document节点和documentfragment节点。
【parentElement】
parentElement属性返回当前节点的父元素节点。 如果当前节点没有父节点,或者父节点类型不是Element节点,则返回null。
ps:parentElement很早是ie所独有的属性,其能实现的功能parentNode都能够实现。可以说parentNode是parentElement的标准版本。
3、返回当前node的内容的属性:textContent,nodeValue
【textContent】
textContent属性返回当前节点和它的所有后代节点的文本内容。
【nodeValue】
nodeValue属性返回或设置当前节点的值,格式为字符串。
但是nodeValue只对Text节点、XML文档的CDATA节点有效,其他类型的节点一律返回null。
因此,nodeValue属性一般只用于Text节点。对于那些返回null的节点,设置nodeValue属性是无效的。
4、返回当前节点的子节点的属性:childNodes,firstChild,lastChild
【childNodes】
childNodes属性返回一个节点集合(NodeList),节点集合中包括当前节点的所有子节点。
需要指出的是,除了HTML中的元素节点之外,该属性返回的还包括Text节点和Comment(注释)节点。
如果当前节点不包括任何子节点,则返回一个空的NodeList集合。
由于NodeList对象是一个动态集合,一旦子节点发生变化,立刻会反映在返回结果之中。
var ulNodes = document.querySelector('ul').childNodes;
【firstChild】
firstChild属性返回当前节点的第一个子节点,如果当前节点没有子节点,则返回null。需要指出的是,除了HTML元素子节点,该属性还包括文本节点和空白节点。
【lastChild】
lastChild属性返回当前节点的最后一个子节点,如果当前节点没有子节点,则返回null。
三.Node的方法
- appendChild(),hasChildNodes()
- cloneNode(),insertBefore(),removeChild(),replaceChild()
- contains(),isEqualNode()
1、appendChild(),hasChildNodes()
【appendChild()】
appendChild()方法接受一个节点对象作为参数,将其作为最后一个子节点,插入当前节点
var p = document.createElement("p");
document.body.appendChild(p);
【hasChildNodes()】
hasChildNodes()方法返回一个布尔值,表示当前节点是否有子节点。
2、cloneNode(),insertBefore(),removeChild(),replaceChild()
【cloneNode()】
cloneNode()方法用于克隆一个节点。它接受一个布尔值作为参数,表示是否同时克隆子节点。默认是false,即不克隆子节点。
需要注意的是,克隆一个节点,会拷贝该节点的所有属性,但是会丧失addEventListener方法和on-属性(即node.onclick = fn)添加在这个节点上的事件回调函数。
【insertBefore()】
insertBefore方法用于将某个节点插入当前节点的指定位置。
它接受两个参数,第一个参数是所要插入的节点,第二个参数是当前节点的一个子节点,新的节点将插在这个节点的前面。
该方法返回被插入的新节点,根据情况不是必须创建变量来保存。
【removeChild()】
removeChild方法接受一个子节点作为参数,用于从当前节点移除该节点。
它返回被移除的节点,根据情况不是必须创建变量来保存。
【replaceChild()】
replaceChild方法用于将一个新的节点,替换当前节点的某一个子节点。
它接受两个参数,第一个参数是用来替换的新节点,第二个参数将要被替换走的子节点。它返回被替换走的那个节点。
var replacedNode = parentNode.replaceChild(newChild, oldChild);
3、contains(),isEqualNode()
【contains()】
contains方法接受一个节点作为参数,返回一个布尔值。
contains方法表示判断【参数节点】是否为【当前节点】的子节点。
【isEqualNode()】
isEqualNode方法返回一个布尔值,用于检查两个节点是否相等。
ps:所谓相等的节点,指的是两个节点的类型相同、属性相同、子节点相同。
四、HTML元素
html元素是网页的根元素,document.documentElement就指向这个元素。js中关于html元素也提供了一些相关的属性和方法来帮助我们更好的操作:
(1)视图窗口大小:clientWidth属性,clientHeight属性
(2)html元素大小:offsetWidth属性,offsetHeight属性
ps:clientWidth和clientHeight这两个属性返回的是视口(viewport)的大小,单位为像素。
pss:clientWidth和clientHeight在计算视图大小的时候不计算滚动条部分。
psss:window.innerWidth和window.innerHeight包括了滚动条的高度和宽度。
五、HTML内的元素
(1)元素位置相关属性:
offsetParent属性
offsetTop属性
offsetLeft属性
(2)获取元素对象的方法:
querySelector方法
querySelectorAll方法
getElementsByTagName方法
getElementsByClassName方法
(3)元素属性的相关方法:
hasAttribute()方法
getAttribute()方法
setAttribute()方法
removeAttribute()方法
1、元素位置相关属性
【offsetParent】
offsetParent表示获取距离【当前元素】的最靠近的、并且CSS的position属性不等于static的父元素。
<p id="p-id" style="position:relative;">
<span id="span-id">
<a href="#" id="a-id">test-a</a>
</span>
</p> var a = document.getElementById("a-id"); var a_parent = a.offsetParent; console.log(a_parent);//
很明显能看到结果是a的offsetParent是p而不是span。
【offsetTop、offsetLeft】
offsetTop:当前HTML元素左上角相对于offsetParent的垂直位移。
offsetLeft:当前HTML元素左上角相对于offsetParent的水平位移。
2、获取元素对象的方法
我们之前已经知道通过getElementById方法来获取页面中的任意元素,在这里我们再为大家介绍4中选择元素的方法。
- querySelector方法
- querySelectorAll方法
- getElementsByTagName方法
- getElementsByClassName方法
【querySelector、querySelectorAll】
这两个方法都是通过css选择器来获取页面中的指定元素对象。不同点在于
querySelector是获取单个元素,如果有多个则获取第一个。
querySelectorAll是获取所有符合条件的元素的数组。
【注意:querySelector系列方法与getElementsBy系列方法对比有什么不同?】
(i)两者的W3C标准不同
querySelector系列属于W3C中的Selectors API(JS)规范
getElementsBy系列则属于 W3C的DOM 规范。
(ii) 两者浏览器的兼容不同
getElementsBy系列基本能被所有浏览器支持。 querySelector系列则通常只有在考虑兼容性的时候才被提起(尽管两者功能近似)
(iii)接受参数不同
querySelector系列接收的参数是一个css选择器名。
getElementsBy系列接收的参数只能是单一的className、tagName 和 name。
(iv)返回值不同
querySelectorAll()返回的是一个静态节点列表(Static NodeList)
getElementsBy系列的返回的是一个动态节点列表(Live NodeList)。
querySelectorAll的返回值是一个静态的NodeList对象
getElementsBy系列的返回值实际上是一个动态的NodeList对象 。
需要注意的是,querySelector系列所接收的参数是必须严格符合css选择器规范的。所以下面这种写法将会出错。
var e1 = document.getElementsByClassName('1a2b3c');var e2 = document.querySelectorAll('.1a2b3c');
console.log(e1 && e1[0].className);console.log(e2 && e2[0].className);
3、 元素属性的相关方法
- hasAttribute()方法
- getAttribute()方法
- setAttribute()方法
- removeAttribute()方法
【hasAttribute】
hasAttribute()方法用来检测元素是否具有某些属性,但是IE8及其更早的版本并不支持本方法
语法:element.hasAttribute(attributename)
【getAttribute】
getAttribute()方法用来获取指定元素属性名的属性值。
语法:element.getAttribute(attributename)
【setAttribute】
setAttribute() 方法添加指定的属性,并为其赋指定的值。如果这个指定的属性已存在,则仅设置/更改值。
语法:element.setAttribute(attributename,attributevalue)
【removeAttribute】
removeAttribute()方法删除指定的属性。
语法:element.removeAttribute(attributename)
肆、javascript事件
一、事件概述
1、事件
事件:是可以被js检测到的行为,实质上是一种交互操作。
例如:我们可以给某按钮添加一个【onClick点击事件】,当用户对按钮发生点击时来触发某个函数。
事件的作用:
(1) 各个元素之间可以借助事件来进行交互
(2) 用户和页面之间也可以通过事件来交互
(3) 后端和页面之间也可以通过事件来交互(减缓服务器的压力)
ps:注意:事件通常与函数配合使用,当事件发生时函数才会执行。
2、 事件传播/事件传递/事件流
一个事件发生后,会在子元素和父元素之间传播(propagation)。这种传播分成三个阶段
- 第一阶段:从window对象传导到目标节点(上层传到底层),称为“捕获阶段”(capture phase)。
- 第二阶段:在目标节点上触发,称为“目标阶段”(target phase)。
- 第三阶段:从目标节点传导回window对象(从底层传回上层),称为“冒泡阶段”(bubbling phase)。
w3c规定:事件冒泡+事件捕获+事件真正的触发者等各个分支构成了js的事件机制。
ps:如没有特殊情况,均采用事件冒泡。
3、事件冒泡(Bubble):
所谓的事件冒泡就是事件向上传导,当后代元素上的事件被触发时,其祖先元素上的相同事件也会被触发
在开发中大部分的事件都是有用的
取消冒泡
元素.事件 = function(event){
event = event || window.event;
event.cancelBubble = true;
};
二.非IE浏览器中的【事件绑定】
1、 HTML事件
绑定操作发生在HTML代码中的事件,称为HTML事件。
语法:on+事件=‘函数();函数();函数();……‘
<div class="d1" οnclick="test1();test2()">
<div class="d2" οnclick="test2()"></div></div>
ps:HTML事件采用冒泡机制来处理事件。即
点击d2时会先执行d2的绑定事件(即执行test2函数)。
然后采用事件冒泡将事件传递给上一级DOM节点d1,然后d1执行自己的绑定事件。
pss:函数执行的顺序按照绑定事件时函数的顺序为准
HTML事件的移除方式:
元素.setAttribute('on+事件名',null);
HTML事件缺陷:
耦合性太强了,修改一处另一处也要修改。
当函数没有加载成功时,用户去触发事件,则会报错
2、 DOM0级事件
在js脚本中,直接通过【on+事件名】方式绑定的事件称为是DOM0级事件。
语法:元素.on+事件名 = function(){需要执行的语句;}
ps:以冒泡机制来处理事件,不存在兼容的问题
DOM0级事件的移除方式:
元素. on+事件名=null;
DOM0级事件缺陷:
一次只能绑定一个触发函数。如果同时绑定多个触发函数,则以最后一个为准。
3 、DOM2级事件
在js脚本中,通过addEventListener函数绑定的事件称为是DOM2级事件。
语法:元素.addEventListener(type,listener,useCapture)
type:事件类型。【没有on!没有on!没有on!】
listener:监听函数,绑定的函数
useCapture:是否使用捕获机制。如果不写,默认值为false
false:冒泡机制
true:捕获机制
注意:DOM2级事件可以绑定多个函数,执行顺序按照函数书写的顺序。
DOM2级事件的移除方式:
node.removeEventListener(type,外部函数名,useCapture)
ps:DOM2级事件中如果绑定函数为【匿名函数】则无法删除。能够删除的只能是外部函数。
pss:第三个参数默认可以不写,默认是false。但是如果删除的是捕获事件,则必须写为true才可以。
三、IE浏览器中的【事件绑定】
- HTML事件处理程序:等同于非IE
- DOM0级事件:等同于非IE
- DOM2级事件:
在js脚本中,通过attachEvent函数绑定事件
语法:元素.attachEvent(type,listener)
type:事件类型。【有on!有on!有on!】
istener:监听函数,绑定的函数
注意:如果绑定多个函数,按照函数书写的倒叙执行。
IE下DOM2级事件的移除方式:
元素.detachEvent(type,listener);
四、解决浏览器中关于【事件绑定】兼容性问题
由于【IE浏览器中的事件绑定】和【非IE浏览器中的事件绑定】方式方法都有所不同。所以单一的某种函数都不能完美解决不同浏览器下的方法绑定问题。
那么我们又应该如何面对在不同浏览器下【事件绑定】这个问题的解决方案呢?
以下为解决方案的思路。
绑定事件时:
如果能使用addEventListener方法绑定的,就采用本方法
否则采用attachEvent方法绑定
解绑事件时:
如果能采用addEventListener方法绑定的,就采用removeEventListener方法解绑
否则采用detachEvent方法解绑
var Event = { addEvent: function (ele, type, handler) {
if (ele.addEventListener) {ele.addEventListener(type, handler);}
else if (ele.attachEvent) {ele.attachEvent('on' + type, handler);}
else {ele['on' + type] = handler;}
},
removeEvent: function (ele, type, handler) {
if (ele.addEventListener) {ele.removeEventListener(type, handler);}
else if (ele.attachEvent) {ele.detachEvent('on' + type, handler);}
else {ele['on' + type] = null;} }
};
function test() {alert('点击事件');}
Event.addEvent(document.querySelector('div'), 'click', test);
五、.鼠标事件
js鼠标事件是指通过鼠标一系列操作(如进入,点击等)来触发的事件。
(1)鼠标事件类型
鼠标单击是触发:click
鼠标双击是触发:dblclick
鼠标按下时触发:mousedown鼠标抬起时触发:mouseup
鼠标移动时触发:mousemove鼠标移入时触发(不冒泡): mouseenter
鼠标移出时触发(不冒泡): mouseleave鼠标移入时触发(冒泡): mouseover
鼠标移出时触发(冒泡): mouseout
语法:元素.on+鼠标事件名称 = 调用函数
例如:d1.ondblclick = function () { console.log('这是d1');}
(2)鼠标事件原则
a.鼠标的基本事件默认采用冒泡传递
b.可以给一个元素添加多个不同的鼠标事件,不同的鼠标事件之间互不影响
c.mouseenter和mouseleave两个事件不冒泡触发。
六.文档事件
文档事件中主要是指添加给整个文档的事件。在这一类事件中,绝大部分并不需要用户主动去进行调用。而是通过文档的不同状态来进行自动执行。
(1)加载成功\失败事件:load\error
(2)当DOM加载完成时触发事件:DOMContentLoaded
(3)文档加载状态判断事件:readystatechange
(4)文档大小发生改变时的回调事件:resize
1、加载成功\失败事件:load\error
load事件指的是:节点加载成功时自动发生回调事件
error事件值得是:节点加载失败时自动发生的回调事件
语法: node.onload = func(){};
例如:
在head中为页面元素添加点击事件,通过文档的onload事件解决了
【因网页加载未完成,而导致的获取页面元素失败】的问题
window.onload = function () {var div = document.querySelector(‘div’);
div.onclick = function () {console.log('点击事件');};
}
元素加载失败时触发的操作,只需要给指定元素一个.onerror属性即可
var mylink = document.getElementsByTagName(“link”).item(0); mylink.onerror = function () {console.log('css文件加载出问题了');
};
2、当DOM加载完成时触发事件:DOMContentLoaded
DOMContentLoaded事件和load事件的区别是触发的时机不一样,先触发DOMContentLoaded事件,后触发load事件。
DOM文档加载的步骤为:
解析HTML结构。
加载外部脚本和样式表文件。
解析并执行脚本代码。
DOM树构建完成。 //DOMContentLoaded执行
加载图片等外部文件。
页面加载完毕。 //load执行
因此样式文件的加载会阻塞脚本的执行。
所以如果你把一个内部脚本<script>元素放在了一个<link>后面,如果页面没有完成解析则脚本不会触发,直到样式文件加载完成之后.(这种情况被称为文件阻塞)
3、文档加载状态判断事件:readystatechange
当document的readyState改变时触发这个事件(仅第二阶段)。
众所周知,document节点中拥有一个属性叫做readyState。其拥有三个可能值:
loading:加载DOM中
interactive:加载外部资源
complete:加载完成
而readystatechange事件正是在这个状态发生改变时调用的事件。
(5)文档大小发生改变时的回调事件:resize
window.onresize = function(){
console.log('width:'+document.documentElement.clientWidth);
console.log('height:'+document.documentElement.clientHeight);
};
但是美中不足的是,js中为了追求变化的敏感度。将resize事件的响应事件设置为了0。也就是说每一次的文档大小改变都会立即调调用本事件。
这就造成了【一次变化】却发生了【不止一次】的resize事件调用。
所以为了解决这个问题,我们可以采用一种延迟的写法来实现。
4【失去焦点事件blur】与【获得焦点事件focus】
焦点:js当前正在和用户发生交互的节点称为焦点。可以类比为人类目光汇聚的地方。
语法:获得焦点和失去焦点事件既可以使用DOM0绑定也可以使用DOM2绑定
注意:
这两个事件均不支持事件冒泡(只有当前节点发生调用)。
如果需要连续多次的触发,则需要使用DOM2级绑定事件中的捕获事件来达到。
5、滚动事件scroll
scroll事件会在【文档】或【元素】发生滚动操作时触发。
【文档发生滚动时】
属性scrollTop\scrollLeft表示文档滚动的距离:(没有单位)
IE:document.documentElement.scrollTop\Left 非IE:document.body.scrollTop\Left
(可以使用document.body.scrollTop||document.documentElement.scrollTop来解决兼容性)
//例:
window.onscroll = function () {
var top = document.body.scrollTop||document.documentElement.scrollTop;
var left = document.body.scrollLeft||document.documentElement.scrollLeft;
console.log('top:'+top+'left:'+left);
};
【元素发生滚动时】
元素发生滚动时并不存在兼容性的问题,但是需要有一个前提那就是:必须存在滚动条。
(元素的滚动条属性可以同过overflow:scroll/overflow-x:scroll/overflow-y:scroll来实现)
在元素发生滚动的时候,可以通过【元素.scrollTop/scrollLeft】获取到元素的位移距离。
例如:
var div = document.querySelector('div');
div.onscroll = function () {
console.log(div.scrollTop);
};
特别注意:
(1)刚刚我们提到的scrollTop属性和scrollLeft属性都是一个可读可写的属性。
(2)赋值时直接使用’=’即可,不需要加单位
(3)若赋的值大于【最大滚动距离】,则按照最大滚动距离为准
七.、键盘事件
1、 键盘事件种类
键盘事件是指当用户在操作键盘的时候会自动被触发的事件,通常有以下三种:
(1) keydown:用户按下任意键都可以触发这个事件。如果按住不放,事件会被连续触发。 .
(2) keypress:用户按下任意键都可以触发这个事件(功能键除外)。如果按住不放,事件会被连续触发
(3) keyup: 用户释放按键时触发
ps:键盘事件一般绑定在需要用户输入的元素上(例如input),但是由于键盘事件默认采用事件冒泡机制,因此将键盘事件直接绑定在body之上也是允许的。
2、 键盘事件中提供的属性
在键盘事件中可以通过event.keycode来获取按下按键的编码值。
input1.onkeydown = function () { console.log("down:"+event.keyCode); };
ps:因此我们可以通过这个属性来获取到,在页面中用户曾按下过哪些按键。
pss:常见的按键编码【回车:13】【backspace:8】
3、keydown和keypress事件的区别
(1)keyPress主要用来捕获:数字(包括Shift+数字的符号)、字母(包括大小写)、小键盘等能够显示在屏幕中的字符。但是不能对系统功能键(例如:后退、删除等,其中对中文输入法不能有效响应)进行正常的响应 而KeyDown和KeyUp通常可以捕获键盘除了PrScrn所有按键(这里不讨论特殊键盘的特殊键)
(2)捕获字符长度区别
KeyPress只能捕获单个字符
KeyDown和KeyUp可以捕获组合键。
(3)捕获字符大小写识别区别
KeyPress可以捕获单个字符的大小写
KeyDown和KeyUp对于单个字符捕获的KeyCode都是一个值,也就是不能判断单个字符的大小写。
(4)捕获字符数字区别
KeyPress不区分小键盘和主键盘的数字字符。
KeyDown和KeyUp区分小键盘和主键盘的数字字符。
4、特殊情况
PrScrn按键KeyPress、KeyDown和KeyUp都不能捕获。
上下左右等功能键的keydown、keyup都能获取keyCode,并且值相等
八.手机触摸事件
1、手机触摸事件
(1)touchstart:当手指触摸屏幕时触发;即使已经有一个手指放在了屏幕上也会触发。
(2)touchmove:当手指在屏幕上滑动时连续的触发。
(3)touchend:当手指从屏幕上移开时触发。
(4)*touchcancel:当系统停止跟踪触摸时触发。(如电话接入或者弹出信息,一般在这个操作中来做一些暂停游戏类的操作 或者点击通知)
ps:如非特殊说明,事件均为冒泡事件
pss:手机触摸事件必须使用dom2来进行绑定
psss:可以给一个元素添加多个触摸事件.
2、 【事件对象】的属性
事件对象,即【事件触发的时】用来保存【事件相关的所有信息的对象】。
事件对象基本都是系统为我们自动生成,不必手动创建。
(1)touches:表示当前跟踪的触摸操作的Touch对象的数组(当前屏幕上所有的触摸点列表)。
(2)targetTouches:特定于事件目标的Touch对象的数组(当前对象上所有的触摸点列表)。
(3)changeTouches:表示自上次触摸以来发生了什么改变的Touch对象的数组(涉及当前事件的触摸点列表)。
3、 【触摸对象】的属性
触摸对象,即【事件对象的touches属性】中的每一个元素。
一次触摸会创建一个触摸对象。
触摸对象中提供了很多属性方便我们获取和使用:
clientX:触摸目标在视口中的X坐标。
clientY:触摸目标在视口中的Y坐标。
identifier:表示触摸的唯一ID。
pageX:触摸目标在页面中的x坐标。
pageY:触摸目标在页面中的y坐标。
screenX:触摸目标在屏幕中的x坐标。
screenY:触摸目标在屏幕中的y坐标。
target:触摸的DOM节点坐标
九.this对象
概念:
this代表【函数运行时】【自动生成的】一个【用来指代函数调用者】的对象,this只能在函数内部使用。
根本原则:函数的调用者是谁,this就是谁
this对象的注意事项:
HTML 级事件:this指向window
DOM0级事件:this指向绑定事件的这个元素
DOM2级事件:this指向绑定事件的这个元素(非IE) this指向window(IE)
十、event事件
1、非IE
1、event对象
概念:当dom tree中某个事件被触发的时候,会同时自动产生一个用来描述事件所有的相关信息(比如出发事件的元素、或者是事件的类型)的对象,这个对象就是event(事件对象)。
获取方式:
(1)直接通过event来获取
(2)还可以通过函数传参数的形式来使用,一般而言我们使用【形参e或event】来代替
2、 event中常用的属性和方法
因为event对象是用来描述【发生的事件的信息】的,而event对象当中所提供的一系列属性和方法正是用来获取这些信息的途径。
【type 属性】
type属性用来获得【当前触发事件】的类型,此属性只读。
【bubbles 属性】
bubbles属性用来获得【当前触发事件的类型】是否冒泡,如果当前事件类型支持冒泡则返回true,否则返回false。
必须注意的是:bubbles属性指的是该事件是否冒泡。和事件处理机制无关!!!!
因为鼠标【点击事件】这个事件本身支持冒泡。
因此当存在点击事件被触发后,event对象的bubbles属性返回的就是true,表示当前事件支持冒泡。
但绝不是把这个事件以冒泡的形式继续传递下去!
【eventPhase 属性】
eventPhase:事件传导至【当前节点】时处于什么的状态。
1:事件处于捕获状态
2:事件处于真正的触发者
3:事件处于冒泡状态
【target 属性和 currentTarget 属性】
target:返回事件真正的触发者
currentTarget:返回事件的监听者(触发的事件绑定到了哪个节点,就返回谁)
【stopPropagation() 方法】
event对象中提供了一个名为stopPropagation的方法。用来阻止事件从当前节点传播到下一个节点。.
ps:stopPropagation方法虽然能够阻断事件的传播,但是并不会影响同一节点上的其他事件句柄。
【preventDefault() 方法】
event对象中提供了一个名为preventDefault的方法,用来取消当前节点的默认行为(譬如超级链接的点击跳转行为)。该方法没有返回值。
【cancelable() 方法】
event对象中提供了一个名为cancelable的方法,用来判断当前节点能否使用preventDefault方法来取消默认行为。如果可以则返回true,否则返回false。
2.IE
1、IE中的event对象与非IE下的区别
event对象在不同的浏览器下的区别:
(1)非IE下event的值默认为undefined,而IE中event的值默认为null。
(2)非IE下可以随意通过dom0或dom2中的参数来使用event,而IE中dom0级无法 使用传参的形式来使用event。(dom2可以)
ps:因为event本身是归属于window的一个属性,因此我们可以在函数中通过
var eve = e||window.event
来解决获取event对象的兼容性问题
2 、IE中的event对象的常用属性和方法
【srcElement 属性】
srcElement属性代表事件真正的触发者,等同于非IE下的target属性。
因此,为了在不同的浏览器下解决获取target的兼容性问题,可以采用如下的写法:
var target = eve.target || eve.srcElement;
【cancelBubble 属性】
cancelBubble属性用来阻止事件在当前节点上的冒泡行为。
作用类似于非IE下的stopPropagation方法。
语法:
event.cancelBubble = false;(默认值)
event.cancelBubble = true;(可以取消冒泡)
ps:stopPropagation方法表示阻断事件传递,而cancelBubble属性则仅阻断事件冒泡。
【returnValue 属性】
returnValue属性用来设置【是否取消当前节点的默认行为】
作用类似于非IE下的preventDefault方法
语法:
event.returnValue = false;(取消默认行为) event.returnValue = true;(默认值)
3、兼容性问题
通过对IE下event的方法和非IE的方法的介绍,能够感觉到两种情况的很多属性和方法大致都相同,只不过会在某些特殊方法上面存在不同的兼容性写法。因此我们可以提出一些同时满足不同浏览器兼容性的写法。
属性的兼容性写法我们已经说过:
var target = eve.target || eve.srcElement;
var eve = eve || window.event
方法的兼容性写法我们也可以仿照这个来进行编写。思路如下:
(1)因为两种情况下的event对象获取方式并不同,所以希望能够自定义一个对象来替代event对象的使用。
(2)因为想要自定义对象在功能上和系统event对象的方法相同,所以需要给自定义对象添加方法
4.event中的一些其他属性
(1)返回事件触发点距离视口的距离 e.clientX e.clientY
(2)返回事件触发点距离页面的距离e.clientx+滚过的距离 e.pageX e.pageY
ps:以上2个方法一个计算滚动条一个不计算滚动条
(3)返回事件触发点距离屏幕的距离 e.screenX e.screenY
(4)e.button:返回按下了鼠标的哪个键
非IE中 左中右代表数字为0 1 2
IE中 左中右代表数字为1 4 2
十一、鼠标滚轮事件
滚轮就是鼠标上的滚轮,它滚动的时候触发事件
oDiv.onmousewheel = function(event){
oDiv.innerHTML = event.wheelDelta;
}
onmousewheel就是鼠标滚动事件,mouse鼠标,wheel就是轮子。
event参数最最重要的事就event.wheelDelta属性,表示滚动的方向。这是浏览器的规定:
鼠标往上滚, 120
鼠标往下滚, -120
火狐浏览器滚轮事件
火狐浏览器不兼容,火狐使用自己的专用事件DOMMouseScroll ,并且这个事件只能通过标准的DOM2级的事件绑定方式添加。
oDiv.addEventListener("DOMMouseScroll",function(event){
oDiv.innerHTML = event.detail;
},false);
火狐添加的事件,是它自己的专门事件DOMMouseScroll,
表示滚动方向的事件的属性叫做event.detail。
detail就是细节的意思。反着的,滚动方向往上,-3;滚动方向往下,3。
function mousewheelhandler(event){
event = event || window.event; //→ 解决IE6、7、8和高级浏览器的不兼容
//Chrome、IE用的是event.wheelDelta;
var direction = 0;
if(event.wheelDelta){ //→ 解决火狐和其他浏览器的不兼容
direction = event.wheelDelta > 0 ? 1 : -1;
}else if(event.detail){
//火狐用的是event.detail;
direction = event.detail > 0 ? -1 : 1;
}
oDiv.innerHTML = direction;
return direction;
}
十二、多级联动
1.select元素的option创建方式:【var option = new Option(‘想要显示的内容’);】
2.select元素中添加option方式:【select.options.add(新创建的option);】
3.select元素清空所有的option方式:【select.options.length = 0;】
4.select元素改变时触发的事件:【select.onchange = function(){};】
5.select元素当前正在选中的option的序号:【select.selectedIndex】,从0开始。
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
省:<select name="sheng">
<option name="xuanze" value="请选择">请选择</option>
</select>
市:<select name="shi">
</select>
区:<select name="qu">
</select>
</body>
<script>
var sheng = document.getElementsByName("sheng")[0];
var shi = document.getElementsByName("shi")[0];
var shengArr =["陕西","山西","四川"];
var shiArr = [ ['西安','榆林','延安'],["大同","开封","河南"], ["成都","洒洒水","SaaS"]];
for(var i = 0;i<shengArr.length; i++){
var opt = new Option(shengArr[i]);
sheng.options.add(opt);
}
//情况列表所有元素
sheng.onchange= function () {
shi.options.length = 0;
for(var i = 0; i < shiArr[sheng.selectedIndex-1].length; i++){
var opt = new Option(shiArr[sheng.selectedIndex-1][i]);
shi.options.add(opt);
}
}
</script>
</html>
伍、HTTP BOM(window对象)
一.BOM的概念
1、 BOM
概念:BOM(Browser Object Document)即浏览器对象模型
关于BOM的说明:
(1)BOM提供了独立于内容 而与浏览器窗口进行交互的对象
(2)由于BOM主要用于管理窗口与窗口之间的通讯,因此其核心对象是window对象
(3)BOM由一系列相关的对象构成,并且每个对象都提供了很多方法与属性
(4)BOM缺乏一个统一的标准
JavaScript语法的标准化组织是ECMA
DOM的标准化组织是W3C [所有浏览器公共遵守的标准]
BOM是各个浏览器厂商根据dom在各自浏览器上的实现;[表现为不同浏览器定义有差别,实现方式不同]
ps:通常情况下如果提到了bom,一般指的都是window对象。
2 BOM和DOM的关系
根据上述两张导图能够得出结论:
(1)DOM通过document对象来访问、控制、修改html和xhtml等文档中的内容
(2)BOM通过 window 对象来访问、控制、修改浏览器中的内容
联系:BOM包含DOM。
浏览器提供用来访问的是BOM对象
从BOM对象可以访问到DOM对象
从而使javascript可以操作浏览器、并通过操作浏览器读取到文档的内容
区别:DOM描述了处理网页内容的方法和接口,即操作页面内部
BOM描述了与浏览器进行交互的方法和接口,即操作页面之间
二、window对象
1 window对象
概念:window对象是bom的具象化表现形式。
window和bom之间的关系就好比document对象和dom之间的关系一样:
bom相当于dom
window对象相当于document对象
ps:因为window对象是js中的顶级对象,因此所有定义在全局作用域中的变量、函数都会
变成window对象的属性和方法,在调用的时候可以省略window。例:
打开窗口 window.open(url); 【等价于open(url);】
关闭窗口 window.close(); 【等价于close();】
获取事件 window.event 【等价于event;】
获取文档 window.document 【等价于document】
2 window对象中常用的属性和方法
1、window.name
属性:
window.name是window对象的一个属性,默认值为空
特性:
window.name值在不同的页面(甚至不同域名)加载后依旧存在,
并且可以支持非常长的name值(2MB左右)
应用:
正是由于window.name属性拥有在不同页面保持存在的特性,
因此出现了一门叫做【跨域传输】的技巧。
而这个技巧的内部实现原理就是window.name的持久性的特性。
跨域传输案例:
2、window尺寸属性
window.outerHeight
window.outerWidth
这两个属性返回的是整个浏览器的高度
和页面窗口的大小没有任何关系
window.innerHeight
window.innerWidth
返回视口的宽高 (计算滚动条的高度)
页面变化它就变
document.documentElement.clientHeight
document.documentElement.clientWidth
返回视口的宽高(不计算滚动条的高度)
window.pageYOffset
window.pageXOffset
返回页面滚动的距离(通用)
这两个属性指的是页面发生滚动的距离
window.screenX
window.screenY
返回浏览器距离屏幕的距离
3、window.navigator对象属性
window.navigator对象包含大量有关Web浏览器的信息,在检测浏览器及操作系统上非常有用。(这个对象和event一样是一个全局变量,并且是唯一的)
navigator.appCodeName //浏览器代码名的字符串表示
navigator.appName //官方浏览器名的字符串表示
navigator.appVersion //浏览器版本信息的字符串表示
navigator.cookieEnabled //如果启用cookie返回true,否则返回false
navigator.javaEnabled() //如果启用java返回true,否则返回false
navigator.platform //浏览器所在计算机平台的字符串表示
navigator.plugins //安装在浏览器中的插件数组
navigator.userAgent //返回和浏览器内核相关的信息
ps:如果window.navigator.userAgent出现了Mobile,可以确定用户使用的是移动设备
4、window对象中涉及到的方法
3.提示框
1 浏览器中常见的三种提示框
(1) alert(alertMsg);
表示警示框,作用是提示用户信息,该方法执行后无返回值。
(2) prompt(alertMsg,defaultMsg);
表示警示框,作用是提示用户信息,该方法执行后根据情况不同返回值略有不同。
a)点击取消,返回值为null
b)没有默认值
如果用户没有输入内容,返回一个空字符串
如果用户输入了内容,返回值为用户输入的内容
c)有默认值
如果用户没有输入内容,返回默认值
如果用户修改了默认,返回值为用户输入的内容
(3) confirm(alertMsg)
表示警示框,作用是提示用户信息,点击确认返回true,点击取消返回false。
注意:以上三种对话框都是模式对话框,即在用户点击确定按钮或取消按钮把对话框关闭之前, 它将阻止用户对浏览器的所有输入,并暂停对 JavaScript 代码的执行, 在用户作出响应之前,不会执行下一条语句。
2 提示框综合案例【自定义右键菜单】
四.间隔调用和延迟调用
4.1 间隔调用
间隔调用全称为间隔调用函数,又名定时器。是一种能够每间隔一定时间自动执行一次的函数。
语法:var timer = null;
timer = setInterval(需要执行的函数,执行间隔时间ms);
例如:var timer = null;
timer = setInterval(function(){
console.log('hello world!');
},2000);
根据语法所述,上述代码所表示的含义为:每间隔2s自动打印一句【hello world!】
清除间隔调用
既然间隔调用每隔一段时间就会自动执行一次,那么清除间隔调用就势必存在。
语法:clearInterval(变量标识)
例如:clearInterval(timer);
上述代码就能够将刚刚创建的定时器移除掉,令其不在间隔一段时间后自动再次执行。
注意:
(1)间隔调用的返回值是一个数字队列,因此通过访问数字队列来清除间隔调用也被允许。
(2) 如果间隔调用的函数需要传入参数,则间隔调用需要使用如下的方式声
语法:var timer = null;
timer = setInterval(字符串,执行间隔事件ms);
例如:var timer = null;
function show(words){console.log(words);}
timer = setInterval('show("hello world!")',2000);
(3) 间隔调用不是立即执行,而是在【任务队列中的任务完成后】才执行间隔调用
(4) 因为间隔调用函数的实际执行者是window,因此间隔调用内部的this指向window
2 延迟调用
延迟调用又叫延迟调用函数。是一种能够等待一定时间后在执行的函数。
语法:var timer = null;
timer = setTimeout(需要执行的函数,等待的时间);
例如:var wait = null;
wait = setTimeout(function(){
console.log('hello world!');
},2000);
根据语法所述,上述代码所表示的含义为:等待2s后打印一句【hello world!】
注意:延迟调用除了在语法上和间隔调用略有不同外,其余语法均相同。
五.初识数据解析
数据解析:将【不能被直接使用的数据】通过某种方法转变为【能够被直接使用的数据】的过程称为数据解析。
而对于开发者来说最常见的数据解析就是将【字符串数据】解析为【对象数据】
例如:
假设我们得到了一个字符串数据为:
var data ="?name=frank&age=18&sex=male";
很显然这样一个字符串是没有办法直接为我们所用,因此我们可以通过如下的手段将这个字符串变更为一个对象。
var infoArr = window.location.search.slice(1).split("&");
var obj = {};
for(var i=0;i<infoArr.length;i++){
var temp = infoArr[i].split("=");
if(temp[0]){
obj[temp[0]] = temp[1];
}
}
六、页面加载优化和js文件解析顺序
1.defer
defer属性:等待DOM加载完成后才去加载JS脚本
2 async
async属性:DOM加载和js脚本加载异步执行,同时进行。
async优势:避免了因DOM文件过大导致的【文件加载阻塞】
async缺陷:无法确定js脚本到底何时执行,并仅对外部js脚本生效
HTML5规范要求——脚本执行应该按照脚本出现的先后顺序执行
3 不添加任何属性的js脚本
js脚本在不受任何外界因素影响的时候,实际上就是按照html代码的加载顺序执行的。因此【不添加任何属性的js脚本】总是会在【引入脚本的节点】加载完毕之前执行。
六.浏览器性能优化:回流和重绘
1 重绘(repaint)和回流(reflow)
回流(reflow):当页面中的部分或者全部元素改变宽度和高度、或者位置发生变化、删除或者增加某个或者某些元素时、某个元素影藏或者显示时,这时页面的重新加载被称为是回流。
重绘(repaint):当页面的中的可见性发上变化时,我们说页面发生了重绘。比如:背景颜色吗,文字颜色等。
通过上述概念我们能得到一个结论:回流必将引起重绘,而重绘不一定引起回流。
ps:重绘的代价是高昂的,因为浏览器必须验证DOM树上其他节点元素的可见性。
ps:回流更是浏览器性能的关键因为其变化涉及到部分页面(或是整个页面)的布局。一个元素的回流导致了其所有子元素以及DOM中紧随其后的祖先元素的随后的回流。
2 引起重绘和回流的原因
或许有人会说:既然他们对于页面的影响是这么的可怕,那么有哪些因素可能导致回流呢?我们记住,然后避免他们不就可以了么?
不幸的是,对于网页中的很多操作都可能会引发回流,其中甚至包括了一些对css的操作。
例如:
调整窗口大小(Resizing the window)
改变字体(Changing the font)
增加或者移除样式表(Adding or removing a stylesheet)
内容变化,比如用户在input框中输入文字(Content changes, such as a user typing text inan input box)
激活 CSS 伪类,比如 :hover
(IE 中为兄弟结点伪类的激活)(Activation of CSS pseudo classes such as :hover (in IE the activation of the pseudo class of a sibling))
操作 class 属性(Manipulating the class attribute)
脚本操作 DOM(A script manipulating the DOM)
计算 offsetWidth 和 offsetHeight 属性(Calculating offsetWidth and offsetHeight)
设置 style 属性的值 (Setting a property of the style attribute)
3 如何从重绘和回流方面提高浏览器性能
1.不要一项一项的去改变样式,尽可能一口气写完。(可以写在一起,不要被打断就行)
最好使用.style或者.style.cssText
2.读写DOM也尽量也放在一起
3.使用文档碎片 var linshi = document.createDocumentFragment();
4.使用fixed或者absolute可以减少回流和重绘
5.使用
window.requestAnimationFrame(function () {
for(var i=0;i<div.length;i++){
div[i].style.background = "red";
}
})
把发生重绘的代码推迟到下一次重绘发生时一起执行
七、.window.history对象
window.history对象表示整个浏览器的页面栈对象。在对象中提供了一些属性和方法来帮助更好的控制整个浏览器中页面的访问。
(1)window.history.back() 跳转到栈中的上一个页面
(2)window.history.forward() 跳转到栈中的下一个页面
(3)window.history.go(num) 跳转到栈中的指定页面
(4)window.history.length 栈中页面的数量
ps:通过window.history对象中提供的方法进行的页面跳转并不会向栈中添加新的页面。
而通过window.location.href或者通过a标签进行的跳转,则会向栈中添加新的页面。
八.函数的【道岔】:call和apply--以及对函数中this的影响
什么是道岔?
火车在行进途中遇到路口后,决定火车应该向那个方向执行的装置被称为【道岔】
我们可以将函数类比为火车,
而今天介绍的call和apply就好比为控制火车行进方向的【道岔】
语法:
call: 函数.call(函数实际的调用者,函数参数1,函数参数2,...)
apply: 函数.apply(函数实际的调用者,【函数参数1,函数参数2,...】)
他们所表达的含义是:
函数的实际调用者是call或者apply的第一个参数。
而后的参数是这个要执行的函数的参数。
call函数结论:
(1)call函数能够改变函数的实际调用者,也就是函数中this的指向。
(2)call函数中第一个参数必须写,而其余参数可以不写。
(3)call函数传递参数的时候,用逗号分隔每一个参数
apply函数结论:
(1)apply函数能够改变函数的实际调用者,也就是函数中this的指向
(2)apply函数中第一个参数必须写,而其余参数可以不写
(3)apply函数传递参数的时候,参数采用数组方式传递
九.闭包
1 变量作用域
闭包在js中是一个非常使用的模块,不过我们在学习闭包之前,需要先了解javascript的作用域方面的知识。
javascript中变量作用域只有两种:
全局作用域
函数作用域(局部作用域)
javascript语言特殊之处就在于,在函数内部能够直接读取全局变量
2 如何在函数外部读取局部变量
出于很多原因,的确在很多时候需要在函数之外读取函数内部的局部变量。
但是刚才也说过了,正常情况下js中是不允许这种访问的。
所以我们需要一种变通的方法,来帮助我们在函数之外访问函数内部的局部变量。
但是什么办法能实现这个功能呢?
让我们先把这个问题放在一边,来看下面的一段代码
function func(){
num=999;
function func2(){
console.log(num);
}
}
在这段代码中func中的所有局部变量对func2来说都是可见的,因为func2被包括在了func函数之内,但是反过来则不行。这就是js中独有的【链式作用域(chain scope)】结构
既然刚才的代码中func2可以读取func中的局部变量,那么只要把func2作为返回值,不就可以在func外部读取它的内部变量了么?
function func(){
num=999;
function func2(){ console.log(num); }
return func2;
}
var result=func();
result();
ps:在这里func2函数的函数名实际上并没有什么用。
3 闭包
实际上上一节中我们所写的func2就是一个闭包。我们把上一节课的代码稍稍整理一下可以得到下列的代码:
function func(){
num=999;
return function(){console.log(num);}
}
func()();
在上述案例中,我们正是通过闭包将函数内部的局部变量传递到了函数外部。
所以在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
4 闭包的用途
闭包在js中可以使用在很多地方,但是闭包最常见的用途会使用在如下两个方面:
(1)通过闭包,可以在函数外部读取函数内局部变量的值
(2)让局部变量始终生存在内存当中,避免被垃圾回收机制杀死
很显然对于第一个用途我们刚刚已经说过了,但是对于第二个用途我们又应当如何理解呢?
请观察下列代码:
function func(){
var num=999;
nAdd=function(){num+=1;}
return function (){console.log(num);};
}
var result=func();
result();
nAdd();
result();
5 闭包的注意事项
(1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大。
所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。
解决方法是:在退出函数之前,将不使用的局部变量全部删除。
(2)闭包会在父函数外部,改变父函数内部变量的值。
所以如果把父函数当作对象(object)
那么闭包就好比是对象的公用方法(Public Method)
而内部变量则就是对象的私有属性(private value)
这时一定要小心,不要随便改变父函数内部变量的值。
(3)由于闭包的实际调用者都是window,因此所有闭包中的this均指向了window。
如果非要在函数中通过this来调用函数中的变量,则记得使用apply或者call变更闭包中this的指向。
十、this总结
this关键字可以说在js中使用频率是一个较高的东西,而this的使用场景更是复杂多样。
因此对于this,我们需要更好的掌握
下面是对于this的使用场景,我们都逐一学习和使用过。那么下面我们就来看一下this关键字在如下场景中都发挥了什么样子的作用。
(1)this在正常函数中: 谁调用了函数,this指向谁
(2)this在闭包中: 闭包中的this指向window
(3)间隔调用和延迟调用: 间隔调用和延迟调用中的this指向window
(4)事件中的this
HTML:this指向window
DOM0:this指向绑定该事件的元素
DOM2级:IE指向window 非IE中指向指向绑定该事件的元素
(5)自执行函数: this指向window
(6)call和apply函数: 第一个参数是谁,this指向谁
1.以函数的形式调用的时,this永远都指的的是window
2.以方法的形式调用时,this指的就是调用方法的对象
3.当以构造函数的形式调用时,this就是新建的那个对象
4.当使用call() 和 apply() 调用时,this是指定的那个对象
陆、HTML原型和原型链
1、原型
js中给函数提供了一个对象类型的属性,叫做prototype(原型)。
原型归函数所有,他不用创建,是默认存在的。
例:
function Car(){}
var mycar1 = new Car();
var mycar2 = new Car();
Car.prototype.lun1 = '左前轮';
console.log(mycar1.lun1);
console.log(mycar2.lun1);
js中提供了一种机制:如果是通过类创建的对象,当访问的属性在对象中如果没有找到。 则会去【创建对象的类】的原型中查找。如果能找到,也相当于对象拥有这个属性。
那么从上面的图中我们就能够得到一个结论:
原型的作用其实就是为类(函数)提供了一个【公共区域】,在这个公共区域中声明的属性 和方法能够被所有通过这个类所创建的对象所访问到。
ps:在原型中声明的属性和方法,有时也被称为是类的公有属性和公有方法
概念:原型是js为所有函数所创建的一个对象类型的属性,原型当中的属性和方法被所有
通过这个函数所创建的对象共享。
结构:原型是一个对象,在原型中通常拥有两个属性:
(1)构造器constructor:该属性指向了这个类本身
(2)原型指向__proto__:该属性指向原型本身,提供给通过类创建的对象使用。
作用:原型用来创建类的公有属性和公有方法,为创建对象服务
优点:节约内存空间,不必为每一个对象都分配公有属性和公有方法的内存。
缺点:原型中不能保存数组这类引用类型的数据,
因为地址传递的问题会导致出现修改的连锁变化
hasOwnPrototype() 来检测自己是否有该属性
<script>
function Cat(){
}
var cat1 = new Cat();
Cat.prototype.a = "公共区域";
console.log(cat1.a);
console.log(cat1.hasOwnProperty("a"));
</script>
输出:
公共区域
false
2.原型链
1 原型链构成
由【对象的__proto__属性】和【对象的构造函数的原型的__protp__属性】构成的链式结构称为原型链。
ps:原型链的顶端是Object对象。
pss:Object对象没有__proto__属性,或者说Object对象的__proto__属性指向了自身。
下面我们通过一段代码来解释什么是原型链。
function Car(){} Car.prototype.lun1 = '左前轮';
var mycar1 = new Car();console.log(mycar1.__proto__);
//输出的内容是【mycar1对象的构造函数Car的原型】即Car.prototypeconsole.log(mycar1.__proto__.__proto__);
//输出的内容是【Car.prototype对象的构造函数Object的原型】即Object.prototypeconsole.log(mycar1.__proto__.__proto__.__proto__);
//输出的内容是【Object.prototype对象的构造函数Object的原型】即null(因为Object的__proto__指向自己)
2 原型链的作用及创建
原型链的作用 : 访问对象的属性或方法的时候,
首先在本身中查找是否拥有这个属性或方法。
如果没有找到那么就沿着原型链向上逐级查找直到Object为止,
在任何一级寻找到这个属性或方法都视为对象拥有这个属性或方法。
原型链的创建 : 上一节中我们说道原型链是依靠__proto__属性将对象和原型连接起来
那么原型链的创建实际上就是将
【函数的原型】设置为【另一个函数的对象】
即可。
function Father(){}
Father.prototype.fname = 'frank';
var father = new Father();
function Son(){}
Son.prototype = father;
柒、正则表达式
扒、排序算法
1.数组去重
数组去重是指:从数组中找到相同的元素,并将相同的元素删除。保证数组中的每个元素都是独一无二的操作。
1 indexOf数组去重
基本思想是:利用数组的indexOf方法,目的是寻找存入参数在数组中第一次出现的位置。
缺点:实现这个方法的时候会遍历数组直到找到目标为止,消耗掉很多时间。
2 hash表数组去重
基本思想是:将已经出现过的元素当做属性名,存入一个object内,下标的引用要比用indexOf搜索数组快的多
缺点:内存占用很多,以牺牲空间来换取时间。
3 冒泡排序(Bubble Sort)
基本思想是:
依次比较相邻的两个数,如果不符合排序规则,则调换两个数的位置。这样一遍比较下来,能够保证最大(或最小)的数排在最后一位
再对最后一位以外的数组,重复前面的过程,直至全部排序完成
function bubble(myarr) {
var len = myarr.length;
var i = 0;
for (var i = 0; i < len - 1; i++) //需要几轮比较
{
var flag = true;
for (var j = 0; j < (len - 1) - i; j++) //一轮比较中,需要比较的次数
{
if (myarr[j] > myarr[j + 1]) //比较两个数组元素的大小,并将大的放在后面
{
var temp = myarr[j];
myarr[j] = myarr[j + 1];
myarr[j + 1] = temp;
flag = false;
}
}
if(flag==true) {
break;
}
i++;
}
console.log(myarr);
console.log(i);
return myarr;
}
var a = [1,5,2,3,4,6,8,44];
bubble(a);
玖、json
1、json的概述
JSON英文全称JavaScript Object Notation,是一种轻量级的数据交换格式。
JSON是一门独立的语言,用于存储和传输数据的格式,通常用于服务端向网页传递数据 。
JSON语言采用了JavaScript的语法,这意味着在 JavaScript 中处理 JSON数据不须要任何特殊的 API 或工具包,但是还是需要说明的一点就是:
JSON和Javascript是两门不同的语言。
JSON的格式仅仅是一个文本,而文本是可以被任何编程语言读取及作为数据格式传递的。
ps:个人理解,JSON就是
(1)将【前台的数据(对象、数组等)】转换成【字符串发送给后台】。
(2)将【后台回传的数据(字符串)】转换为【普通的数据(对象、数组等)】。
这个转换过程。
2 JSON提供的方法
前面提过JSON是用来对数据进行处理和转换的一种语言,并且在JSON内部的执行代码采用了JS的语法,因此JSON对JS直接提供了两个方法来处理数据。而不需要在额外的添加各种数据包和API。
(1)JSON.parse(后台传输过来的数据)
反序列化(有时候也被称作JSON数据解析,简称为JSON解析),
能够把JSON字符串转换成JS的数据类型。
转换的时候,如果字符串中存在不符合JSON要求的格式,会直接报错。
(2)JSON.stringify(要往后台传输的数据)
序列化(有时候也被称作JSON数据封装或数据加密)
能够把JS的数据类型转换成JSON字符串。
转换的时候,如果数据中存在不符合JSON要求的格式,会做对应的处理
例如:
服务器传给前台一条数据:
'{"stuInfo":[{"name":"frank"},{"name":"bill"},{"name":"jobs"}],"feature":["英俊潇洒","富可敌国","英年早逝"]}'那么很显然这个数据是一个字符串,而对于JS而言字符串并不是十分理想的数据格式。
如果想要动态的将数据加载至页面中,最好的数据格式就是对象和数组。
我们再来仔细观察一下这条数据,发现实际上这个字符串实际上是一个‘对象’!'{
"stuInfo":[{"name":"frank"},{"name":"bill"},{"name":"jobs"}],
"feature":["英俊潇洒","富可敌国","英年早逝"]
}‘而我们如果想要使用后台传回的数据,便需要对这个字符串进行【处理】。这个处理的过程就是JSON解析。
3 JSON解析
JSON解析就是通过某种手段,将【后台回传的字符串数据】转换成【可以直接被使用的数据】的过程。
通常情况下JS中的JSON解析会直接采用JSON中提供的JSON.parse方法来直接转换。
var dataStr = '{"stuInfo":[{"name":"frank"},{"name":"bill"},{"name":"jobs"}],"feature":["英俊潇洒","富可敌国","英年早逝"]}';
var dataObj = JSON.parse(dataStr);
console.log(dataObj);
注意: JSON在实际开发过程中通常会在两个地方被用到。
一个是发送请求的时候,会将数据封装为一个JSON字符串在发送。返回来第二点就是在接受请求来的数据的时候,使用JSON来将数据信息转换为实际可用的数据类型。除此之外使用JSON的机会不多。
复杂json展示:http://api.douban.com/v2/movie/top250