JavaScript基础

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)

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)
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(节点值)
文档节点#document9null
元素节点标签名1null
文本节点#text3文本内容
属性节点属性名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)
例如: 点击事件和倒计时事件,当主线程读取到的时候会放入到"异步进程处理”,当倒计时条件满足或者点击事件被点击了,就会进入"任务队列中",谁先满足条件,谁先进"任务队列"

  1. 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值