《Javascript高级程序设计》第三版--读书笔记

第二章、在HTML中使用Javascript

2.1 script

在使用<script>嵌入JS代码时,不要在代码中的任何地方出现"</script>"字符串,否则会产生错误,可以这样用"</script>"

2.1.2 延迟脚本

<script>元素中设置defer属性,相当于告诉浏览器立即下载,但其中包含的脚本将延迟到浏览器遇到</html>标签后在执行。HTML5规范要求脚本按照它们出现的先后顺序执行。现实中延迟脚本不一定会按照顺序执行,因此最好只包含一个延迟脚本。
只适用于外部JS文件,IE4~7支持defer,IE8级以上则完全支持HTML5规定

2.1.3 异步脚本

html5位script定义了async属性,与defer类似,告诉浏览器立即下载,但不保证按照先后顺序执行。其目的是不让页面等待两个脚本下载和执行,建议异步脚本不要在加载期间修改DOM

第三章、基本概念

3.1.2 标识符

所谓标识符就是指变量、函数、属性的名字或者函数的参数。
第一个字符必须是字母或_或$,其他字符可以是字母、_、$、数字

3.3 变量

在函数中使用var定义的变量是局部变量,这个变量在函数退出后会被销毁,因此在外部不能访问了
在函数内部省略var操作符可以定义全局变量,但不推荐,会导致不必要的混乱
可以使用一条语句定义多个变量,中间用逗号分隔

3.4 数据类型

JS中有5中基本(标准)类型undefined null boolean number string和一种对象类型Object

3.4.1 typeof操作符

typeof可以识别标准类型(null除外)不能识别具体的对象类型(function除外)
如果这个值未定义则结果是undefined
如果这个值是对象或null则结果是object
如果这个值是函数则结果是function
typeof是一个操作符不是函数,圆括号可用,但不是必须

3.4.2 undefined类型

对未初始化的变量执行typeof操作符会返回undefined值,而对未声明的变量执行typeof操作符同样会返回undefined值

3.4.3 null类型

null值表示一个空指针对象,而这也正是使用typeof操作符检测null值会返回object的原因。
如果定义的变量准备在将来用于保存对象,那么最好将该变量初始化为null,这样一来只要检查null值就可以知道相应的变量是否已经保存一个对象的引用

3.4.4 boolean类型

可以对任何数据类型的值调用boolean()函数,而且该值总会返回一个boolean值 在if语句中很重要,会自动调用boolean函数

3.4.5 number类型

在进行算术计算时,所有八进制和十六进制表示的数值都将被转化为十进制数值
isFinite()在参数位于最小和最大数值之间时会返回true
任何涉及NaN的操作都会返回NaN,NaN与任何值都不相等,包括NaN本身
isNaN()函数在接到值后会尝试将这个值转化为数值,不能转为数值的这个函数返回false
在基于对象调用isNaN()函数时,会首先调用对象的valueOf()方法,如果不能转化为数值则再调用toString()方法,再测试返回值。这个过程也是ECMAscript种内置函数和操作符的一般执行流程。
有3个函数可以把非数值转化为数值(返回的是NaN或十进制的数值)

  • number()可用于任何数据类型
  • parseInt()函数会忽略字符串前的空格,如果第一个字符不是数字或负号会返NaN,若是数字继续解析第二个,直到解析完所有后续字符或者遇到了一个非数字字符为止。
    parseInt(“oxAF”,16)指定基数16作为第二个参数,返回的是十进制的数
  • parseFloat()从第一个字符解析直到遇见一个无效的浮点数字字符为止,(第二个小数点无效),只解析十进制值,其他进制值返回0
3.4.6 string类型
var text="this is the letter sigma:\u03a3.";
alert(text.length);     //28    6个字符长的转义序列表示1个字符

数值、布尔值、对象、字符串值都有tostring()方法,null undefined没有该方法
默认情况下tostring()方法以十进制格式返回数值的字符串表示,通过传递基数可以输出其他进制格式
在不知道要转化的值是不是null undefined的情况下,可以使用string()函数string(null); //"null"

3.4.7 object类型

object的每个实例都具有下列属性:

  • constructor:保存着用于创建当前对象的函数
  • hasownproperty(propertyname):用于检查给定的属性在当前对象实例中(而不是在实例的原型中)是否存在.ropertyname必须以字符串形式指定
  • isprototypeof(object):用于检查传入的对象是否是另一个对象的原型
  • propertyIsEnumberable(propertyname):用于检查给定的的属性能否使用for -in语句来枚举
  • toLocaleString():返回对象的字符串表示,该字符串与执行环境的地区对应
  • toString()返回对象的字符串表示
  • valueof()返回对象的字符串、数值或布尔值

3.5 操作符

3.5.1 一元操作符

前置递增或递减操作符时,变量的值都是在语句被求值以前改变的
后置递增或递减操作是在包含他们的语句被求值之后才执行的
这4个操作符还可以用于字符串、布尔值、浮点数值和对象

3.5.3 布尔操作符
  1. 逻辑非操作符 !
    首先会将它的操作数转换为一个布尔值,然后再求其反。同时使用两个逻辑非操作符会将一个值转化为与其对应的布尔值,相当于boolean()
  2. 逻辑与操作符 &&
    逻辑与操作可以应用于任何类型的操作数,而不仅仅是布尔值。在有一个操作数不是布尔值的情况下,逻辑与操作不一定返回布尔值
    如果第一个操作数的布尔值为false,则不解析第二个操作数直接返回第一个操作数,如果第一个的布尔值为true第二个操作数的布尔值为false,则返回第二个操作数
    如果有一个操作数为null或NaN或undefined则返回null NaN undefined
  3. 逻辑或操作符 ||
    逻辑或操作可以应用于任何类型的操作数,而不仅仅是布尔值。在有一个操作数不是布尔值的情况下,逻辑与操作不一定返回布尔值
    如果第一个操作数的布尔值为true,则不解析第二个操作数直接返回第一个操作数,如果第一个的布尔值为false第二个操作数的布尔值为true,则返回第二个操作数
    如果有一个操作数为null或NaN或undefined则返回null NaN undefined
3.5.4 乘性操作符

在操作数为非数值的情况下会自动执行隐式类型转换
求模

var result = 26 % 5;  //1
var re = 5 % 26;  //5 当被除数小于除数时结果直接返回被除数

如果操作数都是数值。执行常见的除法计算,返回出的的余数

3.5.5 加性操作符

加法
如果有一个操作数是字符串,则将另一个操作数转化为字符串,再拼接起来
如果有一个操作数是对象、布尔值,则调用他们的toString()方法取得相应的字符串

3.5.6 关系操作符
3.5.7 相等操作符

相等和不相等!=——先转换为数值在比较
全等
=和不全等!==——仅比较不转换
null和undefined是相等的
null和undefined不全等 数据类型不同

3.5.8 条件操作符

var boolean_expression ? true_value : flase_value

3.5.10 逗号操作符

使用逗号操作符可以再一条语句中执行多个操作,多用于声明多个变量

3.6 语句

通过for-in 语句循环输出的属性名的顺序是不可预测的
label语句 可以再代码中添加标签,以便将来使用,

var num = 0;
outermost:
for(var i = 0;i < 10; i++){
    for(var j = 0;j <10;j++){
        if(i == 5 && j == 5){
            break outermost; 
        }
        num ++
    }
}
alert(num);

with语句的作用是将代码的作用域设置到一个特定的对象中
switch语句中可以使用任何数据类型

3.7 函数

argument.length用来确定传递进来多少个参数,arguments[0]表示第一个参数 与数组类似

第四章、变量 作用域和内存问题

4.1 基本类型的值和引用类型的值

在给变量赋值时,解析器必须确定这个值是基本类型还是引用类型
基本类型是按值访问的
引用类型是按引用访问的,其值保存在内存中,在操作对象时是操作对象的引用

4.1.1 动态的属性

对于引用类型,我们可以为其添加属性和方法,也可以改变和删除其属性和方法,但是我们不能给基本类型的值添加属性,尽管不出错

4.1.2 复制变量值

如果从一个变量向另一个变量复制基本类型的值时,会在变量对象上创建一个新值,然后把该值复制到为新变量分配的位置上,这两个值是独立的不会互相影响。
如果一个变量向另一个变量复制引用类型的值时,同样也会将存储在变量对象中的值复制一份到为新变量分配的空间中,不同的是这个副本其实是一个指针。复制操作结束后,两个变量实际上将引用同一个对象,因此改变其中一个变量就会影响另一个变量。

4.1.3 传递参数

ECMAscript中所有函数的参数都是按值传递的,基本类型值和引用类型值的传递就如同其变量的复制一样
为了证明对象是按值传递的,有下面的例子:

function setName(obj){
    obj.name = 'jesse';
    obj = new Objext();
    obj.name = 'grey';
}
var person = new Object();
setName(person);
alert(person.name);  //jesse

当函数内部重写Obj时,这个变量引用的就是一个局部对象,这个局部对象会在函数执行完毕后立即被销毁。

4.1.4 检测类型

typeof常用于检测基本数据类型(null除外)typeof null; //object typeof不能识别具体的对象类型(function除外)
如果变量是给定引用类型的实例,那么instanceof操作符就会返回trueperson instanceof Object; //true

4.2 执行环境

全局执行环境被认为是window对象,所有全局变量和函数都作为window对象的属性和方法创建的
内部环境可以通过作用域链访问所有的外部环境,但外部环境不能访问内部环境中的任何变量和函数

4.2.1 延长作用域链

try-catch语句的catch块会创建一个新的变量对象,其中包含的是被抛出的错误对象的声明
witch语句会将指定的对象添加到作用域链中

4.2.2 JS没有块级作用域

在JS中,if语句中的变量声明会将变量添加到当前的执行环境中,for语句创建的变量i即使在for循环结束后,也会依旧存在于循环外部的执行环境中。

  1. 声明变量
    使用var声明的变量会自动被添加到最接近的环境中,如果初始化变量时没有使用var,该变量会自动被添加到全局环境。在编写JS过程中,不声明而直接初始化变量是一个常见的错误做法
  2. 查询标识符
    沿着作用域链向上逐级查找,找到后即搜索停止
4.4 小结

基本类型值在内存中占据固定大小的空间,因此被保存在栈内存中
从一个变量向另一个变量复制基本类型的值,会创建这个值的一个副本
引用类型的值是对象,保存在堆内存中
从一个变量向另一个变量复制引用类型的值,复制的其实是指针,因此两个变量最终都指向同一个对象
确定一个值是哪种基本类型可以使用typeof操作符,而确定一个值是哪种引用类型可以使用instanceof
所有变量(基本类型和引用类型)都存在于一个执行环境中,这个执行环境决定了变量的生命周期
函数的局部环境不仅能访问函数作用域中的变量,而且能访问其父环境乃至全局环境中的变量

第五章、引用类型

5.2.1 检测数组

if(value instanceof Array){
    
}
if(Array.isArray(value)){
    //对数组的操作
}
5.2.2 转换方法

所有对象都有toLocalString() toString() valueOf()方法
var colors = ["red","blue","green"]; color; //red,blue,green
由于alert()要接受字符串参数,所以它会在后台调用toString()方法
join()将数组转为字符串
只接受一个参数,即用作分隔符的字符串,然后返回所有数组项的字符串

5.2.5 重排序方法

sort()方法会调用每个数组项的toString()转型方法,然后比较得到的字符串

5.2.6 数组的操作方法

contact()合并数组并返回新数组
slice()截取数组中项并返回新数组
splice()数组中项的插入删除替换,参数分别为起始位置、要删除的项数、要插入的项数。返回一个新数组,该数组中包含原数组中的删除项

5.2.8 数组的迭代方法

every(),some(), filter(), map(), forEach()

5.3 Date类型

var now = new Date(); //创建新对象自动获得当前日期和时间
Date.parse()接受一个表示日期的字符串函数,并返回相应日期的毫秒数
var someDate = new Date(“May 25,2004”)会在后台调用Date.parse()方法
Date.now()返回表示调用这个方法时的日期和时间的毫秒数

5.5 function类型

函数名仅仅是一个包含指针的变量而已

5.5.4 函数内部属性

argument 保存函数参数
argument.callee 指向拥有这个argument对象的函数
this 引用的是函数据以执行的环境对象
caller 保存着调用当前函数的函数的引用

5.5.5 函数属性和方法

属性:length prototype
方法:apply() call()这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值,真正的作用是扩充函数的作用域
它们的区别仅在于接受参数的方式不同
bind() 这个方法会创建一个函数的实例,其this值会被绑定到传给bind()函数的值。

5.6 基本包装类型

ECMA提供了3个特殊的引用类型:boolean number string
每当读取一个基本类型值的时候,后台就会创建一个对应的基本包装类型的对象

5.6.2 Number类型

toFixed()方法会按照指定的小数位返回数值的字符串表示
toExponential()方法返回以指数表示法
toPrecision()方法可能返回固定大小格式

5.6.3 String类型
  1. 字符方法
    charAt()方法以单字符字符串的形式返回给定位置的那个字符
    charCodeAt()方法以单字符编码的形式返回给定位置的那个字符

  2. 字符串操作方法
    合并
    contact()用于将一或多个字符串拼接起来,并返回拼接得到的新字符串。可以接收任意多个参数,可以拼接任意多个字符串
    截取
    基于子字符串创建新字符串的方法,都会返回被操作字符串的一个子字符串,对原始字符串无影响,第二个参数为空时默认将字符串长度作为结束位置。
    slice(子字符串的开始位置,子字符串最后一个字符后面的位置)
    参数为负数时,将负值与字符串长度相加
    substr(子字符串的开始位置,返回的字符个数)
    负的第一个参数加上字符串长度,负的第二个参数转为0
    substring(子字符串的开始位置,子字符串最后一个字符后面的位置)
    会把所有的负数转为0

  3. 字符串位置方法
    从一个字符串中搜索给定的子字符串,并返回子字符串的位置,未找到则返回-1
    indexOf()方法从字符串开头向后搜索
    lastIndexOf()方法从字符串末尾向前搜索

  4. trim()方法
    trim()返回删除前置后置所有空格后的字符串副本,对原始字符串无影响。IE9+

  5. 字符串的模式匹配方法
    match(),search(),replace(regexp对象或字符串,字符串会函数)
    split()方法基于指定的分隔符讲一个字符串分割成多个子字符串,并将结果放在一个数组中,第二个参数可以指定数组长度

第六章、面向对象的程序设计

6.1.1 属性类型及特征

ECMAScript中有两种属性类型:

  1. 数据属性

    • [[Configurable]]表示能否修改属性的特性,默认为true
    • [[Enumerable]]表示能否通过for-in循环返回属性,默认为true
    • [[Writable]]表示能否修改属性的值,默认为true
    • [[Value]]包含这个属性的数据值,默认为undefined

    要修改属性默认的特性,必须使用Object.defineProperty()方法,该方法接收三个参数:属性所在的对象,属性的名字,描述符对象。描述符对象的属性必须是:configurable,enumerable,writable,value

var person = {};
Object.defineProperty(person,'name',{
    configurable:false,  //设置为不可配置,就不能再变回可配置
    writable:false, //设置为不能修改
    value:"Jack"
});
alert(person.name);  //"Jack"
person.name = 'Greg';
alert(person.name);  //"Jack"
  1. 访问器属性
6.2.2 构造函数模式

构造函数始终都应该以一个大写字母开头,必须使用new操作符

6.2.3 原型模式

这个对象的用途是包含可以由特定的所有实例共享的属性和方法
isPrototypeOf()方法来确定对象之间是否存在指向关系
alert(Person.prototype.isPrototypeOf(person1)); //true
Object.getPrototypeOf()返回取得一个对象的原型
使用hasOnProperty()方法可以检测一个属性是存在实例中,还是存在原型中。是从Object继承来的
原型与in操作符
在单独使用时 in操作符会在对象都够访问给定属性时返回true,无论该属性存在实例中还是原型中

6.2.4 组合使用构造函数模式和原型模式
6.3.2 借用构造函数

通过使用apply()和call()也可以在新创建的对象上执行构造函数,从而实现继承

6.3.3 组合继承

将原型链和借用构造函数的技术组合到一起,使用原型链实现对原型链属性和方法的继承,而通过借用构造函数实现对实例属性的继承

第七章、函数表达式

创建函数的两种方式:
函数声明function关键字和函数表达式var functionName=function()
函数表达式在调用前必须先赋值
函数声明提升 是指在执行代码之前会先读取函数声明,这意味着可以把函数声明放在调用他的语句后面

7.1 递归

递归函数是在一个函数通过名字调用自身的情况下构成的
arguments.callee是一个指向正在执行的函数的指针,因此可以用来实现对函数的递归调用,比使用函数名更保险 在严格模式下不能通过脚本访问callee,可以使用命名函数表达式来实现相同的效果

7.2 闭包

闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的常见方式,就是在一个函数内部创建另一个函数。

7.3 模仿块级作用域

块级作用域的匿名函数的语法如下所示:

(function(){
    //块级作用域
})()

创建并立即调用一个匿名函数

第八章、BOM

8.1 window对象

全局变量不能通过delete操作符删除,而直接在window对象上的定义的属性可以。
跨浏览器取得窗口左边和上边的位置
screenTop,screenLeft表示的是从屏幕左边和上边到由window对象表示的页面可见区域的距离

var leftPos = (typeof window.screenLeft == "number") ? window.screenLeft : window.screenX;
var topPos = (typeof window.screenTop == "number") ? window.screenTop : window.screenY;

8.2 location对象

window.location和document.location引用的是同一个对象
获取查询字符串方法 //用以解析查询字符串,返回包含所有参数的一个对象

function getQueryStringArgs(){
    var qs = (location.search.length > 0 ? location.search.substring(1) : ""),
      args = {},
     items = qs.length ? qs.split("&") : [],
      item = null,
      name = null,
     value = null,
         i = 0,
       len = items.length;
    for(i = 0; i < len; i++){
        item = items[i].split("=");
        name = decodeURIComponent(item[0]);
        value = decodeURIComponent(item[1]);
        if(name.length){
            args[name] = value;
        }
      }
      return args;
}

location.href
location.reload()重新加载当前显示页(可能从缓存中加载)
location.reload(true)重新加载当前显示页(从服务器中加载)
####8.5history对象
history.go(-1);//后退一页
history.go(1);//前进一页

第九章、客户端检测

9.1 能力检测

只需要检测浏览器知否支持特定的能力

9.3 用户代理检测

检测用户使用的是PC端还是mobile端?

第十章、DOM

10.1. 节点层次

JS中所有节点类型都继承自Node类型,因此都共享这基本属性和方法
每一个节点都有一个parentNodes属性,该属性指向文档数中的父节点。
每一个节点都有一个childNodes属性,其中保存着一个NodeList类数组对象,
childNodes列表中每个节点的previousSibling和nextSibling可以访问同一列表中的其他节点
所有节点的ownerDocument属性直接指向整个文档的文档节点。
appendChild(要插入的节点)
如果传入到appendChild()中的节点已经是文档的一部分,那么结果就是该节点从原来的位置转移到新位置。
insertBefore(要插入的节点,参照节点)
replaceChild(要插入的节点,要替换的节点)
removeChild(要移除的节点)
要使用以上4个方法必须先取得父节点
cloneNode(false)浅复制,只复制节点本身
cloneNode(true)深复制,复制节点及整个节点树
Document类型
document对象是window对象的一个属性,因此可以讲其作为全局对象来访问
doucmentElement始终指向html元素
document.body始终指向body元素
docuemnt.links 包含文档中所有带href特性的a元素
getElementById() getElementsByTagName() getElementsByClassName() namedItem()
document.write() 原样写入
document.writeln()在字符串末尾添加换行符
操作特性的DOM方法分别是getAttribute(),setAttribute()和removeAttribute()
有些浏览器会将文本节点看做子节点,有些则不会,因此在执行某项操作前需要检查nodeType是否==1(表示元素节点)

第十一章、DOM扩展

11.1 选择符API

querySelectot()方法接受一个CSS选择符,返回与该模式匹配的第一个元素,未找到返回null
querySelectorAll()方法接受一个css选择符,返回与该模式匹配的所有元素,一个Nodelist实例

11.2 元素遍历

Element Traversal API为DOM元素添加了以下5个属性:

  • childElementCount返回子元素的个数(不包含文本节点及注释)
  • firstElementChild指向第一个子元素
  • lastElementChild指向最后一个子元素
  • previousElementSibling指向前一个同辈元素
  • nextElementSibling指向后一个同辈元素

支持的浏览器有IE9+ firefox3.5+ safari4+ chrome opera10+

11.3 HTML5

11.3.1 与类相关的扩充

getElementsByClassName()
支持的浏览器有IE9+ Firefox3+ Safari3.1+ Chrome Opera9.5+
classList属性,用于添加删除替换类名,支持的浏览器有Firefox3.6+ Chrome

div.classList.remove("disabled"); //删除类名
div.classList.add("current"); //添加类名
div.classList.troggle("user"); //切换类名
11.3.2 焦点管理
  1. document.activeElement属性,始终会引用DOM中当前获得了焦点的元素
  2. document.hasFocus()用于确定文档是否获得了焦点
11.3.3 HTMLDocument
  • readyState属性,通过它来实现一个文档是否已加载完成
if(document.readyState == "complete"){
    //执行操作
}
  • 标准模式与混杂模式
if(document.compatMode == "CSS1Compat"){
    //标准模式
}else{
    //混杂模式
}
  • insertAdjacentHTML(插入位置,要插入的HTML文本)
element.insertAdjacentHTML("beforebegin","<p>Hello world!</p>"); //在当前元素之前插入一个紧邻的同辈元素
element.insertAdjacentHTML("afterend","<p>Hello world!</p>");    //在当前元素之后插入一个紧邻的同辈元素
element.insertAdjacentHTML("afterbegin","<p>Hello world!</p>"); //在当前元素之下插入一个新的子元素
element.insertAdjacentHTML("beforeend","<p>Hello world!</p>");  //在当前元素之下插入一个新的子元素

11.3.7 scrollIntoView()

可以在所有html元素上调用,通过滚动浏览器窗口或某个容器元素,调用元素就可以出现在视口中

document.forms[0].scrollIntoView(true);//调用元素与视口顶部尽可能齐平
document.forms[0].scrollIntoView(false);//调用元素与视口底部尽可能齐平

第十二章、DOM2和DOM3

12.2 样式

任何支持style特性的html元素在javascript中都有一个对应的style属性,使用短划线的css属性必须转为驼峰大小写形式

特例 float

cssFloat //非IE
styleFloat //IE
12.2.1 DOM样式属性和方法
  • cssText:能够访问并重写style特性中的css代码
  • length:给定元素的css属性数量
  • parentRule:表示CSS信息的CSSRule对象
  • getPropertyCSSValue(propertyName):返回包含给定属性的CSSRule对象
  • getPropertyPriotrity(propertyName):如果给定的属性设置了important,则返回important,否则返回空字符串
  • getPropertyValue(propertyName):返回给定属性的字符串值
  • item(index):返回给定位置的CSS属性的名称
  • removeProperty(propertyName):从样式中删除给定属性
  • setProperty(propertyName,value,priority):将给定的属性设置为相应的值,并加上优先权标志
12.2.3 元素大小

获得元素的左偏移量

function getElementLeft(element){
    var actualLeft = element.offsetLeft();
    var current = element.offsetParent;

    while (current !== null){
        actualLeft += current.offsetLeft;
        current = current.offsetParent;
    }

    return actualLeft;
}
  1. 偏移量
    • offsetHeight():height+borderWidth+scrollbarHeight
    • offsetWidth():width+borderwidth+scrollbarHeight
    • offsetLeft():元素的左外边框至其父元素的左内边框之间的距离
    • offsetTop():元素的上外边框至其父元素的上内边框之间的距离
  2. 客户区大小
    • clientWidth()元素内容区宽度加上左右内边距宽度
    • clientHeight()元素内容区高度加上上下内边距高度
  3. 滚动大小
    • scrollLeft被隐藏在内容区左侧的像素宽度
    • scrollTop被隐藏才内容区上方的像素高度

第十三章、事件

13.1事件流

  • 事件冒泡即事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的节点
  • 事件捕获则与事件冒泡相反

事件流的三个阶段:

  1. 事件捕获阶段
  2. 处于目标阶段
  3. 事件冒泡阶段

13.2 事件处理程序

13.2.1 HTML事件处理程序

<input type="button" value="click Me" onclick="alert('Clicked')"/>
缺点:

  1. javascript还没加载完用户就点击,就会引发错误
  2. 这种扩展事件处理程序的作用域链在不同浏览器中会导致不同结果
  3. HTML代码与javascript代码紧密耦合,不利于后期修改维护
13.2.2 DOM0级事件处理程序
var btn = document.getElementById('mybtn');
btn.onclick = function(){
    alert("clicked");
}
13.2.3 DOM2级事件处理程序

处理指定事件程序addEventListener(事件名,事件处理程序函数,布尔值)

var btn = document.getElementById('mybtn');
var hander = function(){
    alert("clicked");
};
btn.addEventListener("click",hander,false);
//其他代码
btn.removeEventListener("click",hander,false);

布尔值为true表示在捕获阶段调用事件处理程序,布尔值为false表示在冒泡阶段调用事件处理程序,不建议在事件捕获阶段注册事件处理程序

删除事件处理程序removeEventListener(事件名,事件处理程序函数,布尔值)

addEventListener()添加的事件处理程序只能使用removeEventListener()来移除

13.3 事件对象

要阻止特定事件的默认行为,可以使用preventDefault()
要阻止事件捕获或冒泡,可以使用stopPropagation()

13.3.3 跨浏览器的事件对象
var EventUtil = {

    addHandler: function(element, type, handler){
        if (element.addEventListener){
            element.addEventListener(type, handler, false);
        } else if (element.attachEvent){
            element.attachEvent("on" + type, handler);
        } else {
            element["on" + type] = handler;
        }
    },
    
    removeHandler: function(element, type, handler){
        if (element.removeEventListener){
            element.removeEventListener(type, handler, false);
        } else if (element.detachEvent){
            element.detachEvent("on" + type, handler);
        } else {
            element["on" + type] = null;
        }
    },

    preventDefault: function(event){
        if (event.preventDefault){
            event.preventDefault();
        } else {
            event.returnValue = false;
        }
    },
    
    stopPropagation: function(event){
        if (event.stopPropagation){
            event.stopPropagation();
        } else {
            event.cancelBubble = true;
        }
    },

    getEvent: function(event){  //返回对event对象的引用,IE中event未定义,返回window.event
        return event ? event : window.event;
    },

    getTarget: function(event){ //返回事件的目标
        return event.target || event.srcElement;
    },

    getButton: function(event){
        if (document.implementation.hasFeature("MouseEvents", "2.0")){
            return event.button;
        } else {
            switch(event.button){
                case 0:
                case 1:
                case 3:
                case 5:
                case 7:
                    return 0;
                case 2:
                case 6:
                    return 2;
                case 4: return 1;
            }
        }
    },
    
    getCharCode: function(event){
        if (typeof event.charCode == "number"){
            return event.charCode;
        } else {
            return event.keyCode;
        }
    },
    
    getClipboardText: function(event){
        var clipboardData =  (event.clipboardData || window.clipboardData);
        return clipboardData.getData("text");
    },
    
    getRelatedTarget: function(event){
        if (event.relatedTarget){
            return event.relatedTarget;
        } else if (event.toElement){
            return event.toElement;
        } else if (event.fromElement){
            return event.fromElement;
        } else {
            return null;
        }
    },
    
    getWheelDelta: function(event){
        if (event.wheelDelta){
            return (client.engine.opera && client.engine.opera < 9.5 ? -event.wheelDelta : event.wheelDelta);
        } else {
            return -event.detail * 40;
        }
    },
    
    setClipboardText: function(event, value){
        if (event.clipboardData){
            event.clipboardData.setData("text/plain", value);
        } else if (window.clipboardData){
            window.clipboardData.setData("text", value);
        }
    }
};

13.4 事件类型

13.4.1 UI事件
  • load
  • upload 当页面完全卸载后在window上触发
  • abort
  • select 当用户选择文本框中的一个或多个字符时触发
  • error 当发生JS错误时在window上触发
  • resize 当窗口或框架的大小变化时在window或框架上触发
  • scroll 当用户滚动带滚动条的元素中的内容时,在该元素上触发
13.4.2 焦点事件

blur在元素失去焦点时触发,不冒泡
focusout在元素失去焦点时触发,冒泡
focus在元素获得焦点时触发,不冒泡
focusin在元素获得焦点时触发,冒泡

13.4.3 鼠标与滚轮事件
  • click
  • dbclick
  • mousedown
  • mouseup
  • mousemove
  • mouseenter 鼠标光标从目标元素外部首次移动到元素范围之内时触发,不冒泡,光标移到其后代元素上也不会触发
  • mouseleave 鼠标光标从目标元素上方首次移动到元素范围之外时触发,不冒泡,光标移到其后代元素上也不会触发
  • mouseover 鼠标光标从目标元素外部首次移动到相关元素范围之内时触发,相关元素可以是目标元素的外部元素或子元素
  • mouseout 鼠标光标从目标元素上方首次移动到相关元素范围之内时触发,相关元素可以是目标元素的外部元素或子元素
13.4.7 HTML5事件

contextmenu() 通过点击鼠标右键可以调出上下文菜单
beforeunload()在浏览器页面卸载前触发
DOMContentLoaded()在形成完整的DOM树之后触发
readystatechange()
pageshow() pagehide()
hashchange()

13.4.8 设备事件

orientationchange()横竖屏切换时触发

13.4.9 触摸与手势事件

触摸事件

  • touchstart
  • touchmove
  • touchend
  • touchcancel

手势事件

  • gesturestart
  • gesturechange
  • gestureend

属性

  • rotation 手势变化引起的旋转角度,负值表示逆时针旋转,正值表示顺时针旋转
  • scale 两个手指间距离的变化情况
13.5 内存和性能

事件委托,利用了事件冒泡,只指定一个事件处理程序,就可以管理一类型所有事件

var list = document.getElementById("myLinks");

EventUtil.addHandler(list, "click", function(event){
    event = EventUtil.getEvent(event);
    var target = EventUtil.getTarget(event);

    switch(target.id){
        case "doSomething":
            document.title = "I changed the document's title";
            break;

        case "goSomewhere":
            location.href = "http://www.wrox.com";
            break;

        case "sayHi":
            alert("hi");
            break;
    }
});

优点:

  1. document很快就可以访问,在页面生命周期任何时间点上添加事件处理程序
  2. 只添加一个事件处理程序所需的DOM引用更少
  3. 整个页面占用内存更少

最适合采用事件委托技术的事件包括click mousedown mouseuo keydown keyup keypress

13.5.2 移除事件处理程序

在页面卸载之前,先通过onunload事件处理程序移除所有事件

第十四章、表单脚本

14.1 表单基础知识

常用的表单提交按钮

<input type="submit" value="Submit from">  //通用提交按钮
<button type="submit">submit from<\/button> //自定义提交按钮
<input type="image" src="graphic.gif">  //图像按钮
14.1.3 表单字段

每个表单都有elements属性,该属性时表单中所有表单元素的集合,可以按照位置和name属性来访问

var filed = form.elements['textbox1'];
//避免多次提交表单
EventUtil.addHandler(form,"submit",function(event){
    event = EventUtil.getEvent(event);
    var target = EventUtil.getTarget(event);
    var btn = target.elements["submit-btn"];
    btn.dsiabled = true;
})

14.2 文本框脚本

  • size指定文本框中能够显示的字符,
  • maxlength指定文本框可以接受的最大字符数
  • select()方法用于选择文本框中的所有文本
  • select事件,只有用户选择了文本,才会触发select事件
14.2.1 选择文本
  1. 取得选择的文本
function getSelectedText(textbox){
    if(typeof textbox.selectionStart == "number"){
        return textbox.value.substring(textbox.selectionStart,textbox.selectionEnd);
    }else if(document.selection){
        return document.selection.createRange().text;
    }
}
  1. 选择部分文本
function selectText(textbox, startIndex, stopIndex){
    if (textbox.setSelectionRange){
        textbox.setSelectionRange(startIndex, stopIndex);
    } else if (textbox.createTextRange){
        var range = textbox.createTextRange();
        range.collapse(true);
        range.moveStart("character", startIndex);
        range.moveEnd("character", stopIndex - startIndex);
        range.select();                    
    }
    textbox.focus();
}

操作剪贴板

14.2.3 自动切换焦点

在自动切换焦点之前必须知道用户已经输入了既定长度的数据maxlength

<input type="text" name="tel1" id="txtTel1" size="3" maxlength="3" >
<input type="text" name="tel2" id="txtTel2" size="3" maxlength="3" >
<input type="text" name="tel3" id="txtTel3" size="4" maxlength="4" >
(function(){

    function tabForward(event){            
        event = EventUtil.getEvent(event);
        var target = EventUtil.getTarget(event);
        
        if (target.value.length == target.maxLength){
            var form = target.form;
            
            for (var i=0, len=form.elements.length; i < len; i++) {
                if (form.elements[i] == target) {
                    if (form.elements[i+1]){
                        form.elements[i+1].focus();
                    }
                    return;
                }
            }
        }
    }
                
    var textbox1 = document.getElementById("txtTel1"),
        textbox2 = document.getElementById("txtTel2"),
        textbox3 = document.getElementById("txtTel3");
    
    EventUtil.addHandler(textbox1, "keyup", tabForward);        
    EventUtil.addHandler(textbox2, "keyup", tabForward);        
    EventUtil.addHandler(textbox3, "keyup", tabForward);        
        
})();

14.2.4 HTML5 约束验证API

  1. 必填字段 required属性
  2. input新类型email url
  3. pattern属性<input type="text" pattern="\d+" name="count">

第十五章、使用Canvas绘图

15.1 基本用法

IE9+,firefox1.5+,safari2+,chrome支持<canvas>
要使用<canvas>元素,必须先设置其width和height属性,指定可以绘图的区域的大小
在使用<canvas>元素之前,首先要检测getContext()方法是否存在

if(drawing.getContext){
    var context = drawing.getContext('2d');
    //more code
}

使用toDataURL()方法可以导出在canvas元素上绘制的图像

15.2 2D上下文

15.2.2 绘制矩形

fillRect(x,y,width,height)方法在画布上绘制的矩形会填充指定的颜色

context.fillStyle = "rgba(0,255,0,0.5)";
context.fillRect(10,10,50,50);

strokeRect()方法在画布上绘制的矩形会使用指定的颜色描边

context.strokeStyle = "red";
context.strokeRect(10,10,50,50);

clearRect()方法用于清除画布上的矩形区域,本质上可以把绘制上下文中的某一矩形区域变透明

context.clearRect(40,40,10,10);

15.2.3 绘制路径

要绘制路径首先必须调用beginPath()方法,表示开始绘制路径

  • arc(x,y,radius,startAngle,endAngle,counterclockwise)
  • acrTo(x1,y1,x2,y2,radius)从上一点开始绘制一条弧线,到(x2,y2)为止,并以给定的半径穿过(x1,y1)
  • bezierCurveTo(c1x,c1y,c2x,c2y,x,y)
  • lineTo(x,y)从上一点开始绘制一条直线,到(x,y)为止
  • moveTo(x,y)将绘图游标移动到(x,y),不画线
  • quadraticCurveTo(cx,cy,x,y)
  • rect(x,y,width,height)
  • closePath()闭合路径
  • fill()填充路径
  • stroke()描边路径
  • clip()创建剪切区域

15.2.4 绘制文本

fillText(str,x,y);

15.2.5 变换
  • rotate(angle):围绕原点旋转图像angle弧度
  • scale(scalex,scaley):缩放图像
  • translate(x,y):将坐标原点移动到(x,y)
  • save()方法保存的只是对绘图上下文的设置和变换

文章目录

  1. 第二章、在HTML中使用Javascript
    1. 2.1 script
    2. 2.1.2 延迟脚本
    3. 2.1.3 异步脚本
  2. 第三章、基本概念
    1. 3.1.2 标识符
    2. 3.3 变量
    3. 3.4 数据类型
      1. 3.4.1 typeof操作符
      2. 3.4.2 undefined类型
      3. 3.4.3 null类型
      4. 3.4.4 boolean类型
      5. 3.4.5 number类型
      6. 3.4.6 string类型
      7. 3.4.7 object类型
    4. 3.5 操作符
      1. 3.5.1 一元操作符
      2. 3.5.3 布尔操作符
      3. 3.5.4 乘性操作符
      4. 3.5.5 加性操作符
      5. 3.5.6 关系操作符
      6. 3.5.7 相等操作符
      7. 3.5.8 条件操作符
      8. 3.5.10 逗号操作符
    5. 3.6 语句
    6. 3.7 函数
  3. 第四章、变量 作用域和内存问题
    1. 4.1 基本类型的值和引用类型的值
      1. 4.1.1 动态的属性
      2. 4.1.2 复制变量值
      3. 4.1.3 传递参数
      4. 4.1.4 检测类型
      5. 4.2 执行环境
      6. 4.2.1 延长作用域链
      7. 4.2.2 JS没有块级作用域
      8. 4.4 小结
  4. 第五章、引用类型
    1. 5.2.1 检测数组
      1. 5.2.2 转换方法
      2. 5.2.5 重排序方法
      3. 5.2.6 数组的操作方法
    2. 5.2.8 数组的迭代方法
    3. 5.3 Date类型
    4. 5.5 function类型
      1. 5.5.4 函数内部属性
      2. 5.5.5 函数属性和方法
    5. 5.6 基本包装类型
    6. 5.6.2 Number类型
      1. 5.6.3 String类型
  5. 第六章、面向对象的程序设计
    1. 6.1.1 属性类型及特征
      1. 6.2.2 构造函数模式
      2. 6.2.3 原型模式
      3. 6.2.4 组合使用构造函数模式和原型模式
      4. 6.3.2 借用构造函数
      5. 6.3.3 组合继承
  6. 第七章、函数表达式
    1. 7.1 递归
    2. 7.2 闭包
    3. 7.3 模仿块级作用域
  7. 第八章、BOM
    1. 8.1 window对象
    2. 8.2 location对象
  8. 第九章、客户端检测
    1. 9.1 能力检测
    2. 9.3 用户代理检测
  9. 第十章、DOM
    1. 10.1. 节点层次
  10. 第十一章、DOM扩展
    1. 11.1 选择符API
    2. 11.2 元素遍历
    3. 11.3 HTML5
      1. 11.3.1 与类相关的扩充
      2. 11.3.2 焦点管理
      3. 11.3.3 HTMLDocument
    4. 11.3.7 scrollIntoView()
  11. 第十二章、DOM2和DOM3
    1. 12.2 样式
      1. 12.2.1 DOM样式属性和方法
      2. 12.2.3 元素大小
  12. 第十三章、事件
    1. 13.1事件流
    2. 13.2 事件处理程序
      1. 13.2.1 HTML事件处理程序
      2. 13.2.2 DOM0级事件处理程序
      3. 13.2.3 DOM2级事件处理程序
    3. 13.3 事件对象
      1. 13.3.3 跨浏览器的事件对象
    4. 13.4 事件类型
      1. 13.4.1 UI事件
      2. 13.4.2 焦点事件
      3. 13.4.3 鼠标与滚轮事件
      4. 13.4.7 HTML5事件
      5. 13.4.8 设备事件
      6. 13.4.9 触摸与手势事件
      7. 13.5 内存和性能
      8. 13.5.2 移除事件处理程序
  13. 第十四章、表单脚本
    1. 14.1 表单基础知识
      1. 14.1.3 表单字段
    2. 14.2 文本框脚本
      1. 14.2.1 选择文本
    3. 14.2.3 自动切换焦点
    4. 14.2.4 HTML5 约束验证API
  14. 第十五章、使用Canvas绘图
    1. 15.1 基本用法
    2. 15.2 2D上下文
      1. 15.2.2 绘制矩形
      2. 15.2.3 绘制路径
      3. 15.2.4 绘制文本
      4. 15.2.5 变换