JavaScript
1. 浏览器内核
五大主流浏览器: IE(edge)、Firefox、Safari、Opera、Google Chrome
五大内核: Trident、Gecko、Blink、Webkit、Presto
-
Trident
- Trident(又叫MSHTML),是微软开发的一种排版引擎
- 浏览器: IE ,现在edge采用双内核(其中就有Chromium迷你)
-
Gecko
- Gecko(Firefox内核):Netscape6开始采用的内核,后来的Mozilla FireFox(火狐浏览器)
-
Webkit
- Webkit(Safari内核,Chrome内核原型,开源)
-
Presto内核
- Opera浏览器内核(V14):最初是自己的Presto内核,后来是Webkit,现在是Blink内核;
-
Blink (V8引擎)
- Opera,Chrome
注1: 提到Chrome浏览器,一般人会认为使用的Webkit内核,这种说法不完全准确。Chrome发布于2008年,使用的渲染内核是Chromium,它是fork自Webkit,但把Webkit梳理得更有条理可读性更高,效率提升明显。2013年,由于Webkit2和Chromium在沙箱设计上的冲突,谷歌联手Opera自研和发布了Blink引擎,逐步脱离了Webkit的影响。所以,可以这么认为:Chromium扩展自Webkit止于Webkit2,其后Chrome切换到了Blink引擎。另外,Chrome的JS引擎使用的V8引擎,应该算是最著名和优秀的开源JS引擎,大名鼎鼎的Node.js就是选用V8作为底层架构。
注2: Opera在2013年V12.16之前使用的是Opera Software公司开发的Presto引擎,之后连同谷歌研发和选择Blink作为Opera浏览器的排版内核
浏览器分为两部分渲染引擎和JS引擎
* 渲染引擎:用来解析HTML,俗称"内核"
* JS引擎: 也叫JS解析器,用来读取网页的JS代码,对其处理后运行,比如:谷歌V8引擎
浏览器本身不会执行JS代码,而是通过内置JavaScript引擎(解释器)来执行JS代码,JS引擎执行代码时逐行解释每一句源码(转为机器语言),然后由计算机执行,所以JavaScript语言归为脚本语言,会逐行解释执行
2.JavaScript简介
JavaScript一种直译式脚本语言(客户端脚本语言)是一种动态类型,弱类型, 基于原型的语言,内置支持类型
- 它的解释其被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在HTML
- (标准统用标记语言下的一个应用)在网页上使用,用来给HTML网页增加动态效果
- 在1995年时,有Netscape公司的Brendan Eich,在网景导航者浏览器上首次设计实现而成
- 因为Netscape与SUN合作,Netscape管理层希望它外观看起来像Java,因此取名为JavaScript
- 但是语法实际上与self及Scheme较为接近
3. JavaScript结构
- JavaScaript :
- ECMAScript3/5/6. JS的基本语法;
- DOM(Document Object Model)文档对象模型;
- BOM(Browser Object Model)浏览器对象模型
4. 变量
\\ES3
var a = 12;
console.log(a);//==>控制台输出12
\\ES6
let b = 200;
console.log(b);//==>控制台输出200
const c = 1000; //const创建的遍历不能被修改
console.log(c);//==>控制台输出1000
\\Symbol 唯一值
let n = Symbol(100);
let m = Symbol(100);
n == m//false ,有点像Java里面的对象比地址
5. 命名规范
* 1.严格区分大小写;
* 2.使用数字(不能开头),字母,下划线,$,_(公共变量开头)
* 3.小驼峰命名
* 4.不用关键字和保留字
注 1: 关键字: 当下有特殊含义
注 2: 保留字: 未来可能成为关键字
6. 数据类型
- 基本数据类型
- 数值型(Number): 常规数字和NaN(不是数字),Infinty(正无穷,加-就是负无穷)
- 字符串(String): 单引号,双引号和反引号(模板字符串)包起来的
- 布尔值(boolean): true,false
- 空对象指针(null)
- 未定义(undefined)
- Symbol(ES6)
- BigInt(ES10, V8引擎v6.7 默认启用对 BigInt 的支持 )
- 引用数据类型
- 对象数据类型(Object)
- { } 普通对象
- [ ]数组对象
- /^$/ 正则对象
- Math 数学函数对象
- Date 日期
- Error 错误
- 函数数据类型(function)
- 对象数据类型(Object)
JavaScript六大数据类型: Number, String , Boolean, null, undefined, Object
7. Number数据类型
7.1 进制
进制前缀 二进制(0B), 八进制0, 十进制, 十六进制(0x)
// 八进制数0-7的范围
var num1 = 010; //输出十进制: 8
// 十六进制转为10进制,范围(0-9,A-F)
var num2 = 0xa; //十进制输出: 10
//数值型最大值和最小值
alert(Number.MAX_VALUE); //1.7976931348623157e+308
alert(Number.MIN_VALUE); //5e-324
// 无穷大(Infinity) 无穷小(-Infinity)
alert(Number.MAX_VALUE * 2);//Infinity
alert(Number.MAX_VALUE * -2);//Infinity
7.1 NaN
NaN (not a number)不是一个数
NaN和任何东西(自己都不认识)
console.log("判断 1 == NaN: " + (1 == NaN));//false
console.log("判断'1' == NaN: " + ('1' == NaN));//false
console.log("判断 NaN == NaN: " + (NaN == NaN));//false
7.2 isNaN
isNaN 监测是否是一个有效数字,如果是返回false,否则true
语法: isNaN([value]) []:参数描述占位符
isNaN:底层会验证监测是否为Number类型,如果不是,先基于Number()这个方法,把值转换为数字类型,然后再监测
Number(10) ==> 10 -->isNaN(10) ==> false
console.log("isNaN(5): " + isNaN(5));//false
console.log("isNaN('5'): "+isNaN('5'));//false
console.log("isNaN('5we'): "+isNaN('5'));//false
console.log("isNaN('ew5'): "+isNaN('5'));//false
console.log("isNaN('a')" + isNaN('a'));//true
console.log("isNaN(true)" + isNaN(true));//false
console.log("isNaN(false)" + isNaN(false));//false
console.log("isNaN(NaN)" + isNaN(NaN));//true
7.3 数据类型转换为Number
- 方法一: 使用Number([value])函数
- 字符串 --> 数字
- 1.如果是纯数字的字符串则直接转换为数字
- 2.如果字符串有非数字内容,则转换为NaN
- 3.如果为空或者空格字符则转换为0
- 4.把引用数据类型转换为数字–>先把他基于toString的方法转换为字符串,然后在转换为数字
- 例: 11 + [] = “11”; //[]数组对象,先转为字符串’’(空) 11 + ‘’= ‘11’
- 规则:JS,浏览器底层渲染规则,V8引擎最底层机制
- 字符串 --> 数字
- 方法二:
- parseInt(String, radix)
- String:需要解析的字符串
- radix:(可选:默认为10)
- 1.可以将数字字符串开始中的字符前有效整数保留
- 2.如果对非String使用parseInt()或者parseFloat()
- 3.先转成String,然后在操作
- parseFloat()
- 1.可以将数字字符串开始中的字符前有效浮点数保留
- 浏览器给的方法(API)
- parseInt(String, radix)
var str = 'px123.3';
console.log("Number('123.123'): " + Number('123.123'));//123.123
console.log("Number(' -123.123'): " + Number(' -123.123'));//-123.123
console.log("Number('PX123.5'): " + Number('PX123.5')); //NaN
console.log("Number('123.5px'): " + Number('123.5px')); //NaN
console.log(parseInt('px123.3'));//NaN
console.log(parseInt('123.3px'));//123
console.log(parseInt('1f',16));//16(0-9,A-F)进制解析字符串: 16 + 15 = 31
console.log(parseInt('11',2));//2(0,1)进制解析字符串: 2 + 1 = 3
console.log(parseInt('27',8));//8(0-7)进制解析字符串: 14 + 7 = 23
console.log(parseInt('27',10));//10(0-9)进制解析字符串: 20 + 7 = 27
console.log(parseInt("2/2"); // 2
console.log(parseFloat('px123.3'));//NaN
console.log(parseFloat('123.3px'));//123.3
console.log(parseFloat('123.3px'));//123.3
console.log(parseFloat(true));//NaN 底层先把true转为'true',然后praseFloat
console.log("Number(' '): " + Number(' '));// 0
console.log("Number(null): " + Number(null));//0
console.log("Number(false): " + Number(false));//0
console.log("Number(true): " + Number(true));//1
console.log("Number([]): " + Number([]));//0 [].toString() ==> ""
console.log("Number([1]): " + Number([1]));//1 [1].toString() ==> "1"
console.log("Number([1,2]): " + Number([1,2]));//NaN [1,2].toString() ==> "1,2"
console.log("Number(NaN): " + Number(NaN)); //NaN
console.log("Number(undefined): " + Number(undefined));//NaN
console.log("Number(Object): " + Number(Object));//NaN Object.toString() == >"function Object() { [native code] }"
console.log("Number({}): " + Number({}));//NaN ({}).toString ==> "[Object Object]"
console.log("Number({name: '123'}): " + Number({name : '123'}));//NaN ({name: '123'}).toString() ==>"[Object Object]"
console.log("Number(Function): " + Number(Function));//NaN Function.toString() ==> "function Function() { [native code] }"
console.log(5 > '30'); // false 字符串和数字比较,字符串会转为数字
console.log('5' > '30'); // true 字符串和字符串比较,是比较位,先是最高位,然后依次向下
10 + undefined;//NaN
10 + NaN; //NaN
'10PX' - 10; //NaN;
'10' - 10; //0
8. String字符串数据类型
1.所有的单引号,双引号,反引号(ES6模板字符串)包起来的是字符串
2.将其他类型转换为字符串
方式一: [val].toString(x);(x可选:进制)
方法二:String([val]);
方法三:字符串拼接 +
[val].toString()
-
调用被转换的数据类型的toString()方法
法不会影响到原来的变量,他会将转换的结果返回- null,undefined这个值禁止使用toString()方法,如果调用会报错 对象.toString()的结果是"[object Object]" ==> Object.prototype.toString方法不是转换为字符串,而是用来检测数据类型的
String([val])
-
调用String()函数,并将被转换的数据作为参数传递给函数
-
使用String()函数做强制类型转换时
- 对于Number和Boolean实际上就是调用的toString()放
- 但是对于null和undefined,就不会调用toString()方法
-
他会将null直接转换为"null"
-
undefined直接转换为"undefined"
注意:Google数字显示蓝色,字符串黑色
-
let a = 10;
console.log("a转字符串: " + a.toString());//10
console.log("NaN转字符串: " + (NaN).toString());//NaN
//console.log("null转字符串: " + (null).toString());语法错误
console.log("null转字符串: " + String(null));//null
//console.log("undefined转字符串: " + (undefined).toString());语法错误
console.log("undefined转字符串: " + String(undefined));// undefined
console.log("false转字符串: " + (false).toString()); //false
console.log("true转字符串: " + (true).toString()); //true
console.log("[]转字符串: " + [].toString());// ""
console.log("[1]转为字符串: " + [1].toString());// "1"
console.log("[1,2]转为字符串: " + [1,2].toString());// "1,2"
console.log("正则转字符串: " + (/^$/).toString);// "/^$/"
console.log("{}转字符串: " + ({}).toString());// "[object Object]"
console.log("{1}转字符串: " + ({name : "123"}).toString());// "[object Object]"
console.log("Object转字符串: " + (Object).toString());//"function Object() { [native code] }"
console.log("Function转字符串: " + (Function).toString());//"function Function() { [native code] }"
let a = 10 + null + true + [] + undefined + '您好' + null + [] + 10 + false;
console.log(a);
/*
10 + null = 10 // 10 + 0 = 10
10 + true = 11 // 10 + 1 = 11
11 + [] => 11 + '' => '11'
'11' + undefined => '11undefined'
'11undefined' + '您好' = '11undefined您好'
'11undefined您好' + null => '11undefined您好null'
'11undefined您好null' + [] == > '11undefined您好null' + '' = '11undefined您好null'
// 把引用数据类型转换为数字-->先把他基于toString的方法转换为字符串,然后在转换为数字
'11undefined您好null' + 10 == > '11undefined您好null10'
'11undefined您好null10' + false = '11undefined您好null10false'
*/
9 DOM基本语法
文档对象模型(Document Object Model,简称:DOM): 是w3c组织推荐处理可扩展标记语言的标准编程接口
W3C已经定义了一系列的DOM接口,通过这些接口可以改变网页的内容,结构和样式
-
DOM树
- 文档: 一个页面就是一个文档,Dom使用document表示
- 元素: 页面中的所有标签都是元素,Dom中使用element表示
- 节点: 网页中的所有内容都是节点(标签,属性,文本,注释等),DOM中使用node表示
-
getElementById();方法获取带有ID的元素对象,找到返回匹配的ID的DOM Element对象,没找到返回null
-
getElementsByTagName();方法可以返回带有指定标签名的对象集合
-
getElementsByName(): 通过name属性获取一组元素节点对象
-
HTML5新增
- documet.getElementsByClassName(‘类名’); 根据类名返回元素对象集合
- document.querySelector(‘选择器’); 根据指定选择器返回第一个元素对象
- document.querySelectorAll(‘选择器’); 根据指定的选择器,返回所有的元素对象
-
获取body元素: document.body;
-
获取html元素: document.documentElement
-
获取属性
- 旧: element.属性
- 新: element.getAttribute(‘属性’); get获取 attribute属性
区别
element.属性: 获取内置属性(元素本身自带的)
element.getAttribute(‘属性’); 主要获取自定义属性(标准)
-
设置属性
- 旧: element.属性 = ‘值’;
- 新: element.setAttribute(‘属性’,‘值’);
-
删除属性
- element.removeAttribute(‘属性’)
-
自定义属性: 是为了保存并使用数据,有些数据可以保存到页面中,而不用保存到数据库里面
//这两种自定义在IE6,7,8混用不会出现问题,在高版本浏览器中由于存放的位置不同,所以取不到结果
lis[i].MyAttribute = i; // .自定义属性
dlis[this.MyAttribute] = 'active';
divs[this.MyAttribute].className = 'active';
或
lis[i].setAttribute('MyAttribute', i); //getAttribute() 和setAttribute设置自定义属性
var index = this.getAttribute('MyAttribute');
divs[index].className = 'active';
//H5标准自定义属性以data-开头
//H5新增element.dataset.index(属性)或者element.dataset['index'] ie11以上支持
//获取自定义属性 data-index = "2";
console.log(div.dataset.index);//省略前缀data
console.log(div.dataset.listName);//省略前缀data
console.log(div.dataset);//是一个集合存放了所有data开头的自定义属性
10 DOM节点
- 常用的4个节点
- 文档节点: 整个HTML文档
- 元素节点: HTML文档中的标签
- 属性节点: 元素的属性
- 文本节点: HTML中的文本内容,空格,换行,注释
节点(node): 页面中所有的内容都是节点(标签,文本(文字,空格,换行),注释等),在DOM中,利用父子兄弟节点关系获取元素; 逻辑性强,但是兼容性差
nodeName(节点名称) | nodeType(节点类型) | nodeValue(节点值) | |
---|---|---|---|
文档节点 | #document | 9 | null |
元素节点 | 标签名 | 1 | null |
文本节点 | #text | 3 | 文本内容 |
属性节点 | 属性名 | 2 | 属性值 |
属性 | 说明 |
---|---|
parentNode | 父节点,返回上一级的父类(只返回亲爸爸),没有返回null |
childNodes | 得到所有子节点(空格,文本,换行) |
parentNode.children(非标准) | 浏览器都支持,是一个只读属性,返回所有的子节点元素 |
parentNode.firstChild | 返回第一个子节点,找不到返回null,也包括所有的节点 |
parentNode.lastChild | 返回最后一个子节点,找不到返回null,也包括所有的节点 |
parentNode.firstElementChild | 获取第一个子元素,IE9以上兼容 |
parentNode.lastElementChild | 获取最后一个子元素,IE9以上兼容 |
node.nextSibling | 下一个兄弟节点(所有的节点) |
node.previouSibling | 上一个兄弟节点(所有的节点) |
node.nextElementSibling | 下一个兄弟元素节点,IE9以上兼容 |
node.previousElementSibling | 上一个兄弟元素节点,IE9以上兼容 |
创建节点: document.createElement(‘tagName’);
创建由tagName指定的HTML元素,因为这些元素本来不存在,是根据需求创建的,所以称为动态创建元素节点
添加节点: node.appendChild(child);
将节点添加到制定父节点的子节点列表的末尾,类似于css里面after
添加节点: node.insertBefore(child, 指定元素);
将一个元素节点添加到父节点指定子节点前面,类似于css中的before
删除节点: node.removeChild(child)
从Dom中删除一个子节点,返回删除的节点
复制节点: node.cloneNode()
调用方法,返回副本,也称为克隆节点或者赋值节点,括号里面的参数为空或者false,则是浅拷贝,即只克隆父节点本身,不克隆里面的子节点
- 三种动态创建元素的区别
- document.write()将内容写入页面的内容流,但是文档加载完毕,他会导致页面重绘
- element.innerHTML 大量创建字符串拼接,耗时长,内存在不断地开辟空间
- 如果采用数组的形式,一次性添加到innerHTML中,效率更高,结构复杂
- document.createElement() 耗时短,结构清晰()
注意浏览器下innerHTML效率比creatElement高
//element.innerHTML拼接
function fn() {
var d1 = +new Date();
var str = '';
for (var i = 0; i < 1000; i++) {
document.body.innerHTML += '<div style="width:100px; height:2px; border:1px solid blue;"></div>';
}
var d2 = +new Date();
console.log(d2 - d1);
}
fn();// 3秒钟
//element.innerHTML数组
function fn() {
var d1 = +new Date();
var array = [];
for (var i = 0; i < 1000; i++) {
array.push('<div style="width:100px; height:2px; border:1px solid blue;"></div>');
}
document.body.innerHTML = array.join('');
var d2 = +new Date();
console.log(d2 - d1);
}
fn(); //8毫秒
//document.createElement()
function fn() {
var d1 = +new Date();
for (var i = 0; i < 1000; i++) {
var div = document.createElement('div');
div.style.width = '100px';
div.style.height = '2px';
div.style.border = '1px solid red';
document.body.appendChild(div);
}
var d2 = +new Date();
console.log(d2 - d1);
}
fn();//20毫秒
11 DOM事件
事件三要素: 事件源, 事件类型, 事件处理程序
- 事件类型
- 鼠标点击(onclick),
- 鼠标经过触发,会冒泡,经过子盒子,还会触发(onmouseover)
- 鼠标经过触发,不会冒泡,只会触发本身(onmouseenter)
- 鼠标离开(onmouseout),
- 鼠标离开触发,不会冒泡,只会触发本身,和onmouseenter一起使用(onmouseleave)
- 获取鼠标焦点触发(onfocus),
- 失去鼠标焦点触发(onblur),
- 鼠标移动触发(onmousemove),
- 鼠标弹起触发(onmouseup),
- 鼠标按下触发(onmousedown)等等
鼠标事件对象 | 说明 |
---|---|
e.clientX | 返回鼠标相对于浏览器窗口可视区的X坐标 |
e.clientY | 返回鼠标相对于浏览器窗口可视区的Y坐标 |
e.pageX | 返回鼠标相对于文档页面的X坐标,IE9+ |
e.pageY | 返回鼠标相对于文档页面的Y坐标,IE9+ |
e.screenX | 返回鼠标相对于电脑屏幕的X坐标 |
e.screenY | 返回鼠标相对于电脑屏幕的Y坐标 |
禁止鼠标右键菜单
contextmenu主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单
禁止鼠标选中: selectstart
event对象代表事件的状态,根相关的一系列信息的集合;现在主要是鼠标事件对象MouseEvent和键盘事件对象KeyboardEvent
|键盘事件|触发条件||执行顺序|
|:–|:–|:–|
|onkeyup|某个键盘按键被松开时触发|3|
|onkeydown|某个键盘按键被按下时触发|1|
|onkeypress|某个键盘按键被按下时触发,但是它不识别功能键,如: ctrl shift 箭头等|2|
document.onkeyup = function() {
console.log('我弹起了');
}
document.addEventListener('keyup', function() {
console.log('我弹起啦');
})
//e.keyCode 返回键盘的ASCII码值, keyup和keydown事件不区分字母的大小写 A和a得到的都是65
//keypress事件区分大小写
document.addEventListener('contextmenu', function(event) {//整个页面都不能右键
event.preventDefault();//阻止事件,让其不跳转
console.log('鼠标相对于浏览器窗口 X:' + event.clientX + ' Y:' + event.clientY); //鼠标右键就可以看见坐标,可视区域
console.log('鼠标相对于文档页面 X:' + event.pageX + ' Y:' + event.pageY); //鼠标右键就可以看见坐标,整体页面
})
document.addEventListener('selectstart', function(event){ //整个页面都不能被选中
event.preventDefault();//阻止事件,让其不跳转
});
注册事件或者绑定事件: 给元素添加事件;
- 注册事件
- 传统方法: 注册事件唯一性,同一个元素,同一事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数
- 方法监听注册方式: addEventListener()IE8不支持; attachEvent()IE10以前用这个代替
- 同一个元素同一个时间可以注册多个监听器,按注册顺序依次执行
- 语法: eventTarget.addEventListener(type, listener[, useCapture]) 将制定的监听器注册到eventTarget(目标对象上),当该对象触发指定的事件时,就会执行函数
- type: 事件类型字符串,比如’click’,‘mouseover’,注意不要on
- listener: 事件处理函数,事件发生时,会调用该监听函数
- useCapture: 可选,布尔值,false(默认)
- 语法: eventTarget.attachEvent(eventNameWithOn, callback) 不兼容IE11(报错),兼容IE10及以下
- eventNameWithOn: 事件类型字符串,比如’onclick’,‘onmouseover’,注意要on
- callback: 事件处理函数,当目标触发事件时回调函数被调用
- 删除事件或者解绑事件: 传统方式: eventTarget.onclick = null;
- 方法监听删除事件
- eventTarget.removeEventListener(type, listener[, useCapture]);
- eventTarget.detachEvent(eventNameWithOn, Callback)
- 方法监听删除事件
Dom事件流: 描述从页面中接受事件的顺序,事件发生时会在元素节点之间按照特点的顺序传播,这个传播顺序就是DOM事件流
当我们点击button的时候,button在body里面,body在html里面,html在document文档里面;
buttoon --> body --> html --> document文档
- 内存捕获阶段
- 首先document先接收了点击事件,然而他没有接收到绑定事件
- 然后html也接收到了点击事件,然后他也没有接受绑定事件
- 然后body也接收到了点击事件,然后他也没有接受绑定事件
- 然后button也接收到了点击事件,然后他有接受绑定事件
当前目标阶段: 就是触发点击事件,点击事件执行完毕
- 冒泡阶段
- 向上走,接触到了body,然而他也没有接受绑定事件
- 向上走,接触到了html,然而他也没有接受绑定事件
- 向上走,接触到了document,然而他也没有接受绑定事件,于是就结束了
Dom事件流三阶段: 内存捕获阶段(从外向里,网景提出), 但前目标阶段(执行本身), 冒泡阶段(从里向外,IE提出)
- 注意
- 1.JS代码只能执行捕获或者冒泡其中之一
- 2.onclick和attachEvent只能得到冒泡阶段
- 3.addEventListener,第三个参数是true表示事件捕获阶段调用事件处理程序; false(默认不写)
- 4.onblur, onfocus, onmouseenter, onmouseleave没有冒泡
事件对象: event就是一个事件对象,写到监听函数里面的小括号里面,当形参看,系统自动创建,不需要我们传递;这个事件对象可以自己命名,比如event, evt, e
console.log(event);// IE不兼容,返回undefined
console.log(window.event); // IE写法
//e.target 返回触发事件对象(元素),点击那个元素就返回那个元素
//this 返回绑定事件对线(元素),元素绑定了这个点击事件就返回这个点击事件
//currentTarget 和this相似,返回的也是一样(ie6-8不认识)
var target = event.target || event.srcElement; //兼容性处理
console.log(event.target);
//<div class = "div_one">div_one</div>,如果是ul,li,则返回的是点击的li节点
console.log(this);//<div class = "div_one">div_one</div>,如果是ul,li返回的是ul节点
console.log(event.currentTarget);//<div class = "div_one">div_one</div>,>,如果是ul,li返回的是ul节点
//阻止默认行为(事件),让连接不跳转,或者提交按钮不提交
var a = document.querySelector('a');
a.onclick = function(event) {
event = event || window.event;
event.preventDefault()
event.returnValue;
// return false 也能阻止,没有兼容性问题
}
一系列相关数据的集合,跟事件相关的,比如鼠标点击事件,里面就包含鼠标信息
方法 | 属性 |
---|---|
e.target | 返回触发时间的对象(标准) |
e.srcElement | 返回触发事件的对象(非标准ie6-8) |
e.type | 返回事件类型,日入click mouseover不带on |
e.cancalBubble | 该属性阻止冒泡,非标准(ie6-8) |
e.returnValue | 该属性组织默认时间(默认行为)非标准ie6-8使用,比如不让链接跳转 |
e.preventDefault() | 该方法阻止默认时间(默认行为)标准,比如: 不让链接跳转 |
e.stopPropagation() | 阻止冒泡(标准) |
事件委派(代理,委派):原理: 不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点
作用: 只操作一次dom,提高性能
事件冒泡本身特性, 会带来坏处,需要灵活掌握,
比如上面的ul,li,要获取li以前是每个li都要获取,但是li多了,于是响应时间长;
事件委托: 给ul注册点击事件,然后利用事件对象的target来找到当前点击的li,因为点击的li,事件会冒泡到ul上,ul有注册事件,就会触发事件监听器
12 BOM
BOM(Browser Object Model)即浏览器对象模型,它提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是window
BOM由一系列相关的对象构成,并且每个对象提供了很多方法与属性
DOM缺乏标准,JavaScript语法的标准化组织是ECMA,DOM的标准化组织是W3C,BOM最初是Netscape浏览器标准的一部分
window对象是浏览器的顶级对象,它具有双重角色
1. 它是JS访问浏览器窗口的一个接口
2. 它是全局对象,定义在全局作用域中的变量,函数都会变成window对象的属性和方法
name是window下的特殊含义属性,所以变量不要定义为name
12.1 窗口加载事件
window.onload是窗口(页面)加载时间,当文档内容完全加载会完成触发该事件(包括图形,脚本文件,CSS文件等),就调用的处理函数
window.onload传统注册方式只能写一次,如果有多个,会以最后一个为准,使用addEventListener则没有限制
DOMContentLoaded事件触发,仅当DOM加载完毕,不包括样式表,图片,falsh等,IE9+
如果页面图片非常多,用户访问到onload触发时间比较长,交互效果不能实现,必然影响到用户体验,此时用DOMContentLoaded
window.onload = function() {
}
window.addEventListener("load",function(){
});
document.addEventListener("DOMContentLoaded",function(){
});
下面三种情况都会刷新页面都会触发 load 事件。
1.a标签的超链接
2.F5或者刷新按钮(强制刷新)
3.前进后退按钮
但是 火狐中,有个特点,有个“往返缓存”,这个缓存中不仅保存着页面数据,还保存了DOM和JavaScript的状态;
实际上是将整个页面都保存在了内存里。所以此时后退按钮不能刷新页面。
此时可以使用 pageshow事件来触发。,这个事件在页面显示时触发,无论页面是否来自缓存。在重新加载页面中,pageshow会在load事件触发后触发;
根据事件对象中的persisted来判断是否是缓存中的页面触发的pageshow事件
注意这个事件给window添加。`
12.2 调整窗口大小事件
window.onresize = function() {}
windos.addEventListener(“resize”, function() {})
window.onresize是调整窗口大小加载事件,当触发时就调用的处理函数,只要窗口大小发生变化就会触发,一般用来完成响应式布局.windos.innerWidth/Height当前屏幕的宽度/高度
12.3 定时器
setTimeout() --> window.setTimeout(调用函数,[延迟的毫秒数]);
用于设置一个定时器,该定时器在定时器到期后执行调用函数,window在调用的时候可以省略
setTimeout(function() {
console.log("时间到了");
}, 2000)
//可以把function封装到callback里面
function callback() {
console.log("HI");
}
//调用
setTimeout(callback,3000);
setTimeout('callback()',3000);
setTimeout() 也叫回调函数callback, 意思就是上一件事昨晚,然后来做这件事
停止定时器: window.clearTimeout(timeoutID)
定时器:setInterval() 每间隔多少秒就会调用这个函数,重复调用,其他的和setTimeout()方法一样
停止定时器: window.clearInterval(intervalID)
12.4 this
- 一般情况下this的最终指向的是那个调用它的对象
- 作用域或者普通函数中this指向的是window(注意:定时器中this指向window)
- 方法调用中,谁调用,this指向谁,
- var o = {sayHi: function(){console.log(this);}} this指向o,这个对象 --> {sayHi:f}
- 构造函数this指向构造函数的实例
- 例: function Fun(){console.log(this);} 调用: var fun = new Fun(); this指向new Fun在堆内存中创建的空间,赋值给了fun,所以指向fun
12.5 JS执行机制
JS特点:单线程
为了解决这个问题: 利用多核cpu的计算能力,HTML5提出Web Worker标准,允许JS脚本创建多个线程,于是出现 “同步(单线程)” 和 “异步(多线程)”
同步任务: 同步任务都在主线程上"执行栈"
异步任务: 是通过回调函数实现的 1. 普通事件: onclick,resize等
2. 资源加载: 如: load,error等
3. 定时器: 包括setInterval,setTimeout等
异步任务相关回调函数添加到"任务队列"中(消息队列)
JS执行机制原理: 1. 先执行"执行栈"中的同步任务,如果遇到回调函数,就会不执行,会放到"异步进程处理",满足条件放入"任务队列"中
2. 一旦"执行栈"中的所有同步任务执行完毕,系统就会按次序读取"任务队列"中的异步任务
3.于是被读取的异步任务’结束’ '等待’状态,进入执行栈,开始执行
4.执行完毕后,“执行栈"回到"任务队列"中查看是否还有执行的代码,这种叫做事件循环(event loop)
例如: 点击事件和倒计时事件,当主线程读取到的时候会放入到"异步进程处理”,当倒计时条件满足或者点击事件被点击了,就会进入"任务队列中",谁先满足条件,谁先进"任务队列"
- window给我们提供了一个location属性用于获取或设置窗体的URL,并且可以用于解析URL,因为这个属性返回的是一个对象,所以这个属性也叫location对象
URL(Uniform Resource Locator,URL)统一资源定位符: 是互联网上标准资源的地址,互联网上的每个文件都有一个唯一的URL,包含的信息指出文件位置以及浏览器该怎么处理
语法: protocol://host[:port]/path/[?query]#fragment
http://www.itcast.cn/index.html?name=andy&&age=18#link
protocol: 通信协议 通常的htto,ftp,maito等
host: 主机名(域名) www.itcast.cn
port: 端口号可选,省略时使用方案的默认端口 如http的默认端口为80
path: 路径由0或多个’/'符号隔开的字符串,一般用来表示主机上的一个目录或文件地址
query: 参数 以键值对的形式,通过&符号分割开来
fragment 片段 #后面的内容 常见于链接 锚点
location对象属性 | 返回值 |
---|---|
location.href | 获取或者设置整个URL |
location.host | 返回主机(域名)www.itheima.com |
location.port | 返回端口号,如果未写返回空串 |
location.pathname | 返回路径 |
location.search | 返回参数 ?name=andy&&age=18 |
location.hash | 返回片段 #后面内容常见于链接 锚点 link |
location对象方法 | 返回值 |
---|---|
location.assign(‘url’) | 跟href一样,可以跳转页面(也称为重定向页面) |
location.replace(‘url’) | 替换当前页面,因为不记录历史,所以不能后退页面 |
location.reload() | 重新加载页面,相当于刷新按钮或者f5,如果参数为true,强制刷新ctrl+f5 |
navigator对象包含有关的浏览器信息,它有很多属性,我们最常用userAgent,该属性可以返回由客户机发送服务器的user-agent头部值
// 判断用户用哪个终端打开的页面if((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
window.location.href = "url"; //手机
} else {
window.location.href = "url"; //电脑
}
history对象: window对象给我们提供了一个 history对象,与浏览器历史记录进行交互。该对象包含用户(在浏览器窗口中)访问过的URL。
history对象方法 | 作用 |
---|---|
back() | 可以后退 |
forward() | 可以前进 |
go(参数) | 前进后退功能 参数如果是1 前进1个页面,如果是-1则后退一个页面 |
offser偏移量,使用offset系列相关属性可以动态的得到该元素的位置(偏移),大小相等
- 获得元素距离带有定位父元素的位置
- 获得元素自身的大小(高度宽度等)
- 注意: 返回数值都不带单位
offset系列属性 | 作用 |
---|---|
element.offsetParent | 返回作为该元素带有定位的父级元素,如果父级都没有定位则返回body |
element.offsetTop | 返回元素相对带有定位父元素上方的偏移 |
element.offserLeft | 返回元素相对带有定位父元素左边框的偏移 |
element.offserWidth | 返回自身包括padding,边框,内容区的宽度,返回数值不带单位 |
element.offsetHeight | 返回自身包括padding,边框,内容区的高度,返回数值不带单位 |
offset与style的区别
-
offset
- offset 可以得到任意样式表中的样式值
- offset 系列获得的数值是没有单位的
- offsetWidth 包含padding+border+width
- offsetWidth 等属性是只读属性,只能获取不能赋值
- 所以,我们想要获取元素大小位置,用offset更合适
-
style
- style 只能得到行内样式表中的样式值
- style.width 获得的是带有单位的字符串
- style.width 获得不包含padding和border 的值
- style.width 是可读写属性,可以获取也可以赋值
- 所以,我们想要给元素更改值,则需要用style改变
client: 翻译过来就是客户端,我们使用 client 系列的相关属性来获取元素可视区的相关信息。通过 client
系列的相关属性可以动态的得到该元素的边框大小、元素大小等。
client系列属性 | 作用 |
---|---|
element.clientTop | 返回元素上边框的大小 |
element.clientLeft | 返回元素上边框大小 |
element.clientWidth | 返回自身包括padding,内容区的宽度,不包含边框,返回数值不带单位 |
element.clientHeight | 返回自身包括padding,内容区的高度,不包含边框,返回数值不带单位 |
scroll滚动,使用scroll系列的相关属性可以动态的得到该元素的大小,滚动距离等
scroll系列属性 | 作用 |
---|---|
element.scrollTop | 返回被卷去的元素上侧距离,返回数值不带单位 |
element.scrollLift | 返回被卷去的元素左侧距离,返回数值不带单位 |
element.scrollWidth | 返回自身实际的宽度,不含边框,返回数值不带单位 |
element.scrollHeight | 返回自身实际的高度,不含边框,返回数值不带单位 |
window.pageYOffset | 页面被卷去头部,IE9+; |
document.body.scrollTop老版本 | 页面被卷去头部, |
window.pageXOffset | 页面被卷去左侧 |
element.offserWidth | 返回滋生包括padding,边框,内容区的宽度,返回数值不带单位 |
element.clientWidth | 返回自身包括padding,内容区的宽度,不包含边框,返回数值不带单位 |
element.scrollWidth | 返回自身实际的宽度,不含边框,返回数值不带单位 |
- 1.offset系列 经常用于获得元素位置 offsetLeft offsetTop
- 2.client经常用于获取元素大小 clientWidth clientHeight
- 3.scroll 经常用于获取滚动距离 scrollTop scrollLeft
- 4.注意页面滚动的距离通过 window.pageXOffset 获得
//兼容性
function getScroll() {
return {
left: window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft||0,
top: window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0
};
}
使用的时候 getScroll().left