第一章:javascript简史
1.javascript简史
为解决网页上简单的表单验证问题,网景公司的开发人员开发了一种名为livescript的脚本语言,为搭上当时java语言的热浪更名为javascript,所以java和javascript在语言上来说没有任何关系。网景公司的navigator的竞争产品IE浏览器也有了自己的JScript对javascript的实现,于是javascript有了两个不同版本,为了有统一的标准,欧洲计算机制造协商会ECMA指定的39号技术委员会TC39制定了ECMAScript标准ECMA-262
2.javascript实现
DOM
DOM是XML经过扩展用于HTML应用程序编程接口,DOM将页面热映射一个多层节点结构,开发人员可以借助这个API实现对网页上任何节点的增删改查,DOM2级对DOM1级做以下扩充
DOM视图(应用css前后的文档)
DOM事件(事件与事件处理)
DOM样式(css样式接口)
DOM遍历和范围(定义遍历和操作文档树的接口)
BOM
BOM没有标准,不同的浏览器有自己的实现,HTML5解决了大部分这种因BOM实现没有标准带来的问题,以下是BOM的一些扩展
弹出新浏览器窗口,移动缩放关闭浏览器窗口
navigator浏览器详细信息对象
screen用户显示器分辨率详细信息对象
location浏览器加载页面详细信息对象
对cookies支持
XMLHttpRequest、IE的ActiveXObject自定义对象
ECMAScript(语法规则)+DOM(文档对象模型)+BOM(浏览器对象模型)完成对javascript的实现
3.ECMAScript
实现ECMAScript标准:语法、类型、语句、关键字、保留字、操作符、对象、支持Unicode标准
第二章:html中使用javascript
1.script元素
javascript外部引入的异步加载async和同步加载defer
defer属性表示此外部js文件应该在页面结构完全解析完成后执行js
async属性表示此外部js文件的加载不会影响页面上其他资源文件的加载和页面的加载,且加载时就执行js
在没有defer和async的属性前提下,js代码的执行都是按照先后顺序进行的
2.嵌入代码与外部文件
嵌入代码
外部文件
src引入,建议使用外部引入js的方式,可维护性较嵌入代码高,可缓存,适应未来
3.noscript元素
在浏览器不支持javascript或javascript被禁用时使用的标签,一般展示一些javascript被禁用或浏览器不支持javascript的自定义提示信息
第三章:基本概念
1.语法
ECMAScript借鉴了C和类C的很多语言的写法,javascript属于弱类型语言,C属于强类型语言,强弱类型的区别在于是否编译执行,声明变量是否必须声明类型等等
2.区分大小写
所有变量名、函数名、操作符都区分大小写
3.标识符
变量名、函数名、属性名、函数的参数的名字
标识符命名规则:数字、字母、下划线、 组 成 , 字 母 、 下 划 线 、 组成,字母、下划线、 组成,字母、下划线、开头,不能以数字开头。
4.语句
分号结尾,多条或单条语句最好都使用代码块
5.关键字和保留字
关键字和保留字都不能用来作为标识符,关键字具有特殊的定义和用途,保留字是在将来有可能具有特殊的定义和用途
6.变量
在ES5里变量的声明使用var操作符,ES6多了一种let声明和const声明
ES5的函数声明和变量声明会有一个变量声明提升函数定义提升,变量赋值和函数调用在后的特点,在一个作用域中
var a = “哈哈哈”;可以声明任何数据类型的变量,声明未赋值的变量会保存特殊的值undefined,
var a = “哈哈哈”,b=10,c=false,d=undefined;逗号隔开一次性声明多个变量,未声明变量调用会报错
数据类型
基本类型(原始类型):number(所有数字int,double,float…)、string、boolean、undefind、null。
引用类似(对象类型):除了基本类型之外的都是引用类型。
基本数据类型保存在栈内存中
引用数据类型保存在堆内存中
引用数据类型在复制时复制的是引用地址,这就会导致修改复制的引用数据类型的值会导致原数组的值也发生改变,这就是浅拷贝,深拷贝的数据各自的值发生修改互不影响
7.操作符
1.typeof
typeof 用来检测数据是哪种类型,typeof 对象或null为Object,typeof 函数名 为function,typeof NaN 为number,NaN是特殊的number,与任何值都不相等,与自己也不相等,undefined与null相等但不全等,typeof是唯一一个可以使用未声明变量的关键字
2.一元操作符
递增递减操作符:分前缀和后缀,如果是前缀递增或递减,变量的值会在语句求值之前改变,而后缀递增或递减会在语句求值之后改变。
前缀:++a,–a,后缀:a++,a–
一元加和减:+a,-a,一元加和减在变量前面添加+或-对数值没有影响,对于不是数值类型的变量会将它们转换成对应的数值,一元减会对转换后的数值取负数
3.位操作符
待续
8.函数
待续
前三章tips
引引加加:"++"、模板字符串${name},
转义符\:“你好”,
indexOf(寻找内容,索引),charAt(索引),substring([start,end)),
trim()去掉字符串前后空格
和换行\n转义符,
var sum = 1 + “2”;//+号优先考虑字符串
显示转换为数字
Number() parseInt() parseFloat()
Number(true)为1,Number(false)为0,Number(123abc)为NaN,Number(null)为0 Number(undefind)为NaN
隐式转换为数字
*,/, -,
加号只能单目隐式转换。string转布尔,内容非空就为true,空就为false。number转布尔,非0非NaN为真。null、undefind转布尔都为false
第五章:引用类型
1.Object
特性:
对象是一种引用类型的数据,里面可以有很多属性,属性值可以是任何js里的数据类型,属性值为函数时,这个属性叫方法,对象可以字面量创建也可以通过构造函数方式创建,里面的属性和方法并没有规定顺序
使用内部构造函数Object()来创建一个对象
var obj = new Object();
.语法往对象里添加属性和方法
obj.name = “小明”;
声明函数
function 函数名 (){
函数体
}
当对象的属性值为一个函数时,该属性叫方法
通过字面量创建对象
var obj = {}
在创建时添加属性和方法
var obj = {
name:“小明”,
age:30,
gender:function(){
console.log(“男生”);
}
}
添加属性
obj.job = “student”
对象名和方法名可以是数字,但是属性名为数字的话就要这样用
obj[1]
一般的属性也可以用[]获取
obj[“gender”] ();//执行obj里的gender方法
一定的条件下,number string boolean自动转成对象,原始类型包装对象
var v1 = new Number(123);
一但string使用.语法 ,js会自动调用new string()创建临时包装对象
寻找未定义的方法或属性时会报undefined
2.Array
特性:
数组也是一种引用数据类型,数组里的每个元素可以是任何数据类型,每个元素都有对应的下标,可以通过这个下标来访问对应的元素,数组也支持字面量创建和构造函数创建
数组也是一种对象
var arr = new Array(10);//创建长度10,元素空的数组
字面量创建
var arr2 = [10];//创建长度1,元素值为10的数组
var arr3 = [1,2,3,4,5];
添加
var arr3[5] = 6;
数组索引从0开始,寻找不存在的标相当于在对象里寻找不存在的属性或方法会报undefined
元素可以是任意数据类型
arr4 = [“111”,123,null,undefined,true,对象,函数,[456,函数名]];
数组也分一维和多维,想要取对应的元素都必须使用下标去访问
while(表达式){语句块}//先判断再执行
do{语句块}while(表达式)//先执行再判断
表达式满足时,dowhile和while执行的次数一样
for(初始条件;控制条件;追加次数){语句块}
break用于跳出循环–停止
continue用于跳出当前迭代,进入下一个迭代
for in 可以遍历对象和数组,遍历对象遍历的是对象的键值,遍历数组遍历的是数组的下标,遍历数组有时不会按照顺序,for in会将对象及对象原型对象上的属性全部遍历出来,可以用 hasOwnProperty() 来判断是否为当前对象的属性
for of 用于遍历数组里的元素,使用for of遍历普通对象会报错,因为for of是创建一个循环来迭代可迭代对象,可迭代的对象内部实现了这个 Symbol.iterator方法 ,而普通对象没有实现,所以会报一个xxx is not iteratable的错误
forEach:遍历数组,但不能使用break continue return语句
for:遍历数组
map:遍历数组 有返回值。并且可以返回一个结果数组。但是map 遍历对象的话也会报错,所以map只能循环数组或者对象数组
数组的一些常用方法:
数组的复制:浅复制和深复制
浅复制复制地址,复制数组与被复制数组会互相影响,深复制则互不相干
push()向数组末尾添加一个或多个元素,会改变数组,返回新数组长度
pop()删除数组末尾一个元素,会改变数组,返回删除的元素
unshift()向数组开头添加一个或多个元素,会改变数组,返回新数组的长度
shift()删除数组首个元素会改变数组,返回删除的元素
slice(start[,end])截取一段数组,将截取的新数组返回,左闭右开
splice(start,删除个数,添加一个或多个)用于删除指定位置的元素并添加新元素,返回新的数组
如果删除个数为0,会返回空数组
concat()拼接一个或多个数组,不改变原数组,返回拼接的数组
join()将数组转换为字符串,默认逗号连接,可以指定符号连接元素
sort()排序
function com(a,b){
return a-b;//升序
return b-a;//降序
}
arr4.sort(com);
3.Date
日期对象
4.RegExp
正则表达式
5.function
函数的创建方式:
函数声明:function fun(){
…
}
函数表达式:
var fun = fun (){
…
}
构造函数创建:
var fun = new Function(参数,函数体)//不推荐这种方式来创建函数,因为这种语法回导致两次代码解析,这种方式创建函数最后一个参数被当做是函数体,前面的参数都为创建出来的函数的形参
没有重载
声明两个同名函数,则在调用函数时,后声明的函数会覆盖前面声明的函数,执行的是后面函数的函数体里的内容
函数和变量在代码中的执行
全局预编译
1.生成了一个全局执行上下文对象–GO对象(window)
2.声明提升
预编译时只做声明,执行时再进行赋值
var a = 111
var b = function(){}
function a() {}
预编译
GO={
a:function a(){}
b:undefuned,
}
执行
GO={
a:111
b:function(){}
}
函数预编译
1.生成一个函数执行上下文对象AO对象
2.参数提升并赋值 声明提升
function a(par){
console.log(par,b,fun);
var b = 111
function fun(){}
console.log(par,b,fun);
}
a(222)
预编译
AO={
par:222
b:undfined
fun:function fun(){}
}
执行
AO={
par:222
b:111
fun:function fun(){}
}
闭包产生条件:内部函数引用了外部函数的变量就会产生闭包
闭包的作用:使函数内部的变量在执行完毕之后依旧保存
让函数外部可以操作函数内部的数组
作为值的函数:
函数名本身就是变量,所以可以作为一个值来使用,可以当成参数传递,还可以当成函数返回值返回
函数的内部属性:
每个函数内部都会有两个特殊的对象arguments和this,arguments用来保存函数调用时传入的参数,是一个类数组,但它还有一个属性callee指向拥有这个arguments对象的函数,可以降低回调函数的耦合度,例子:
`function check(a,b){
console.log(arguments);
console.log(this);
if(b<=a){
return b;
}
else {
return b+arguments.callee(a,b-1);
}
}`//在函数内部argements.callee代替了函数名调用函数方式,降低了耦合度
函数在每次调用的时候 解析器会向函数内部传入一个隐含的参数 this
this指向的是一个对象 这个对象也叫函数的执行上下文对象
function fun(){
console.log(this);
}
window.fun()
//this 谁调用指向谁
this显示绑定 bind()() apply() call()
第一个参数就是要赋值给this的上下文对象
obj.myFun.call(obj2,“qqq@aaa”,“成都”)//有几个形参就在第一个参数的后面传几个实参
obj.myFun.apply(obj2,[“qqq@aaa”,“成都”])//有几个形参就在第一个参数的后面的数组里面传几个实参
obj.myFun.bind(window,“qqq@aaa”,“成都”)()//有几个形参就在第一个参数的后面传几个实参
函数的属性和方法:
每个函数都会有两个属性length和prototype,length表示该函数需要的参数个数,prototype是函数的原型对象,不可被枚举,很多平时没看见的函数但可以使用,但不知道在哪里定义的,如toString(),valueOf()等方法都是定义在原型对象上的,第六章详解
6.基本包装类型
Boolean类型
使用Boolean构造函数实例一个Boolean对象,这个实例重写了valueOf()方法,重写了toString()方法
官方建议不要使用Boolean对象
Number类型
重写了valueOf()方法,重写了toString()方法,通过Number创建Number对象可以调用toString(“几进制”)来转换对应进制,toFixed(转换小数位数)转换对应几位小数
String类型
字符串也有length属性表示字符串长度,trim()去除字符串首尾空格,转换大小写toUpperCase(),toLowerCase(),
7.单体内置对象
Global对象
不属于任何其他对象的属性或方法就是他的属性或方法,例如isNaN(),isFinite(),parseInt(),parseFloat()等方法
Math对象
第六章:面向对象的程序设计
1.对象的创建方式:
字面量创建
let obj = {
…
}
工厂模式创建:
function createobj(name,age,fun1) {
let obj = new Object();
obj.name = name;
obj.age = age;
obj.fun1 = fun1;
return obj;
}
let factoryobj1 = createobj(“小明”,20,function() {
console.log(我叫${this.name},${this.age}岁了
);
});
构造函数创建:
构造函数的命名大写字母开头
function Createobj(name,age) {
this.name = name;
this.age = age;
this.fun1 = function() {
console.log(我叫${this.name},${this.age}岁了
);
}
}
let factoryobj1 = new Createobj(“小明”,20);
普通函数调用:函数名(),构造函数调用:new 函数名()
new的作用:
1.创建一个新对象,
2.将新对象的属性proto指向构造函数的原型
3.this指向新对象,
4.执行函数中的代码,
5.将新对象作为返回值返回
this指向:
普通函数调用:函数名() this指向window
以方法的形式调用时,谁调用,this指向谁
以构造函数形式调用时,this指向构造函数实例出来的对象
2.对象的属性:
数据属性
描述行为的特性:
configurable:布尔类型默认true,能否通过delete删除属性重新定义属性
enumerable:布尔类型默认true,能否使用for in 循环遍历出属性
writable:布尔类型默认true,能否修改属性值
value:属性值,默认undefined
Object.definePropertyl(对象,属性名,{
特性:值,
…
})来设置这些特性
访问器属性
描述行为的特性:
configurable:布尔类型默认true,能否通过delete删除属性重新定义属性
enumerable:布尔类型默认true,能否使用for in 循环遍历出属性
set:函数,读取属性时调用的函数,默认undefined
get:写入属性时调用的函数,默认undefined
访问器属性不能直接定义,必须使用Object.definePropertyl(对象,属性名,{
get:函数,
set:函数
…
})来定义
3.继承、原型、原型链
原型、原型链:
每一个函数都有一个默认不可见的prototype属性指向这个函数的原型对象,这个原型对象里有一个constructor属性指向这个函数,
实例对象可以使用.__proto__
来访问这个实例的构造函数的原型对象,也就是说__proto__
指向的是这个实例的构造函数的原型对象,但有一个例外,Function的__proto__
指向的就是Function的原型对象, Function.__proto__ === Function.prototype
,为true,Function构造函数可以实例出很多对象,有时这些对象会拥有相同的属性,比如一个Person构造函数实例出两个对象,这两个对象都拥有许多相同的属性和方法,这时就可以考虑将这些属性和方法添加到Person构造函数的原型对象上去,Person.prototype.属性/方法 = …,或使用实例对象来往原型上添加属性、方法,people1.__proto__
.属性/方法 = …
当对象使用属性或方法时,现在自身找,找不到再去父类原型对象去找
一切对象都是Object()的实例,一切函数都是Function()的实例
Object和Function都是构造函数所以Object是Function的实例,而Function的原型对象的__proto__
指向Object的原型对象,Object的原型对象的__proto__
指向为null
继承:
继承则是通过让一个对象的构造函数A的原型对象等于另一个构造函数B的实例,这样一来,构造函数A实例出的对象就可以调用另一个构造函数的原型对象上的属性和方法了,相当于继承了另一个构造函数的原型对象上的属性和方法
构造函数A.prototype = new 构造函数B
第八章:BOM
1.window对象
window是BOM的核心对象,拥有全局作用域,定义在全局作用域下的属性和方法会被归到window下,可以通过window调用,但不能使用delete操作符删除,而通过window添加的属性和方法可以被删除
窗口位置:
非Opera浏览器情况下
window.screenLeft === window.screenX
window.screenTop === window.screenY
窗口大小:
chrome浏览器下这两组值并不相等,IE也不相等
window.innerHeight window.outerHeight
window.innerWidth window.outerWidth
导航和打开窗口:
window.open(),接受四个参数,URL地址,窗口目标,特性字符串,是否代替浏览器中当前加载的页面的布尔值
窗口目标:_self:自身页面重定向,_parent:父窗口执行重定向,_top:第一个父窗口重定向,_blank:重新打开一个窗口
,
特性字符串:对打开窗口的一些配置,如高度、允许滚动等
setTimeout和setInterval:
超时调用和间歇调用
推荐的使用方式
创建 var timeout = setTimeout(function(){
…
},超时时间)
清除 clearTimeout(timeout)
创建 var interval = setInterval(function(){
…
},间歇时间)
清除 clearInterval(interval)
系统对话框:
系统对话框的执行会中断代码的执行,结束后代码继续执行
alert(“提示信息”),
confirm(“提示信息,点击确定返回true,取消返回false”)返回布尔值,
prompt(“提示要输入的内容”,“输入框默认展示的内容”)
2.location对象
查询字符串:
location.search返回URL ?到结尾的字符串
位置操作:
location.assign(“url”)//加载新的文档
window.location(“url”)和location.href(“url”)最后都会调用assign方法来执行
location.reload()//可能从浏览器缓存加载;加上true强制从服务器端加载
location.replace(“url”)//新的文档替换当前文档,历史记录也被替换
host:返回服务器名称(有端口号带上端口号),hostname:不带端口号的服务器名称,pathname:路径名,hash:哈希值,port:端口号
3.navigator对象
所有支持javascript的浏览器都有navigator对象,但他们各自的navigator拥有的属性不完全相同,而且同种浏览器不同版本的navigator拥有的属性也有差别,但也有很多大部分浏览器都拥有的属性如
navigator.userAgent:浏览器用户代理字符串
navigator.mimeTypes:在浏览器中注册的MIME类型数组
navigator.appName:完成名称
navigator.appVersion:浏览器版本
navigator里的属性表示的是当前浏览器的信息,可以通过这个对象识别不同的浏览器
4.screen对象
javascript高级程序设计第三版解释screen对象为js里作用不大且不常用的一个对象,它的特新也和navigator相似,只不过它是关于用户屏幕信息的一个对象,不同的浏览器screen里的属性各不相同
5.history对象
history对象里的属性表示的是用户上网的历史记录信息
length: 返回浏览器历史列表中的URL数量
history.back(): 加载history列表中的前一个URL
history.forward(): 加载histroy列表中的下一个URL
history.go(): 加载history列表中的某个具体页面(go(参数) :参数是正数:前进,负数:回退
第十一章:DOM扩展
将html文档解析为对象,这个对象里面封装了许多方法和属性
节点之间关系,嵌套关系:父节点,子节点,并列关系:同胞(兄弟)
同胞是拥有相同父节点的子节点
DOM会把其他12中数据都解析成节点对象
1.获取节点
选择器获取dom节点:
通过ID名获取元素节点,未找到返回null
document.getElementById("")
通过classname获取元素节点,返回类数组,未找到返回空类数组
document.getElementsByClassName("")
通过name名获取元素节点,返回类数组,未找到返回空类数组
document.getElementsByName("");
通过标签名获取元素节点,返回类数组,未找到返回空类数组
document.getElementsByTagName("")
新增
document.querySelector("")
通过选择器获取元素节点,返回满足选择器条件的第一个元素节点,未找到返回空类数组
document.querySelectorAll("")
通过选择器获取元素节点,返回满足选择器条件的所有元素节点,未找到返回空类数组
通过关系获取节点:
元素与元素节点:
获取父元素节点
parentElement
父节点
const fa2 = box1.parentNode
子元素节点
const son = box1.children;
子节点
const son1 = box1.childNodes;
下一个兄弟元素节点
const bro = box1.nextElementSibling;
下一兄弟节点
const bro1 = box1.nextSibling;
上一个兄弟元素节点
const bro2 = box1.previousElementSibling
上一个兄弟节点
const bro3 = box1.previousSibling
第一个子元素节点
const first = box1.firstElementChild
第一个子节点
const first1 = box1.firstChild
最后一个子元素节点
const last = box1.lastElementChild
最后一个子节点
const last1 = box1.lastChild
通过属性获取节点:
获取body元素节点,document.body
获取body元素节点,document.forms
获取锚们 有name属性的a标签,document.anchors
获取连接们 有href属性的a标签,document.links
获取图片们,document.images
获取当前文档的网址,document.URL
2.操作节点
增加节点
首先可通过createElement(“元素标签”)创建空的dom节点
append()
dom节点可通过调用这个方法添加节点或html内容
appendChild()
dom节点可通过调用这个方法添加节点,节点之间的关系都会得到相应的更新
insertBefore()
这个方法接受两个参数,插入的节点和参照节点,插入的节点会作为参照节点的同胞节点previousSibling
删除节点
replaceChild();
替换节点,接受两个参数,要插入的节点和要替换的节点
removeChild();
移除节点,接受要移除的节点参数
修改节点属性
dom元素有很多的属性如select的selected属性、input的value属性、button的disabled属性等等,这些属性都可以通过setAttribute()和getAttribute()方法来设置和获取dom节点的属性,removeAttribute()方法可以移除对应的属性,document对象上的createAttribute(“自定义属性名”)方法可创建自定义的属性,通过value赋予属性属性值
var attr = document.createAttribute(“self”);
attr.value = “selfvalue”
修改节点文本内容
innerHTML可以识别标签,获取元素节点的所有子节点
使用innerHTML加入的内容会把元素类其他的内容都覆盖掉
innerText获取元素节点的所有文本内容,可通过对innerText赋值修改dom节点的文本内容
动态脚本、样式:
只要是标签,createElement都可以创建,那么动态的脚本和样式表就可以通过函数封装调用实现
script脚本:function loadScript( dom,url){
var createscript = createElement(“srcipt”);
createscript.src = url;
createscript.type = “text/javascript”
dom.appendChild(createscript);
}
第十三章:事件
1.事件流
事件的机制:
事件冒泡:结构上是嵌套关系的元素会存在事件冒泡的功能,及同一事件,子元素冒泡向父元素
如绑定事件的dom元素的上级元素也绑定了事件,在触发目标元素的事件后,上级元素绑定的事件也会被触发
事件捕获:结构上是嵌套关系的元素会存在事件捕获的功能,及同一事件,父元素捕获子元素
通俗的讲事件冒泡由内,事件捕获由外向内
阻止冒泡:event.stopPropagation()
οnclick=function(event){
…;
event.stopPropagation() //IE8以下的浏览器阻止冒泡event.cancelBubble = true
}
focus blur change submit reset 不冒泡
事件两大类:1系统绑定的处理程序,2自定义的处理程序
先执行自定义处理程序再执行系统绑定的处理程序
box1.οnclick=function(e){
…;
e.preventDefault();//阻止系统默认事件
}
事件代理(事件委托)
事件代理的原理:事件冒泡
将原本应该绑定在子元素节点上的事件绑定在父元素节点上
2.事件处理程序
事件处理程序就是执行对应事件的函数,如click、mouseover、mousedown、他们的事件处理程序都以on开头
HTML事件处理程序:
在元素标签里给事件处理程序赋值,在js中写好对应的事件处理函数,缺点是若js未加载完成前触发事件就相当于还没有定义这个函数却执行这个函数,求稳的话得做捕获错误的处理,且假如要修改函数名就得修改两个地方
html
js
function showMessage() {
…
}
DOM0级事件处理程序:
最原始的事件处理方式,将函数赋值给事件处理程序属性,所有现代浏览器都支持,具有跨浏览器的优势,写法简单,如:
var btn = document.getElementById(“my-button”);
btn.οnclick=function(){
…;
}
清除事件:
btn.onclick = null;
缺点是不能绑定多个事件
DOM2级事件处理程序:
添加一个事件监听器,可以绑定多个事件
var btn = document.getElementById(“my-button”);
btn.addEventListener(“事件类型”,事件处理函数,默认false参数//在冒泡阶段触发,为true
则在捕获阶段触发)
清除事件:
清除事件时的参数要和添加事件时的参数一样,且事件处理函数不能为匿名函数才能清除成功
btn.removeEventListener(“事件类型”,事件处理函数,默认false参数)
IE事件处理程序
attachEvent(“事件类型”,事件处理函数) //IE8更早版本只有事件冒泡,所以没有第三个参数控制事件在哪个阶段执行,这种方式添加的事件与DOM0级事件处理程序的区别是attachEvent的事件处理函数是在全局作用域下运行,this = window,DOM0级事件处理函数的作用域是对应元素的作用域
detachEvent(“事件类型”,事件处理函数)
清除事件时的参数要和添加事件时的参数一样,且事件处理函数不能为匿名函数才能清除成功
3.事件对象
兼容dom的浏览器会将事件对象event传入事件处理程序中,无论是事件处理函数是DOM0级还是DOM2级,事件对象只会在事件执行期间存在,事件执行完成后event对象就被销毁
event里常见的属性和方法:
bubbles:事件是否冒泡
cancelable:可否阻止默认事件
target:事件的目标//IE中为srcElement
type:触发事件的类型//IE中相同
preventDefault();//阻止系统默认事件,cancalable属性为true时可使用//IE中event.returnValue设为false取消事件默认行为
event.stopPropagation() //IE8以下的浏览器阻止冒泡event.cancelBubble = true
4.事件类型
DOM3级规定了以下几类事件
UI事件
load:页面完全加载后在window上触发(所有图片javascript文件加载完成)
unload:页面完全卸载后在window上触发(从一个页面切换到另一个页面)
error:js报错,window上触发
select:选择文本框,window上触发
resize:窗口或框架大小变化,window上触发
scroll:滚动带滚动条中的元素时,window上触发
焦点事件
blur:失去焦点触发,不冒泡,所有浏览器支持
foucs:获得焦点触发,不冒泡,所有浏览器支持
鼠标事件
mousedown:鼠标按下触发事件处理函数
mouseup:鼠标弹起触发事件处理函数
mousemove:鼠标移动触发函数,停止暂停函数
event.button判断用户按哪一个鼠标键
contextmenu:右键菜单事件
dblclick:双击鼠标左键
mouseover:鼠标进入元素触发触发事件处理函数
mouseout:鼠标出元素触发触发事件处理函数 mouseover和mouseout必然有冒泡
mouseenter:鼠标进入元素触发触发事件处理函数
mouseleave:鼠标出元素触发触发事件处理函数
滚轮事件
mousewheel:鼠标滚轮向上向下滚动都会触发
文本事件
textInput:可编辑区域中输入字符,他的事件对象中有一个inputMethod可查看字符是通过哪种方式输入的
键盘事件
keydown:键盘按下时触发事件处理函数(要聚焦),window、input,contenteditable="true"的元素
//给div元素绑定onkeydown事件 必须行内式设置contenteditable="true",对于没有聚焦事件的元素设置contenteditable为true点击元素可获得聚焦,是一个编辑文本的状态 window.onkeydown = function(){ console.log(111); }box.onkeydown = function(){
console.log(222);
}
keyup:键盘弹起时触发事件处理函数
keypress:键盘按下时触发事件处理函数(字母键)
先keydown 再keypress 最后keyup 三种键盘事件里都有alert,keyup里的alert不会执行
变动事件
页面上dom元素发生变化(增加修改删除)触发
5.内存和性能
事件委托:
当多个dom元素在同一父级元素下且都需要绑定事件时可利用事件冒泡机制将事件绑定到父级元素上,让父元素代理子元素的事件也称时间代理,可提升一些性能
事件处理程序的清除:
在使用完事件处理程序后最好及时将其清除,不然后期事件处理程序会越来越多,造成内存的浪费,且dom元素与js的关系也来越重
第二十四章:最佳实践
1.可维护性
变量、函数命名规则
变量的命名应该见名知义,在声明变量时如果有多个变量声明应放在一起一次性声明,声明变量时尽可能减少全局变量的声明
变量:
命名为名词,不考虑长度,见名知义,在声明变量时如果有多个变量声明应放在一起一次性声明,声明变量时尽可能减少全局变量的声明
函数:
命名为动词开头,驼峰命名,返回布尔值的函数以is开头,不考虑长度,每个函数应该有注释解释行为,解释参数,是否有返回值
代码格式
代码缩进使用tab缩进,避免使用空格缩进,避免两个空格,函数与函数间空行,vue代码规范参照vue代码风格指南https://cn.vuejs.org/v2/style-guide/
耦合度
高内聚低耦合,可移植:代码功能不会受外界环境影响,牵一发动全身就是耦合度很高的后果,会对后期代码维护造成很大的难度
2.性能
尽量使用javascript原生的方法而不是自己写
多个if else语句使用switch语句替换,switch语句还可以使用表驱动来优化,参考知乎表驱动文章https://zhuanlan.zhihu.com/p/259806449
位运算符速度快于算数运算和布尔运算
字面量创建数组或对象而不是使用构造函数创建
css,js,html应该分离,避免使用js去大量操作dom或css,这回导致页面的重构与回流
3.部署
代码压缩:删除注释,删除空白,缩短变量名