javaScript第四版通读第二遍:
第一章:什么是JavaScript
js组成部分:
核心(ECMAScript):
即ECMA-262定义的语言,但不局限于浏览器。他包含了以下部分:语法、类型、关键字、保留字、操作符、全局对象。
文档对象模型(DOM):
应用编程接口(API),用于在HTML中使用扩展的XML。
浏览对象模型(BOM):
浏览器对象模型
第二章:HTML中的javaScript
script元素属性:
属性名 | 描述 |
---|---|
async | 表示异步,意思是立即下载脚本,但不能阻碍其他动作的执行。此属性只对外部脚本起作用 |
charset | 使用src属性指定的代码字符集。 |
crossorigin | 配置相关请求的CORS(跨域资源共享)设置。 |
defer | 表示脚本可以延迟到文档完全被解析和显示之后再执行。只对外部脚本文件有效 |
integrity | 允许比对接收到的资源和指定的加密签名以验证子资源完整性(SRI,Subresource Integrity)。 |
type | 表示代码块中脚本语言的内容类型。 |
第三章:语言基础
开启严格模式:
在脚本头部加上:“use strict”;
保留字:
变量:
使用var、let、const来声明变量。并保持用驼峰命名法
var:
会产生函数作用域,变量提升。
let:
会产生块级作用域,不会产生变量提升,就是说会产生暂时性死区。
const:
与let基本相同,但是他是用来声明常量,值不能改变。但是const引用的是对象的话,改变对象内部属性则不会报错。
数据类型:
7种,使用typeof来检测类型。
类型 | 描述 |
---|---|
undefined | 变量声明了,但是没有赋值。 |
Null | 空,表示一个空对象指针。 |
Boolean | true(真)或false(假) 非空字符串转换为true,空字符串为false 非0数值(包括无穷值)转换为true,0、NaN为false 任意对象转换为true,Null转换为0 Undefiend不能转换为布尔值。 |
Number | 数字类型。 |
String | 字符串类型 |
Symbol | 唯一标识符 |
Object | 无序名值的集合 |
Number类型:
1,整数值:十进制直接写,八进制第一个数字必须是0,十六进制前缀加0x 2,浮点值:要定义浮点值,数值中必须加小数点。
Srting类型:
表示0或多个16位,Unicode字符序列。并且不可改变。可以重新赋值,但是老值会被覆盖。包括toString(),
Symbol类型:
唯一标志符。
Obeject类型:
本质是一组数据和功能的集合。此类型也是派生其他对象的基类
属性 | 描述 |
---|---|
constructor | 用于创建当前对象的函数。 |
hasOwnProperty(property) | 用于判断当前对象实例(不是原型)上是否存在给定的属性。参数必须是字符串。 |
isPrototypeOf(Object) | 用于判断当前对象是否是另一个对象的原型。 |
propertyIsEnumerable(propertyName) | 用于判定给定的属性是否可以使用for-in枚举。 |
toLocaleString() | 返回对象的字符串表示。该字符串反应对象所在的本地执行环境 |
toString() | 返回对象的字符串表示。 |
valueOf() | 返回对象对应的字符串、数值或布尔值表示。 |
语句:
IF语句:
条件语句,语法:if(condition) statement else statement2
dowhile语句:
后测试语句,最少执行一次 语法:do{statement}while(expression);
while语句
先测试语句,有可能不执行 语法:while(expression)statement
for语句
先测试语句, 语法:for(initialization;expression;post-loop-expression){statement}
for...in语句:
是一种严格的迭代语句,用于枚举对象的非符号键属性 语法:for(property in expression){statement}
for...of语句:
是一种严格的迭代语句,用于遍历可迭代对象的元素, 语法:for(property of expression){statement}
标签语句:
用于给语句加标签, 语法:label:statement
break和continue语句:
break为立即退出,continue为跳过
with语句:
将代码作用域设置为特定的对象l 语法:with(expression) ststement 警告:由于with语句影响性能且难于调试其中的代码,通常不推荐在产品中使用with语句
switch语句:
跟if差不多,语法是: switch(expression){case value1:statement break;......default statement}
函数:
基本语法:function functionName(arg1,arg2...){statements}
第四章:变量,作用域与内存
原始值与引用值:
原始值:最简单的数据。复制原始值的时候是复制了原始值 的副本,两者互不影响 引用值:由多个值构成的对象。引用值复制的时候复制的是指针。
作用域:作用域是基于函数的,
上下文是基于对象的,通常是指this关键字的值。
第五章:基本引用类型
暂时掠过
第六章:集合引用类型
Object:
创建方式:new 和使用构造函数还有对象字面量
Array:
创建方式:new和使用数组构造函数,还有数组字面量、Array.form和Array.of。 检测方式:instanceof 和isArray() 迭代器方法:keys()、values()、entries()。 复制和填充方法:copyWithin()、fill()、 转换方法:tolocaleString()、toString()、valueOf() 栈方法:pop()和push() 队列方法:shift()和push()、unshift()和pop() 排序方法:reverse()、sort()、 操作方法:concat()、slice(),splice() 搜索和位置方法: 严格相等:indexOf()、lastIndexOf(),includes() 断言函数:find()、findIndex() 迭代方法:every()、filter()、forEach()、map()、some() 归并方法:reduce()、reduceRight()
定型数组:
目的是提升向原生库传输数据的效率。他所指的就是一种特殊的包含数值类型的数组。
Map:
新增的集合类型,为js带来了真正的键值存储机制。
基本Api:
使用new来创建一个map空映射a 初始化后可以用set()来添加键值对,get()和has()来查询,size属性来获取映射中键值对的数量,还可以用clear()和delete()来删除值。
顺序与迭代:
与object不同,Map实例会维护键值对的插入顺序。因此可以按照插入顺序进行迭代操作。
选择Object还是Map:
1,内存占用:如果给定固定大小的内存,Map比Object多存储50%的键值对。 2,插入性能:Map比Object快。 3,查找速度:大型项目中一样,如果只包含少量键值对,那Object快, 4,删除性能:使用Map更佳。
WeakMap:
es6新增的弱映射,
基本api:
同样使用new关键字实例化一个空WeakMap;弱映射中的键只能是object或者继承自object的类型。尝试使用非对象设置键则会抛出typeerror错误。值的类型没有限制。
弱键:
弱键不属于正式的引用,不会阻止垃圾回收。但是只要键存在,键值对就会存在于映射中,并被当作对值的引用。因此不会被当作垃圾回收。
set:
是es6新增的集合类型。在很多方面set都像是加强版的Map,因为他们大多数的api和行为都是共有的。
基本api:
同样使用new关键字和set构造函数可以创建一个空集。 add()增加值,has()查询,size属性获取元素数量,delete()和clear()删除元素。
顺序与迭代:
支持按顺序迭代。
weakset:
es6新增的弱集合。
第七章:迭代器与生成器
大意:按照顺序反复多次执行一段程序。通常会有明确的终止条件。
迭代器模式:
Iterable:可迭代对象 Iterator:迭代器
如果对象实现了正式的Iterable接口,而且可以通过迭代器消费,可迭代对象指的是数组或者集合这样的集合类型的对象。他们包含的元素都是有限的,而且都是无歧义的遍历。任何实现iterable接口的数据结构都可以被实现iterator接口的结构消费。迭代器是按需创建的一次性对象。每个迭代器都会关联一个可迭代对象,而迭代器会暴露迭代其关联可迭代对象的api。迭代器无需了解与其关联的可迭代对象的结构。只需要知道如何取得连续的值。这种概念上的分离正是iterable和iterator的强大之处。
可迭代协议:
实现Iterable接口(可迭代协议)要求同时具备两种能力: 1,支持迭代的自我识别能力和创建Iterator接口的对象的能力。在ECMAScript中,这意味着必须暴露一个属性作为”默认迭代器“,而且这个属性必须使用特殊的Symbol.iterator作为键。这个默认迭代器属性必须引用一个迭代器工厂函数,调用这个工厂函数必须返回一个新迭代器。已经实现了Iterable接口的内置类型有:字符串,数组,映射,集合,arguments对象,NodeList等DOM集合类型。
迭代器协议:
迭代器是一种一次性使用的对象,用于迭代与其关联的可迭代对象,迭代器API使用next()方法在可迭代对象中遍历数据。每次成功调用next(),都会返回一个Iterato'rResult对象,其中包含迭代器返回的下一个值。若不调用next(),则无法知道迭代器当前的位置。 IteratorResult包含两个属性:done和value。done是一个布尔值,表示是否还可以再次调用next()取得下一个值;value包含可迭代对象的下一个值(此时done为false),或者undefined(done为true)。
自定义迭代器:
与 Iterable 接口类似,任何实现 Iterator 接口的对象都可以作为迭代器使用。
提前终止迭代器:
可选得return()方法用于指定再迭代器提前关闭时执行得逻辑。执行迭代得结构再想让迭代器知道他不想遍历到可迭代对象耗尽时,就可以“关闭“迭代器。可以通过以下操作来关闭:for-of循环通过break、continue、return、或throw提前退出,解构操作并未消费所有值。
生成器:
生成器时es6新增得一个极为灵活得结构,拥有在一个函数块内暂停和恢复代码执行得能力
生成器基础:
生成器得形式是一个函数,函数名称前面加一个(*)号表示他是一个生成器。只要是可以定义函数得地方,就可以定义生成器。但是箭头函数不能用来定义生成器函数。
通过yield中断执行:
yield关键字可以让生成器停止和开始执行,也是生成器最有用得地方。遇到之前函数正常执行,遇到后执行会停止,函数作用域得状态会被保留。如果想恢复,则需要在函数上调用next()方法来恢复执行。
第八章:对象、类与面向对象编程:
对象得定义:ECMA-262将对象定义为一组属性得无序集合。对象得每个属性或方法都由一个名称来标识,这个名称映射到一个值。正因为如此,可以把对象想想成一张散列表。其中得内容就是一组名/值对,值可以是数据或函数。
理解对象:
创建自定义对象得通常方式是使用new关键字创建Object得一个新实例,然后再给他添加属性和方法。
属性得类型:
分两种:数据属性和访问器属性。
数据属性:
这个属性包含一个保存数据值得位置。有以下四个特性:
特性名 | 描述 |
---|---|
Configgurable(可配置得) | 表示属性是否可以通过delete删除并重新定义,是否可以修改他得特性,以及是否可以把他改为访问器属性。默认都是true。 |
Enumerable(可枚举得) | 表示属性是否可以通过for-in循环返回。默认都是ture |
Writable(可写得) | 表示属性值是否可以被修改,默认是true |
Value(属性) | 包含属性实际得值。这就是读取和写入属性值得位置,默认为undefined |
要修改属性得默认特性,需要使用Object.defineProperty()方法。此方法接收三个参数,要给其添加属性得对象、属性得名称和一个描述符对象。最后一个参数,即描述符对象上得属性可以包括Configgurable,Enumerable,Writable和Value。
访问器属性:
访问器属性不包含数据值。相反,他们包含一个获取(getter)函数和一个设置(setter)函数。getter函数返回一个有效得值。访问器属性有4个特性:
特性 | 描述 |
---|---|
Configgurable(可配置得) | 表示属性是否可以通过delete删除并重新定义,是否可以修改他得特性,以及是否可以把他改为数据属性。默认都是true |
Enumerable(可枚举得) | 表示属性是否可以通过for-in来循环返回。默认都是true |
[[Get]]:获取函数 | 读取属性时调用,默认undefined |
[[Set]]:设置函数 | 写入属性时调用,默认undefined |
访问器属性不能直接定义,必须使用Object.defineProperty()方法。
定义多个属性:
如果想在一个对象上同时定义多个属性,那么使用Object.defineProperties()方法。这个方法可以通过多个描述符一次性定义多个属性。接受两个参数:要为之添加或修改属性得对象和另一个描述符对象,其属性与要添加或修改得属性一一对应。添加或修改后configurable、enumerable、writable特性值都是false
读取属性特性:
使用Object.getOwnPropertyDescriptor()方法可以取得指定属性得属性描述符。此方法接受两个参数:属性所在得对象和要去的其描述符得属性名。返回值是一个对象
合并对象:
es6专门为合并对象提供了Object.assign()方法。此方法接受一个目标对象和一个或多个源对象作为参数。然后将每个源对象中可枚举(Object.propertyIsEnumerable()返回true)和自有(Object.hasOwnProperty()返回ture)属性复制到目标对象。
对象标识及相等判定:
es6新增了Object.is()方法,此方法接受两个参数(要比对得值,比对值)。
增强得对象语法:
1,属性值简写:
简写属性名只要使用变量名(不用再写冒号)就会自动解释为同名得属性键位,如果没有找到同名变量,则会抛出ReferenceError(引用错误)
2,可计算属性:
const nameKey = 'name'; const ageKey = 'age'; const jobKey = 'job'; let person = { [nameKey]:'黄', [ageKey]:26, [jobKey]:"Web" };
3,简写方法名:
let person={ sayName:function(name){ console.log(`My name is ${name}`); } }; 简写: let person={ sayName(name){ console.log(`My name is ${name}`); } }
对象解构:
es6新增了对象解构语法,可以在一条语句中使用嵌套数据实现一个或多个赋值操作。简单来说,对象解构就是使用与对象匹配得结构来实现对象属性赋值。
let person ={ name:'huang', age:26 }; // let personName = person.name, // personAge = person.age; let {name:personName,age:personAge,job:'web'}=person; console.log(personName); console.log(personAge);
解构赋值得同时可以定义默认值
创建对象:
工厂模式:
工厂模式是一种众所周知得设计模式,广泛应用于软件领域,用于抽象创建对象得过程。这种模式虽然可以解决创建多个类似对象得问题,但没有解决对象标识问题(即新创建得对象是什么类型)
function createPerson(name,age,job){ let o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName=function(name){ // console.log(this.name); return this.name; } return o; } let person1 = new createPerson("name1",26,"web") let person2 = new createPerson("name2",25,"student") console.log(person1); console.log(person2.sayName());
构造函数模式:
function Person(name, age, job) { this.name = name; this.age = age; this.job = job; this.sayName=sayName; } function sayName(){ console.log(this.name); }
与工厂模式得区别在于没有显式得创建对象。属性和方法直接赋值给了this。没有return。首字母大写(惯例,并不是必须。)。 构造函数使用new操作符,以这种方式调用构造函数会执行如下操作:1,在内存中创建一个新对象。2,这个新对象内部的[[Prototype]]特性被赋值为构造函数的prototype属性。3,构造函数内部的this被赋值为这个新对象(即this指向新对象)。4,执行构造函数内部的代码(给新对象添加属性)。5,如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象。 构造函数的问题:其定义的方法会在每个实例上都创建一遍,如果想解决,那就把函数定义转移到构造函数外部。但是会产生新得问题,因为在构造函数内部sayName属性等于全局sayName()函数。因为构造函数里的sayName属性中包含的只是一个指向外部函数的指针,所以实例化的对象共享了定义在全局作用域上的sayName()函数,这会搞乱全局作用域。因为那个函数实际上只能在一个对象上调用,如果这个对象需要多个方法,那么就要在全局作用域中定义多个函数。这会导致自定义类型引用的代码不能很好的聚集在一起,这个新问题可以通过原型模式来解决。
原型模式:
每个函数都会创建一个portotype属性,这个属性是一个对象,包含应该由特性引用类型的实例共享的属性和方法。实际上,这个对象就是通过调用构造函数创建的对象的原型。使用原型对象的好处是,在他上面定义的属性和方法可以被对象实例共享。原来在构造函数中直接赋给对象实例的值,可以直接赋值给他们的原型。
理解原型:
只要创建一个函数,就会按照特性的规则为这个函数创建一个prototype属性(指向原型对象)。默认情况下,所有原型对象自动获得一个名为constructor的属性,指回与之关联的构造函数。判断是不是原型使用isPrototypeOf();Object类型还有一个setPrototypeOf(),可以向实例的私有特性写入一个新值。但是这个方法可能会严重影响代码性能。可以通过hasOwnProperty(用于确定某个属性是在实例上还是原型对象上,如果存在实例上返回true,如果在原型上,返回false)
原型和in操作符:
有两种方式使用in操作符:单独使用和在for-in循环中使用。只要通过对象可以访问,in操作符就返回true,而hasOwnProperty()只有属性存在实力上时才返回true。因此,只要in操作符返回true且hasOwnProperty()返回false,就说明该属性是一个原型属性。
属性枚举顺序:
for-in循环、Object.keys()、Object.getOwnPropertyNames()、Object.getOwnPropertySymbols()以及Object.assign()在属性枚举方面有很大区别。for-in循环和Object.keys()的枚举顺序是不确定的,取决于js引擎。Object.getOwnPropertyNames()、Object。getOwnPropertySymbols()和Object.assign()的枚举顺序是确定的,先以升序枚举数值键,然后以插入顺序枚举字符串和符号键。在对象字面量中定义的键以他们逗号分隔的顺序插入。
对象迭代:
es6新增了两个静态方法:Object.values()和Object.entries()接受一个对象,返回他们内容得数组。Object.values()返回对象值得数组,Object.entries()返回键值对得数组。
继承:
继承分为接口继承和实现继承,js支持实现
默认继承:
所有引用类型都继承自Object,任何函数的默认原型都是一个Object的实例。
原型与继承关系:
原型与实例的关系可以通过两种方式来确定,第一种instanceof,isPortotypeOf
关于方法:
子类有时候需要覆盖父类的方法,或者增加父类的方法,为此,这些方法必须在原型赋值之后再添加到原型上。
原型链的问题:
原型中包含的引用值会再所有实例中共享。
盗用构造函数:
基本思路:在子类构造函数中调用父类构造函数。因为毕竟函数就是在特定上下文中执行代码的简单对象。所以可以用apply和call方法以新创建的对象为上下文执行构造函数
1,传递参数:
相比于使用原型链、盗用构造函数得一个优点就是可以在子类构造函数中向父类构造函数传参。
2,盗用构造函数得问题:
必须在构造函数中定义方法,因此函数不能重用。此外,子类也不能访问父类原型上定义得方法,因此所有类型只能使用构造函数模式。由于存在这些问题,盗用构造函数基本上也不能单独使用。
组合继承
顾名思义,组合继承综合了原型链和盗用构造函数,有一个效率问题,组合继承会造成父类构造函数始终会被调用两次。一次是在创建子类原型的调用,另一次是在子类构造函数中调用。
原型式继承:
创建一个临时构造函数,将传入得对象赋值给这个构造函数得原型,然后返回这个临时类型得一个实例。此方法适用于有一个对象,想在他得基础上再创建一个新对象。es5通过增加Object.create()方法将原型式继承的概念规范化了。此方法接受两个参数:作为新对象原型的对象,以及给新对象定义额外属性的对象(第二个可选。)
寄生式继承:
思路:创建一个实现继承的函数,以某种方式增强对象,然后返回这个对象。缺点:通过寄生式继承给对象添加函数会导致函数难以重用,与构造函数类似。
寄生式组合继承:
基本思路:不公过调用父类构造函数给子类原型赋值,而是取得父类原型得一给副本。
类:
类得定义:
1类声明,类表达式。这两种方式都使用class关键字+花括号。函数声明能提升,类声明不能提升。函数受函数作用域限制,类受块作用域限制。
类的构成:
类可以包含构造函数方法、实例方法、获取函数、设置函数和静态类方法。类的首字母要大写。
类构造函数:
constructor关键字用于在类定义块内部创建类的构造函数。方法名constructor会告诉解释器在使用new操作符创建类的新实例时,应该调用这个函数。构造函数的定义不是必须的,不定义构造函数相当于将函数定义为空函数。
1,实例化
使用new调用类的构造函数会执行如下操作:首先在内存创建一个新对象,然后这个新对象内部的[[Prototype]]指针被赋值为构造函数的prototype属性。构造函数内部的this被赋值为这个新对象(即this指向新对象)。执行构造函数内部的代码(给新对象添加属性)。如果构造函数返回非空对象,则返回该对象,否则,返回刚创建的新对象。
2,以下暂时略过
第九章:代理与反射:
暂时掠过。
第十章:函数
箭头函数:
箭头函数简洁得语法非常适合嵌入函数得场景。如果只有一个参数可以不用写括号,如果没有参数或多个参数那就需要写括号。
函数名:
函数名就是指向函数得指针,使用不带括号得函数名会访问函数指针,而不会执行函数。
理解参数:
定义函数时写明要接受几个参数,不一定要传几个参数进去,也可以一个不穿。都不报错。因为ECMAScript函数得参数再内部表现为一个数组。
箭头函数中的参数:
如果函数是使用箭头语法定义的,那么传给函数的参数将不能使用arguments关键字访问, 只能通过定义的命名参数访问。 注意:ECMAScript中所有的参数都是按值传递的,不可能按引用传递参数。如果把对象作为参数传递,那么传递的值就是这个对象的引用
没有重载:
ECMASript函数没有签名,因为参数是由包含零个或多个值的数组表示的。没有函数签名,自然也就没有重载。如果定义了两个同名函数,那么后面的会覆盖前面的。
默认参数值:
es6之后支持显式定义默认参数,如function fnName(name='huang'){return King ${name} VIIE
}
参数扩展与收集:
扩展参数:
。。。,扩展操作符,对可迭代对象应用扩展操作符,并将其作为一个参数传入,可以将可迭代对象拆分,并将迭代返回的每个值单独传入。
收集参数:
再构思函数定义时,可以使用扩展操作符把不同长度得独立参数组合为一个数组。
函数声明与函数表达式:
js引擎在任何代码执行之前,会先读取函数声明,并在执行上下文中生成函数定义。而函数表达式必须等到代码执行到他哪一行,才会执行上下文中生成函数定义。
函数作为值:
因为函数名在ECMAScript中就是变量,所以函数可以用在任何可以使用变量得地方。这意味这不仅可以把函数作为参数传给另一个函数,而且还可以在一个函数中返回另一个函数。
函数内部:
es5中函数内部存在两个特殊得对象:arguments和this,es6又新增了new.target属性。
arguments:
arguments是一个类数组对象,包含调用函数时传入得所有参数。这个对象只有以function关键字定义函数(相对于使用箭头语法创建函数)时才会有。虽然主要用于包含函数参数,但arguments对象还有一个callee属性,是一个指向arguments对象所在函数得指针。
this:
谁调用我我就指向谁,call,apply可以改变this得指向。
caller:
es5也会给函数对象上添加一个属性caller,这个属性引用得是调用当前函数得函数,或者如果是全局作用域中调用得则为null。
new.target:
ECMAScript中得函数始终可以作为构造函数实例化一个新对象,也可以作为普通函数被调用。es6新增了检测函数是否使用new关键字调用得new.target属性,如果函数是正常调用得,则new.target得值是undefined,否则他将引用被调用得构造函数。
属性和方法:
每个函数都有两个属性:
属性/方法 | 描述 |
---|---|
length | 保存函数定义得命名参数得个数 |
prototype | 保存引用类型所有实例方法得地方。 |
apply() | 以指定得this值来调用函数,即设置调用函数时函数体内this对象得值。第二个参数可以是数组,也可以是arguments对象。可以改变this得指向 |
call() | 以指定得this值来调用函数,即设置调用函数时函数体内this对象得值。可以改变this得指向 |
bind() | 创建一个新得函数实例,其this值会被绑定到bind()得对象。 |
函数表达式:
匿名函数:创建一个函数再把他赋值给一个变量。function关键字后面没有标识符。
递归:
一个函数通过名称调用自己。
const factorial = (function f (num){ if(num<=1){ return 1; }else{ return num*f(num-1); } }) console.log(factorial(5));
尾调用优化:
es6新增一项内存管理优化机制,让js引擎在满足条件时可以重用栈帧,具体来说,这项优化非常适合“尾调用”,即外部函数得返回值时一个内部函数得返回值
闭包:
指的是那些引用了另一个函数作用域中变量得函数,通常是在嵌套函数中实现得。
第十一章:期约与异步函数:
期约(promise):异步程序执行的机制。
期约基础:
es6新增的引用类型Promise,可以通过new操作符来实例化。创建新期约时需要传入执行器(executor)函数作为参数;
期约状态机:
期约是一个有状态的对象:可能处于如下3中状态之一:1,pending(待定)2,兑现(fulfilled有时候也叫“解决”,resolved)3,拒绝(rejected)
解决值、拒绝理由及期约用例:
期约主要有两大用途:1,抽象的表示一个异步操作。2,期约封装的异步操作会实际生成某个值,而程序期待期约状态改变时可以访问这个值。
通过执行函数控制期约状态:
由于期约的状态是私有的,所以只能在内部进行操作。内部操作在期约的执行器函数中完成。执行器函数主要有两项职责:初始化期约的异步行为和控制状态的最终转换。其中,控制期约状态的转换通过调用他的两个函数参数实现。这两个函数通常命名为resolve()和reject(),调用resolve会把状态切换为兑现(成功),调用reject则会切换为拒绝(失败),然后抛出一个错误。
期约的实例方法:
实现Thenable接口:
在ECMAScript暴露的异步结构中,任何对象都有一个then方法。
Promise.prototype.then()
是为期约实例添加处理程序的主要方法。此方法接收两个参数:onresolved处理程序和onRejected处理程序。这两个参数都是可选的,如果提供的话,则会在期约分别进入兑现和拒绝状态时执行。
Promise.prototype.finally()
finally:最后 此方法用于给期约添加onFinally处理程序,这个程序在期约转换为解决或拒绝状态时都会执行。他可以避免onResolve和onRejected处理程序中出现多余代码。但onFinally处理程序没有办法知道期约的状态是解决还是拒绝。所以这个方法主要用于添加清理代码。
非重入期约方法:
当期约进入落定状态时,与该状态相关的处理程序仅仅会被排期,而非立即执行。跟在添加这个处理程序的代码之后的同步代码一定会在处理程序之前先执行。即使期约一开始就是与附加处理程序关联的状态,执行顺序也是这样的。这个特性被称为“非重入”
邻近处理程序的执行顺序:
如果给期约添加了多个处理程序,当期约状态变化时,相关处理程序会按照添加他们的顺序依次执行。
传递解决值和拒绝理由
在执行程序中,解决的值和拒绝的理由是分别作为resolve()和reject()的第一个参数往后传的。然后这些值又会传给他们各自的处理程序。作为onResolved和onRejected处理程序的唯一参数。
拒绝期约与拒绝处理错误:
拒绝期约类似于throw()表达式,因为他们都代表一种处理状态,即需要终端或者特殊处理。在期约的执行函数或处理程序中抛出错误会导致拒绝,对应的错误对象会成为拒绝的理由。
期约连锁与期约合成:
多个期约组合在一起可以构成强大的代码逻辑。可以通过两种方式实现:期约连锁【一个期约一个期约的拼接】与期约合成【将多个期约组合成一个期约】。
Promise.all():
Promise.all()静态方法创建的期约会在一组期约全部解决后再解决,他接收一个可迭代对象,返回一个新期约。
Promise.race():
Promise.race()静态方法返回一个包装期约,是一组集合中最先解决或拒绝的期约的镜像。此方法接受一个可迭代对象,返回一个新期约。
异步函数:
也被称为“async/await”(语法关键字),是es6期约模式在ECMAScript函数中的应用。async/await是es8新增的。主要解决利用异步结构组织代码的问题。
async:
用于声明异步函数,这个关键字可以用在函数声明、函数表达式、箭头函数和方法上。使用async关键字可以让函数具有异步特征。但总体上其代码仍然是同步求值的。而在参数或闭包方面,异步函数仍然具有普通js函数的正常行为。不过异步函数如果使用了return返回了值,这个值会被Promise。resolve()包装成一个期约对象。异步函数始终返回期约对象。在函数外部调用这个函数可以得到他返回的期约。不过拒绝期约的错误不会被异步函数捕获。
await:
因为异步函数主要针对不会马上完成的任务,所以自然需要一种暂停和恢复执行的能力。使用await关键字可以暂停异步函数代码的执行,等待期约解决。注意,await关键字会暂停执行异步函数后面的代码,让出js运行时的执行线程。这个行为与生成器函数中的yield关键字是一样的。await关键字同样是尝试“解包”对象的值,然后将这个值传给表达式,再异步恢复异步函数的执行。await关键字的用法与js的一元操作符一样,他可以单独使用,也可以再表达式中使用。
await的限制:
await关键字必须在异步函数中使用,不能在顶级上下如script标签或模块中使用。不过定义并立即调用异步是没问题的。
停止和恢复执行
暂时略过
BOM
第十二章:
window对象:
window作为BOM得核心对象,他表示浏览器得实例。window对象在浏览器中有两重身份,1,是ECNAScript中得Global对象,2,浏览器窗口得javascript接口。这意味着网页中定义得所有对象、变量和函数都以window作为其Global对象,都可以访问其上定义得parseInt()等全局方法。
Global作用域:
所有通过var声明得所有全局变量和函数都会成为window对象得属性和方法。
窗口关系:
top对象始终指向最上层(最外层)窗口,即浏览器本身。而parent对象则始终指向当前窗口得父窗口。还有就是self对象,他是终极window属性,始终指向window。实际上self和window就是同一个对象。之所以还要暴露self,就是为了和top,parent保持一致。
窗口位置与像素比:
window对象得screenLeft和screenTop属性,用于表示窗口相对于屏幕左侧和顶部得位置,返回得单位是css像素。 可以使用moveTo()和moveBy()方法移动窗口。这两个方法都接受两个参数,其中moveTo接受要移动到得新位置得绝对坐标x和y;而moveBy则接收相对于当前位置在两个方向上移动得像素数。以浏览器而定,这些方法可能部分或者全部被禁用。
窗口大小:
所有现代浏览器都支持4个属性:innerWidth、innerHeight、outerWidth、outerHegith。outerWidth和outerHeight返回浏览器窗口自身得大小。innerWidth和innerHeight返回里浏览器窗口中页面视口得大小。可以使用resizeTo()和resizeBy()方法调整窗口大小。
视口位置:
浏览器窗口尺寸通常无法满足完整显示整个页面,为此用户可以通过滚动在有限得视口中查看文档,度量文档相对于视口滚动距离得属性有两对,返回相等得值:window.pageXoffset/window.scrollX和window.pageYoffset/window.scrollY。可以使用scroll()、scrollTo()和scrollBy()方法滚动页面。这三个方法都接受表示相对视口距离得x和y坐标。这两个参数在前两个方法中表示要滚动到得坐标,在最后一个方法中表示滚动得距离。
导航与打开新窗口:
window.open()方法可以用于导航到指定URL,也可以用于打开新浏览器窗口。这个方法接收四个参数:url,目标窗口,特性字符串和表示新窗口在浏览器历史记录中是否替代当前加载页面的布尔值。通常调用这个方法时只传前三个参数,最后一个参数只有在不打开新窗口时才会适用。
定时器:
js在浏览器中时单线程执行的,但允许适用定时器指定在某个时间之后或每隔一段时间就执行相应的代码。setTimeout()用于指定在一定事件后执行某段代码,setInterval()指定每隔一段时间执行某些代码。clearTimeout()用来取消超时任务。clearInterval()并传入定时id取消超时任务。
系统对话框:
alert(),confirm():带确认,取消选项,prompt():提示用户输入消息。
location对象:
location对象提供了当前窗口中加载文档得信息,以及通常的导航功能。他既是window的属性,也是document的属性。也就是说window.location和document.location指向同一个对象。location对象不仅保存这当前加载文档的信息,也保存着把URL解析成离散片段后能够通过属性访问的信息。解析后的属性在下表中有详细说名(location前缀是必须的)。
属性 | 值 | 说名 |
---|---|---|
location.hash | "#contents" | URL散列值(#号后跟零或多个字符),如果没有则为空字符串。 |
location.host | "www.wrox.com:80" | 服务器名及端口号 |
location.hostname | "www.wrox.com" | 服务器名 |
location.pathname | "/wileyCDA/" | URL中的路径或(和)文件名。 |
location.port | "80" | 请求的端口,如果URL中没有端口,则返回空字符串 |
location.href | "http://www.wrox.com:80/WileyCDA/?q=javascript#contents" | 当前加载页面得完整URL。location得toString()方法返回这个值 |
location.protocol(协议) | "heep:" | 页面使用的协议,通常是"http:"或"https:" |
location.search | "?q=javascript" | URL中得查询字符串,这个字符串以问号开头。 |
location.username | "foouser" | 域名前指定得用户名 |
location.password | "barpassword" | 域名前指定得密码 |
location.origin | "http://www.wrox.com" | URL得源地址 |
查询字符串:
let getQueryStringArgs=function(){ let qs = (location.search.length>0?location.search.substring(1):""), args={}; for(let item of qs.split("&").map(kv=>kv.split("="))){ let name = decodeURIComponent(item[0]),value=decodeURIComponent(item[1]); if(name.length){ args[name]=value; } } return args; }
操作地址:
可以通过location对象修改浏览器的地址。首先,最常用的是使用assign()方法并传入一个URL,如下所示:(location.assign("http://www.baidu.com");,第二:location.href或window.location设置url也可以。第三:使用location.reload()方法,
navigator对象:
提供关于浏览器得信息
属性/方法 | 说明 |
---|---|
activeVrDisplays | 返回数组,包含ispresenting |
appcodeName | 即使在Mozilla浏览器中也会返回“Mozilla” |
appName | 浏览器全名 |
appVersion | 浏览器版本,通常与实际得浏览器版本不一致 |
bettery | 返回暴露battery status api 得batteryManger对象 |
buildId | 浏览器得构建编号 |
connection | 返回暴露Network Information API得networkInformation对象 |
cookieEnabled | 返回布尔值,表示是否启用了cookie |
credentials | 返回暴露gredentials Management API得credentials ialsContainer对象 |
deviceMemory | 返回单位为GB得设备内存容量 |
doNotTrack | 返回用户得“不跟踪”设置 |
geolocation | 返回暴露GeolocationAPI得geolocation对象 |
getVRDisplays | 返回与可用媒体设备硬件关联得流 |
getUserMedia | 返回设备得处理器核心数量 |
javaEnabled | 返回布尔值,表示浏览器是否启用了 Java |
languages | 返回浏览器偏好的语言数组 |
language | 返回浏览器的主语言 |
screen对象
客户端显示器信息。
素高度。每个浏览器都会在 screen 对象上暴露不同的属性。下表总结了这些属性。 属 性 说 明 availHeight 屏幕像素高度减去系统组件高度(只读) availLeft 没有被系统组件占用的屏幕的最左侧像素(只读) availTop 没有被系统组件占用的屏幕的最顶端像素(只读) availWidth 屏幕像素宽度减去系统组件宽度(只读) colorDepth 表示屏幕颜色的位数;多数系统是 32(只读) height 屏幕像素高度 left 当前屏幕左边的像素距离 pixelDepth 屏幕的位深(只读) top 当前屏幕顶端的像素距离 width 屏幕像素宽度 orientation 返回 Screen Orientation API 中屏幕的朝向
heistory对象
操纵浏览器历史记录得能力
history 对象表示当前窗口首次使用以来用户的导航历史记录。因为 history 是 window 的属性, 所以每个 window 都有自己的 history 对象。出于安全考虑,这个对象不会暴露用户访问过的 URL, 但可以通过它在不知道实际 URL 的情况下前进和后退。
导航:
go()方法可以在用户历史记录中延任何方向导航,可以前进也可以后退。此方法只接受一个参数,这个参数可以是一个证书,正值代表前进,负值代表后退。 go方法有两个简写方法:back(返回)和forward(前进)
第十四章:DOM
节点层级:
元素节点表示HTML元素,属性节点表示属性,文档类型节点表示文档类型,注释节点表示注释,
node类型:
在js中所有节点类型都继承node类型,因此所有类型都共享相同得基本属性和方法。每个节点都有nodeType属性表示该节点得类型,节点类型由定义在node类型上得12个数值常量表示:
常量 | 描述 | 小写 |
---|---|---|
Node.ELEMENT_NODE | 元素节点 | Node.element_node |
node.ATTRIBUTE_NODE | 属性节点 | node.attRibute_node |
node.TEXT_NODE | 文本节点 | node.text_node |
node.CDATA_SECTION_NODE | 区域节点 | node.cData_section_node |
node.ENTITY_REFERENCE_NODE | 实体引用节点 | node.entity_reference_node |
node.ENTITY_NODE | 实体节点 | node.entity_node |
node.PROCESSING_INSTRUCTION_NODE | 运算指令节点 | node.processing_instruction_node |
node.COMMENT_NODE | 注释节点 | node.comment_node |
node.DOCUMENT_NODE | 文档节点 | node.document_node |
node.DOCUMENT_TYPE_NODE | 文档类型节点 | node.document_type_node |
node.DOCUMENT_FRAGMENT_NODE | 文档片段节点 | node.document_fragment_node |
node.NOTATION_NODE | 记号节点 | node.notation_node |
节点关系:
nodeName与nodeValue保存着有关节点得信息。每个节点都有childNodes属性,其中包含一个NodeList得实例。NodeList是一个类数组对象。用于存储可以按位置存取得有序节点。注意nodelist不是array得实例,但可以使用中括号访问他得值,而且他也有length属性。nodelist对象独特得地方在于,他其实是一个对dom结构得查询。 使用array.prototype.slice()或es6得array.from()fang方法可以把nodelist转换成数组。 每个节点都有一个parentNode属性,指向其DOM树中得父元素。childNodes列表中得每个节点都是同一列表中其他节点得同胞节点。而使用previousSibling和nextSibling可以在这个列表得节点间导航。如果childNodes中只有一个节点,则他得previousSibling和nextSibling属性都是null。 firstChild和lastChild分别指向childNodes中得第一个和最后一个节点。
操纵节点:
方法名 | 描述 |
---|---|
appendChild() | 用于在childNodes列表末尾添加节点。这个方法返回新添加得节点。 |
insertBefore() | 把节点放到childNode中特定得位置,此方法接受两个参数:要插入得节点和参照节点。效果和childNodes方法相同。 |
replaceChild() | 此方法用来替换节点,接受两个参数要插入得节点和要替换得节点。要替换得节点会被返回,并从文档树中删除。 |
removeChild() | 此方法接收一个参数,即要移除得节点。被移除得节点被返回。 |
cloneNode() | 返回与调用他得节点一摸一样得节点。接收一个布尔值参数,表示是否深复制。传入true会进行深复制。即复制节点及其整个子DOM树。如果传入false,则只会复制调用该方法得节点。但是返回得节点属于文档所有,尚未指定父节点。所以称为孤儿节点,可以通过appendChild()、insertBefore()或replaceChild()方法把他添加到文档中。此方法只复制HTML属性以及可选得复制子节点。 |
normalize() | 处理文档子树中得文本节点,由于解析器实现得差异或DOM操作等原因,可能会出现并不包含文本得文本节点,或者文本节点之间护卫同胞关系。在节点上调用normalize()会检测这个节点得所有后代。从中搜索上述两种情形,如果发现空文本节点,则将其删除。如果两个同胞节点是相邻得,则将其合并成一个该文本节点。 |
document类型:
Document类型是javascript中表示文档节点得类型。在浏览器中,文档对象document是HTMLDocument得实例(HTMLDocument继承Document),表示整个HTML页面。document是window对象得属性,因此是一个全局对象。document类型得节点有以下特征:1.nodeType等于9。2,nodeName得值为“#document”。3,nodeValue得值为null。4,parentNode得值为null。5,ownerDocument值为null。6,子节点可以是documentType(最多一个),element(最多一个),processingInstruction或Comment类型。
文档信息:
document
属性 | 描述 |
---|---|
title | 标题 |
URL | 当前页面得完整URL(地址栏中得url) |
domain | 包含页面得域名 |
referrer | 包含链接到当前页面得那个页面得URL。如果当前页面没有来源,则包含一个空字符串。 |
查找元素:
方法 | 描述 |
---|---|
document.getElementById() | 根据ID进行查找,返回一个 |
document.getElementsByTagName() | 根据标签名查找,返回多个 |
namedItem() | 可通过标签得name属性取得某一项得引用,需要配合getElementsByTagName使用。 |
document.getElementsByName | 根据name属性查找。常用于单选按钮。 |
特殊集合:
HTMLCollection:是一个接口,表示html得集合,提供了可以遍历列表得方法和属性 document对象上还暴露了几个特殊集合。这些集合也是HTMLCollection得实例:这些集合是访问文档中公共部分得快捷方式。如下 :
名称 | 描述 |
---|---|
document.anchors | 包含文档中所有待name属性得a元素 |
document.forms | 包含文档中所有form元素 |
document.images | 包含文档中所有得img元素 |
document.links | 包含文档中所有待href |
element类型:
element类型得节点具有以下特征:1,nodeType等于1。2,nodeName值为元素得标签名。3,nodeValue值为null。4,parentNode值为document或element对象。
HTML元素:
所有html元素都通过HTMLElement类型表示,包括其直接实例和间接实例。另外HTMLElement直接继承Element并增加了一些属性。每个属性都对应下列属性之一,他们是所有HTML元素上都有得标准属性:id、title、lang、dir、className、
取得属性:
每个元素都有零或多个属性,通常用于为元素或其内容附加更多信息。与属性相关得DOM方法主要有三个:1,getAttribute():获得指定属性,2,setAttribute(“要设置得属性名,属性得值”):设置属性 此方法接收两个参数。3,removeAttribute():移除属性
attributes
element类型是唯一使用attributes属性得DOM节点类型。attributes属性包含一个NameNodeMap实例,是一个类似NodeList得“实时”集合。元素得每个属性都表示为一个Attr节点。并保存在这个NameNodeMap对象中,此对象包含以下方法:
方法 | 描述 |
---|---|
getNamedItem(name) | 返回nodeName属性等于name得节点 |
removeNamedItem(name) | 删除nodeName属性等于name得节点 |
setNamedItem(node) | 向列表中添加node节点,以其nodeName为索引。 |
item(pos) | 返回索引位置pos处得节点。 |
创建元素:
使用document.createElement(),此方法接收一个参数,即要创建元素得标签名
text类型:
特性:nodeType等于3,nodeName值为#text,nodeValue值为节点中包含得文本。,parentNode值为element对象。不支持子节点 方法:
方法名 | 描述 |
---|---|
appendData(text) | 向节点末尾添加文本 |
delete DATa(offset,count) | 从位置offset开始删除count个字符 |
insert DATa(offset,text) | 从位置offset插入text |
replaceData(offset,count,text) | 用text替换从位置offset到offset+count得文本 |
splitText(offset) | 在位置offset将当前文本节点拆分成两个文本节点。 |
substringData(offset,count) | 提取从位置offset到offset+count得文本。 |
创建文本节点:
document。creatTextNode()创建新得文本节点,接收一个参数,即要插入节点得文本。
comment类型:
特征:nodeType等于8,nodeName=“#comment”,nodeValue=注释得内容,parentNode=document||element对象,不支持子节点。
MutationObserver(观察接口)接口:
在DOM被修改时异步执行回调。使用mutationObserver可以观察整个文档、DIN树得一部分、或某个元素。此外还可以观察元素属性、子节点,文本,或者前三者任意组合得变化。
基本用法:
通过调用MutationObserver构造函数并传入一个回调函数来创建:let observer=new MutationObserver(()=>console.log("DOM was mutation"));
observer():
新创建得MutationObserver实例不会关联DOM得任何部分。要把这个observer与DOM关联起来,需要使用observer()方法。此方法接收两个必须得参数:要观察其变化得DOM节点,以及一个MutationObserverInit对象。
创建一个观察者: let observer = new MUtationObserver(()=>console.log("<body> attrinbutes changed")); observer.observe(document.body,{attributes:true});
以下暂时略过,不能理解。
第十五章:DOM扩展
Selectors API:
querySelector():
此方法接收css选择符参数,返回匹配该模式得第一个后代元素,如果没有返回null
query Selector All():
接收一个css选择符参数,返回所有匹配得节点,返回一个nodeList得静态实例。注意,不是实时得,而是快照。
matches():
接收一个css选择符参数,如果元素匹配该选择符,则返回true,否则返回false。
元素遍历:
element TraverslaAPI为DOM元素添加了五个属性:
属性 | 描述 |
---|---|
childElementCount | 返回子元素得数量(不包含文本节点和注释) |
firstElementChild | 指向第一个element类型得子元素 |
lastElementchild | 指向最后一个element类型得子元素。 |
previousElementSibling | 指向前一个element类型得同胞元素 |
nextElementSibiling | 指向后一个element类型得同胞元素。 |
HTML5:
CSS类扩展:
getElementsByClassName()
此方法接收一个参数,即包含一个或多个类名得字符串,返回雷鸣钟包含相应类得元素得nodelist
HTMLDocument扩展
readState:
有两个属性:loading:正在加载,complete:加载完成。
compatMode
判断浏览器当前处于什么渲染模式。
head
指向文档的head元素。let head = document.head;
字符集属性:
console.log(document.characterSet);document.characterSet = "UTF-8"; 改变字符集。
自定义数据属性:
使用data-作为前缀,可以给元素指定非标准的属性。定义了自定义数据属性后,可以通过元素的 dataset 属性来访问。dataset 属性是一个 DOMStringMap 的实例,包含一组键/值对映射。元素的每个 data-name 属性在 dataset 中都可以通 过 data-后面的字符串作为键来访问(例如,属性 data-myname、data-myName 可以通过 myname 访 问,但要注意 data-my-name、data-My-Name 要通过 myName 来访问)。
插入标记:
innerHTML:
在读取inner HTML属性时,会返回元素所有后代的HTML字符串,包括元素,注释和文本节点。而在写入innerHTML时,则回根据提供的字符串值以新的DOM子树替代元素中原来包含的所有节点。
outerHTML:
读取 outerHTML 属性时,会返回调用它的元素(及所有后代元素)的 HTML 字符串。在写入 outerHTML 属性时,调用它的元素会被传入的 HTML 字符串经解释之后生成的 DOM 子树取代。
第十六章:DOM2和DOM3
样式:
任何支持style属性得HTML元素在js中都有一个对应得style属性。如:document.getElementById().style.backgroundColor="###"
以下先略过
第十七章:事件
事件冒泡
IE事件流被称为事件冒泡》所谓事件冒泡就是从最具体得元素(文档树中最深得节点)开始触发,然后向上传播至没有那么具体得元素(文档)
事件捕获
netscape communicator团队提出事件捕获得事件流。即最不具体得节点应该最先收到事件,而最具体得节点应该最后收到事件。事件捕获实际上是为了在事件到达最终目标前拦截事件。
DOM事件流
DOM2Events规规定事件流分为3个阶段:事件捕获、到达目标和事件冒泡。事件捕获最先发生,为提前拦截事件提供了可能。然后实际得目标元素接收到事件。最后一个阶段是冒泡,最迟要在这个阶段响应事件。
事件处理程序
事件意味着用户或浏览器执行得某种动作。比如click,load(加载),鼠标悬停(mouseover)。为相应事件而调用得函数被称为事件处理程序(或事件监听器)。事件处理程序得名字以"on"开头。
DOM0事件处理程序:
在js中指定事件处理程序得传统方式是把一个函数赋值给(dom元素得)一个事件处理程序属性。要使用js指定事件处理程序,必须先取得要操作对象得引用。使用这种方法为事件处理程序赋值时,所赋函数被视为元素得方法。所以,里面得this等于元素。
let btn = document.getElementById("id"); ben.οnclick=function(){ console.log(this.id); }
DOM2事件处理程序
DOM2Event为时间处理程序的赋值和移除定义了两个方法:addEventListener()和removeEventListener()。他们接受三个参数:事件名,事件处理函数,和一个布尔值。true表示在捕获阶段调用事件处理程序,false(默认值)表示在冒泡阶段调用事件处理程序。
事件对象:
在DOM中发生事件时,所有相关信息都会被收集并存储在一个名为event的对象中,
DOM事件对象
在DOM合规得浏览器中,event对象是传给事件处理程序得唯一参数。不管以哪种方式指定事件处理程序,都会传入event对象。所有事件对象都会包含下表列出得这些公共属性和方法:
属性/方法 | 类型 | 读/写 | 描述 |
---|---|---|---|
bubbles | 布尔值 | 只读 | 表示事件是否冒泡 |
cancelable | 布尔值 | 只读 | 表示是否可以取消事件得默认行为 |
currentTarget | 元素 | 只读 | 当前事件处理程序所在得元素 |
defaultPrevented | 布尔值 | 只读 | true表示已经调用preventDefault()方法(dom3新增) |
detail | 整数 | 只读 | 事件相关得其他信息 |
eventPhase | 整数 | 只读 | 表示调用事件处理程序得阶段:1表示捕获阶段,2表示到达目标,3表示冒泡阶段 |
preventDefault() | 整数 | 只读 | 用于取消事件得默认行为。只有cancelable为ture才可以调用这个方法 |
stopImmediatePropagation() | 函数 | 只读 | 用于取消所有后续事件捕获或事件冒泡。只有bubbles为true才可以调用这个方法 |
target | 元素 | 只读 | 事件目标 |
type | 字符串 | 只读 | 被触发得事件类型 |
isTrusted | 布尔值 | 只读 | true表示事件是由浏览器生成得,false表示事件是开发者通过js创建的(dom3新增) |
View | AbstractView | 只读 | 与事件相关得抽象视图。等于事件所发生得window对象 |
事件类型:
用户界面事件:
涉及与BOM交互得通用浏览器事件
用户界面事件或UI事件不一定跟用户操作有关。这类事件在DOM规范出现之前就已经以某种形式存在了
事件 | 描述 |
---|---|
load | 在window上当页面加载完成后触发,在img元素上当图片加载完成后触发,在object元素上当相应对象加载完成后触发 |
unload | 与上面事件相反 |
abort | 在object元素上当相应对象加载完成前被用户提前终止下载时触发 |
error | 在window上当js报错时触发,在img元素上当无法加载指定图片时触发,在object元素上无法加载相应对象时触发。 |
select | 在文本框(input或textarea)上当用户选择了一个或多个字符时触发 |
resize | 在window或窗口缩放时触发 |
scroll | 当用户滚动包含滚动条得元素时在元素上触发。body元素包含已加载页面得滚动条。 |
焦点事件:
焦点事件在页面元素获得或失去焦点时触发。这些事件可以与document.hasFocus()和document.activeElement一起为开发者提供用户在页面中导航得信息。焦点事件有6种:
事件 | 描述 |
---|---|
blur | 失去焦点时触发,此事件不冒泡 |
focusIn | 获得焦点时触发。往上冒泡 |
focus | 获得焦点时触发,不冒泡 |
focusout | 失去焦点时触发,这个事件时blur得通用版。 |
鼠标和滚轮事件
事件 | 描述 |
---|---|
click | 单击事件 |
dblclick | 双击事件 |
mousedown | 在用户按下任意鼠标键时触发 |
mouseenter | 光标移入时触发,不冒泡。dom3新增 |
mouseleave | 光标移出时触发,不冒泡。dom3新增 |
mousemove | 鼠标移动时触发,在鼠标光标在元素上移动时反复触发。 |
mouseout | 把光标从元素外部移到元素内部时触发 |
mouseup | 释放鼠标键时触发 |
键盘事件:
略过
内存与性能:
在js中,页面中事件处理程序得数量与页面整体性能直接相关。原因有很多,首先每个函数都是对选购,都占用内存空间,对象越多,性能越差。其次,为指定事件处理程序所需访问DOM得次数会先期造成整个页面交互得延迟。
事件与委托:
利用事件冒泡,可以只是用一个事件处理程序来管理一种类型得事件。解除事件委托可以删除元素得事件绑定,然后再删除元素。
第十八章:动画与Canvas图形
canvas会占据一块页面区域,让js可以动态在上面绘制图片
使用requestAnimationFrame:
此方法会告诉浏览器要执行动画,可以通过最优方式确定重绘得时序。此方法接收一个参数,此参数是一个要在重绘屏幕前调用得函数。这个函数就是修改DOM样式以反映下一次重绘有什么变化得地方。为了实现动画循环,可以把多个requestAnimationFrame()调用串联起来。
基本得画布功能:
创建canvas元素时至少要设置其width和height属性。这样才能告诉浏览器在多大面积上绘图。要在画布上绘制图形,首先要取得绘图上下文,使用getContext()方法可以获取对绘图上下文得引用,对于平面图形,需要给这个方法传入“2d“,表示要获取2D上下文对象。 可以使用toDataURL()方法到处canvas元素上得图像。此方法接收一个参数:要生成图像得MIME类型(与用来创建图形得上下文无关)。
2D绘图上下文:
2d绘图上下文提供了绘制2d图像得方法,包括矩形,弧形和路径。其坐标原点(0,0)在canvas元素得左上角,所有坐标值都相对于该点己算。因此X向右增长,y向下增长,默认情况下,width和height是表示两个方向上像素得最大值。
填充和描边:
填充:以指定样式(颜色、渐变或图像)自动填充形状,而描边只为图形边界着色。大多数2d上下问操作有填充和 描边得变体,显示效果取决于两个属性:fillStyle和strokeStyle。这两个属性都可以是字符串、渐变对象或图案对象,默认值都是#000000.
绘制矩形:
矩形是唯一一个可以直接在2D绘图上下文中绘制得形状。相关方法有三个:fillRect(绘制填充矩形)、strokeRect(绘制描边矩形)和clearRect(清楚矩形)。此方法都接收4个参数:矩形x坐标,矩形y坐标,矩形宽度和矩形高度。描边宽度由lineWidth属性控制,lineCap属性控制线条端点得形状["butt":平头,"round":"出圆头",“square”:出方头],lineJoin属性控制线条交叉点得形状[“round”:圆转,“bevel”:取平,“miter”:出尖]。使用clearRect()方法可以擦除画布中某个区域。该方法用于把绘图上下文中得某个区域变透明。通过先绘制形状在擦除指定区域,可以创建出有趣得效果。
绘制路径:
2d绘图上下文支持很多在画布上绘制路径得方法。通过路径可以创建复杂得形状和线条。要绘制路径,必须先调用beginPath()方法以表示要开始绘制新路径。然后再调用下列方法来绘制路径。
方法 | 描述 |
---|---|
arc(x,y,radius,startAngle,endAngle,counterclockwise) | 以坐标(x,y)为圆心,以radius为半径绘制一条弧线,起始角度为startAngle,结束角度为endAngle(都是弧度),最后一个参数counterclockwise表示是否逆时针己算起始角度和结束角度(默认为顺时针)。 |
arcTo(x1,y1,x2,y2,radius) | 以给定半径radius,经由(x1,y1)绘制一条从上一点到(x2,y2)得弧线。 |
bezierCurveTo(c1x,c1y,c2x,c2y,x,y) | 以(c1x, c1y)和(c2x, c2y)为控制点, 绘制一条从上一点到(x, y)的弧线(三次贝塞尔曲线)。 |
lineTo(x,y) | 绘制一条从上一点到(x,y)得直线。 |
moveTo(x,y) | 不绘制线条,只把绘制光标移动到(x,y) |
quadraticCurveTo(cx,cy,x,y) | 以(cx, cy)为控制点,绘制一条从上一点到(x, y) 的弧线(二次贝塞尔曲线)。 |
rect(x, y, width, height) | 以给定宽度和高度在坐标点(x, y)绘制一个矩形。这个方法 与 strokeRect()和 fillRect()的区别在于,它创建的是一条路径,而不是独立的图形 |
创建路径之后,可以使用 closePath()方法绘制一条返回起点的线。如果路径已经完成,则既可 以指定 fillStyle 属性并调用 fill()方法来填充路径,也可以指定 strokeStyle 属性并调用 stroke()方法来描画路径,还可以调用 clip()方法基于已有路径创建一个新剪切区域。 路径是2D上下文得主要绘制机制,为绘制结构提供了很多控制。因为路径经常被使用,所以也有一个isPointInpath()方法,接收x轴和y轴作为参数。这个方法用于确定指定得点是否再路径上,可以再关闭路径前随时调用。
绘制文本:
2d绘图还提供了绘制文本得方法:即fillText()和StrokeText()。这两个方法都接收4个参数:要绘制得字符串,x坐标,y坐标和可选得最大像素宽度。而且,这两个方法最终绘制得结果都取决于以下3个属性:1,font:以css语法指定得字体样式,大小,字体族等比如“10px Arial”。2,textAlign:指定文本得对其方式,值有:start,end,left,right和center。推荐使用start,end。3,textBaseLine:指定文本得基线,可能得值包括”top“,”hanging“,”middle“,”alphabetic","ide发ographic"和"bottom"。
变换:
略过
绘制图像:
略过
阴影:
略过
渐变:
略过
图案:
略过
第十九章:表单脚本
表单基础:
web表单再HTML中以form元素表示,在js中则以HTMLFormElement类型表示。他继承自HTMLElement类型,因此拥有与其他HTML元素得默认属性。不过他也有自己得属性和方法:
属性/方法 | 描述 |
---|---|
acceptCharset | 服务器可以接收得字符集,等价于HTML得accept-charset属性 |
action | 请求得URL,等价于HTML得action属性 |
elements | 表单中所有控件得HTMLCollection |
enctype | 请求得编码类型,等价于HTML得enctype属性。 |
length | 表单中空间得数量 |
method | HTTP请求得方法类型,通常是“get”或“post”,等价于html上得method属性 |
name | 表单得名字,等价于HTML得name属性 |
reset() | 把表单字段重置为各自得默认值。 |
submit() | 提交表单 |
target | 用于发送请求和接收响应得窗口得名字。等价于HTML得target属性。 |
提交表单:
表单时通过用户点击提交按钮或图片按钮得方式提交得。提交按钮可以使用type属性为“submit”得input或button元素来定义。
重置表单:
用户点击type属性为reset得input或button。
第二十章jsAPi:
略过
第二十一章:错误处理与调试
try/catch语句:
基本语法:
try{ //可能出错得代码 }catch(error){ //出错时要做什么 }
finally子句:
try/catch 语句中可选的 finally 子句始终运行。如果 try 块中的代码运行完,则接着执行 finally 块中的代码。如果出错并执行 catch 块中的代码,则 finally 块中的代码仍执行。try 或 catch 块无法阻止 finally 块执行,包括 return 语句。
错误类型:
错误类型 | 描述 |
---|---|
Error | 是基类型,其他错误类型继承该类型。所有错误类型都共享共同得属性(所有错误对象上得方法都是这个默认类型定义得方法)。浏览器很少会抛出Error类型得错误,该类型主要用于开发者抛出自定义错误。 |
InternalError | 在底层js引擎抛出异常时由浏览器抛出。例如递归过多导致了栈溢出。这个类型并不是代码中通常要处理得错误,如果真发生了这种错误,很可能代码那里弄错了或者有危险了。 |
EvalError | 调用eval()函数发生异常时抛出。基本上只要不把eval()当成函数调用就会报告该错误。 |
RangeError | 在数值越界时抛出。 |
ReferenceError | 在找不到对象时发生。这种错误经常时由访问不存在得变量而导致得。 |
SyntaxError | 经常在给eval()传入得字符串包含js语法错误时发生。 |
TypeError | 主要发生在变量不是预期类型,或者访问不存在得方法时。很多原因可能导致这种错误,尤其是在使用类型特定得操作而变量类型不对时。在给函数传参数之前,没有验证其类型得情况下,类型错误频繁发生。 |
URIError | 只会在使用encodeURI()或decodeURI()但传入了格式错误得URI时发生 |
抛出错误:
与try/catch语句对应得一个机制是throw操作符,用于在任何时候抛出自定义错误。throw操作符必须有一个值,但值得类型不限。使用throw操作符时,代码立即停止。除非try/catch语句捕获了抛出得值。
error事件:
任何没有被try/catch语句处理得错误都会在window对象上触发error事件。在onerror事件处理程序中,任何浏览器都不会传入event对象。相反会传入三个参数:错误消息,发生错误得URI和行号。
识别错误:
类型转换错误:
主要原因是使用了会自动改变某个值得数据类型得操作符或语言构造。所以最好在使用变量之前检测以下数据类型。
数据类型错误:
因为js是松散类型得,所以变量和函数参数都不能保证会使用正确得数据类型。
通信错误:
web应用程序在运行期间动态加载数据和功能成为常见得类型,js和服务器之间得通信也会出现这种错误,第一种错误是URL格式或发送数据得格式不正确。通常,在把数据发送到服务器之前没有用encodeURIComponent()编码会导致错误。
错误调试:
debugger:
在代码运行时碰到这个关键字时,所有主流浏览器都会打开开发者工具面板,并在知识位置显示断电。
在页面打印消息
把错误消息写道页面中指定得区域。
第二十二章:处理XML
略过,不重要,后期在学。
第二十三章:JSON
JSON是JavaScript得严格子集,利用js中得几种模式来表示结构化数据。JSON可以直接传给eval()而不需要创建DOM。他只是一种通用数据格式。而不是编程语言。
语法:
JSON语法支持表示3种类型得值: 简单值:js中得基本类型,但不包括undefined、 对象:注意要把属性名用双引号包裹起来。不需要变量声明(json中没有变量)其次,没有分号。
{ "name": "Nicholas", "age": 29 }
数组:
[{1,2,3,4}]
JSON对象:
es5新增了json对象,他有两个方法:
方法名 | 描述 |
---|---|
JSON.stringify() | js对象序列化为json字符串,默认情况下JSON.stringify()会输出不包含空格或缩进得JSON字符串,此方法接收3个参数,1,要转换得目标,通常为对象或数组;第二个参数是用于转换结果得函数或数组。如果是函数,则调用这个函数,如果是数组,则仅转换该数组中具有键值得得成员。成员得转换顺序与键在数组中得顺序一样。第三个三处,文本添加缩进、空格和换行符。如果是一个数字,则返回值文本在每个级别缩进指定数目得空格。如果大于10,那么文本缩进10个空格。 |
JSON.parse() | 将json字符串序列化成js对象,如果给他传入得JSON字符串无效,则会导致抛出错误。接收两个参数,1,text,一个有效得json字符串,第二个,一个转换结果得函数,将为对象得每个成员调用此函数。 |
第二十四章:网络请求与远程资源
XMLHttpRequest对象
这种方式实际上是过时Web规范得产物,应该只在旧版本浏览器中使用。实际开发中,应尽可能使用fetch()。
使用xhr:
使用xhr对象首先要调用open()方法,此方法接收三个参数:请求类型(post,get等),请求url,以及表示请求是否异步得布尔值。注意,此方法只能访问同源url,也就是域名相同、协议相同、端口相同。如果请求得url与发送请求得页面在任何方面有所不同,则会抛出安全错误。 要发送定义好得请求,必须调用send()方法。他收到相应后,xhr对象得以下属性会被填充上数据。
返回得属性 | 描述 |
---|---|
responseText | 作为响应体返回得文本。 |
responseXML | 如果响应得内容类型是“text/xml”或“application/xml",那就是包含响应数据得XML DOM文档。 |
status | 响应得http状态 |
statusText | 响应得http状态描述 |
方法名 | 描述 |
---|---|
open(method,url,async) | 此方法接收三个参数:请求类型(post,get等),请求url,以及表示请求是否异步得布尔值。 |
send() | 接收一个参数,是作为请求体发送得数据。如果不需要发送请求体,则必须传null。因为这个参数在某些浏览器中是必须得。调用send()之后,请求就会发送到服务器。 |
收到响应后,第一步要检查status属性以确保响应成功返回。
阶段 | 描述 |
---|---|
0 | (Uninitialized) 未初始化,尚未调用open()方法 |
1 | (Open)已调用open()方法,尚未调用send()方法 |
2 | (Sent)已调用send()方法,尚未收到响应 |
3 | (Receiving)已经收到部分响应 |
4 | (Complete)已经收到全部响应。 |
每次 readyState 从一个值变成另一个值,都会触发 readystatechange 事件。可以借此机会检 查 readyState 的值。一般来说,我们唯一关心的 readyState 值是 4,表示数据已就绪。为保证跨浏 览器兼容,onreadystatechange 事件处理程序应该在调用 open()之前赋值。
let xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if (xhr.readyState == 4) { if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) { alert(xhr.responseText); } else { alert("Request was unsuccessful: " + xhr.status); } } }; xhr.open("get", "example.txt", true); xhr.send(null);
http头部:
每个http请求和响应都会携带一些头部字段。xhr对象会通过一些方法暴漏与请求和响应相关得头部字段。默认情况下xhr请求会发送以下头部字段
字段 | 描述 |
---|---|
Accept | 浏览器可以处理得内容类型 |
Accept-Charset | 浏览器可以显示得字符集 |
Accept-Encoding | 浏览器可以处理得压缩编码类型 |
Accept-Language | 浏览器使用得语言 |
Conection | 浏览器与服务器得连续类型 |
Cookie | 页面中设置得Cookie |
Host | 发送请求得页面所在得域 |
Referer | 发送请求得页面得URI |
User-Agent | 浏览器得用户代理字符串 |
虽然不同浏览器发送得确切头部字段可能各不相同,但这些通常都是会发送得。如果需要发送额外得请求头部,可以使用setRequestHeader()方法。此方法接收两个参数:头部字段得名称和值。
get请求:
get请求用于向服务器查询某些信息。必要时,需要在get请求得url后面添加查询字符串参数。查询字符串中得每个名和值都必须使用encodeURIComponent()编码。所有名/值对必须以(&)分隔。
post请求:
post请求用于向服务器发送应该保存得数据。每个post请求体中携带提交得数据。
JSONP:
是在Web服务上流行得一种JSON变体。JSONP看起来和JSON一样,只是会被包在一个函数调用里,比如
callback({"name":"Nicholas"});
jsonp格式包含两个部分:回调和数据。回调是在页面接收到响应之后应该调用得函数,通常回调函数得名称是通过请求来动态指定得。而数据就是作为参数传给回调函数得JSON数据。下面是一个典型得jsonp请求
http://freegeoip.net/json/?callback=handleResponse
这个jsonp请求得url是一个地理位置服务,jsonp服务通常支持以查询字符串形式指定回调函数得名称。jsonp调用是通过动态创建script元素并为src属性指定跨域url实现得。此时得script与img元素类似,能够不受限制得从其他域加载资源。因为jsonp是有效得JavaScript,所以jsonp应在被接在完成之后会立即执行。比如下面这个例子:
function handleResponse(response) { console.log(` You're at IP address ${response.ip}, which is in ${response.city}, ${response.region_name}`); } let script = document.createElement("script"); script.src = "http://freegeoip.net/json/?callback=handleResponse"; document.body.insertBefore(script, document.body.firstChild);
jsonp由于简单易用,在开发者中非常流行,相比于图片探测,使用jsonp可以直接访问响应,实现浏览器与服务器得双向通信。不过jsonp也有缺点:第一,jsonp是从不同得域拉取可执行代码,如果这个域不可信,则可能在响应中家入恶意内容,此时除了完全删除jsonp没有其他方法。在使用不受控得web服务时,一定要保证是可以信任得。第二,不好确定jsonp请求是否失败,虽然HTML5规定了script元素得onerror事件处理程序,但还没有被任何浏览器实现,为此,开发者经常使用计时器来决定是否放弃等待响应。这种方式并不准确,毕竟不同用户得网络连接速度和贷款是不一样得。
Fetch API:
fetchapi能够执行XMLHttpRequest对象得所有任务,但更容易使用,接口也更现代化,能够在web工作线程等现代web工具中使用。XMLHttpRequest可以选择异步,而Fetch API则必须是异步。FetchAPI是WHATWG得一个“活标准”,用规范原文说,就是“fetch标准定义请求,响应,以及绑定二者得流程:获取(fetch)”。FetchAPI本身是使用js请求资源得优秀工具,同时这个API也能够应用在服务线程(service worker)中,提供拦截、重定向和修改fetch()生成得请求接口。
基本用法:
fetch()方法是暴露在全局作用域中得,包括主页面执行线程、模块和工作线程。调用这个方法,浏览器就会向给定URL发送请求;
1,分派请求:
fetch()只有一个必需得参数input。多数情况下,这个参数是要获取资源得URL,这个方法返回一个期约:
let r = fetch(url); console.log(r);//Promise <pending>
URL得格式(相对路径、绝对路径等)得解释与XHR对象一样。 请求完成、资源可用时,期约会解决为一个Response对象。这个对象是API得封装,可以通过他取得响应资源。获取资源要使用这个对象得属性和方法,掌握响应得情况并将负载转换为有用得形式,如下所示:
fetch('bar.txt') .then((response)=>{ console.log(response); }); //Response{type:'basic',url:....}
2,读取响应:
读取响应内容得最简单得方式是取得纯文本格式得内容,这要用到text()方法。这个方法返回一个期约,会解决为取得资源得完整内容:
fetch('bar.txt') .then((response)=>{ response.text().then((data)=>{ console.log(data); }) }) //bar.txt得内容
内容得结构通常是打平得:
fetch('bar.txt') .then((response) => response.text()) .then((data) => console.log(data)); // bar.txt 的内容
3,处理状态码和请求失败:
Fetch API支持通过Response得status(状态码)和statusText(状态文本)属性检查响应状态。成功获取响应得请求通常会产生值为200得状态码,如下所示:
fetch('/bar') .then((response) => { console.log(response.status); // 200 console.log(response.statusText); // OK });
请求不存在得资源通常会产生值为404得状态码:
fetch('/does-not-exist') .then((response) => { console.log(response.status); // 404 console.log(response.statusText); // Not Found });
请求得URL如果抛出服务器错误会产生值为500得状态码:
fetch('/throw-server-error') .then((response) => { console.log(response.status); // 500 console.log(response.statusText); // Internal Server Error });
在前面这几个例子中,虽然请求可能失败(如状态码为500),但都只执行了期约得解决处理函数。事实上,只要服务器返回了响应,fetch()期约都会解决。这个行为是合理得:系统及网络协议已经成功完成消息得一次往返传输。至于真正得“成功”请求,则需要在处理响应时再定义。通常状态码为 200 时就会被认为成功了,其他情况可以被认为未成功。为区分这两种情况,可以在 状态码非 200~299 时检查 Response 对象的 ok 属性
fetch('/bar') .then((response) => { console.log(response.status); // 200 console.log(response.ok); // true }); fetch('/does-not-exist') .then((response) => { console.log(response.status); // 404 console.log(response.ok); // false });
因为服务器没有响应而导致浏览器超时,这样真正得fetch()失败会导致期约被拒绝:
fetch('/hangs-forever') .then((response) => { console.log(response); }, (err) => { console.log(err); }); //(浏览器超时后) // TypeError: "NetworkError when attempting to fetch resource."
4,自定义选项:
只使用URL时,fetch()会发送GET请求,只包含最低限度得请求头。要进一步配置如何发送请求,需要传入可选得第二个参数init对象。init对象要按照下表中得键/值进行填充。
键 | 值 |
---|---|
body | 指定使用请求体时请求体得内容 必须是 Blob、BufferSource、FormData、URLSearchParams、ReadableStream 或 String 的 实例 |
cache | 用于控制浏览器与 HTTP缓存的交互。要跟踪缓存的重定向,请求的 redirect 属性值必须是"follow", 而且必须符合同源策略限制。必须是下列值之一 Default : 1, fetch()返回命中的有效缓存。不发送请求 2, 命中无效(stale)缓存会发送条件式请求。如果响应已经改变,则更新缓存的值。然后 fetch() 返回缓存的值 3, 未命中缓存会发送请求,并缓存响应。然后 fetch()返回响应 no-store: 1,浏览器不检查缓存,直接发送请求 2, 不缓存响应,直接通过 fetch()返回 reload: 1, 浏览器不检查缓存,直接发送请求 2, 缓存响应,再通过 fetch()返回 no-cache: 1, 无论命中有效缓存还是无效缓存都会发送条件式请求。如果响应已经改变,则更新缓存的值。然 后 fetch()返回缓存的值 2, 未命中缓存会发送请求,并缓存响应。然后 fetch()返回响应 force-cache: 1, 无论命中有效缓存还是无效缓存都通过 fetch()返回。不发送请求 2, 未命中缓存会发送请求,并缓存响应。然后 fetch()返回响应 only-if-cached: 1, 只在请求模式为 same-origin 时使用缓存 2, 无论命中有效缓存还是无效缓存都通过 fetch()返回。不发送请求 3, 未命中缓存返回状态码为 504(网关超时)的响应 默认为 default |
credentials | 用于指定在外发请求中如何包含 cookie。与 XMLHttpRequest 的 withCredentials 标签类似 必须是下列字符串值之一 1,omit:不发送 cookie 2,same-origin:只在请求 URL 与发送 fetch()请求的页面同源时发送 cookie 3, include:无论同源还是跨源都包含 cookie 在支持 Credential Management API 的浏览器中,也可以是一个 FederatedCredential 或 PasswordCredential 的实例 默认为 same-origin |
headers | 用于指定请求头部 必须是 Headers 对象实例或包含字符串格式键/值对的常规对象 默认值为不包含键/值对的 Headers 对象。这不意味着请求不包含任何头部,浏览器仍然会随请求 发送一些头部。虽然这些头部对 JavaScript 不可见,但浏览器的网络检查器可以观察到 |
integrity | 用于强制子资源完整性 必须是包含子资源完整性标识符的字符串 默认为空字符串 |
keepalive | 用于指示浏览器允许请求存在时间超出页面生命周期。适合报告事件或分析,比如页面在 fetch() 请求后很快卸载。设置 keepalive 标志的 fetch()请求可用于替代 Navigator.sendBeacon() 必须是布尔值 默认为 false |
method | 用于指定 HTTP 请求方法 基本上就是如下字符串值: GET 、 POST 、PUT 、 PATCH 、 DELETE 、 HEAD 、 OPTIONS 、 CONNECT 、 TARCE 默认为 GET |
mode | 用于指定请求模式。这个模式决定来自跨源请求的响应是否有效,以及客户端可以读取多少响应。 违反这里指定模式的请求会抛出错误 必须是下列字符串值之一 1, cors:允许遵守 CORS 协议的跨源请求。响应是“CORS 过滤的响应”,意思是响应中可以访问 的浏览器头部是经过浏览器强制白名单过滤的 2,no-cors:允许不需要发送预检请求的跨源请求(HEAD、GET 和只带有满足 CORS 请求头部的 POST)。响应类型是 opaque,意思是不能读取响应内容 3, same-origin:任何跨源请求都不允许发送 4, navigate:用于支持 HTML 导航,只在文档间导航时使用。基本用不到 在通过构造函数手动创建 Request 实例时,默认为 cors;否则,默认为 no-cors |
redirect | 用于指定如何处理重定向响应(状态码为 301、302、303、307 或 308) 必须是下列字符串值之一 follow:跟踪重定向请求,以最终非重定向 URL 的响应作为最终响应 error:重定向请求会抛出错误 manual:不跟踪重定向请求,而是返回 opaqueredirect 类型的响应,同时仍然暴露期望的重 定向 URL。允许以手动方式跟踪重定向 默认为 follow |
referrer | 用于指定 HTTP 的 Referer 头部的内容 必须是下列字符串值之一 no-referrer:以 no-referrer 作为值 client/about:client:以当前 URL 或 no-referrer(取决于来源策略 referrerPolicy)作 为值 :以伪造 URL 作为值。伪造 URL 的源必须与执行脚本的源匹配 默认为 client/about:client |
referrerPolicy | 用于指定 HTTP 的 Referer 头部 必须是下列字符串值之一 no-referrer 请求中不包含 Referer 头部 no-referrer-when-downgrade 对于从安全 HTTPS 上下文发送到 HTTP URL 的请求,不包含 Referer 头部 对于所有其他请求,将 Referer 设置为完整 URL origin 对于所有请求,将 Referer 设置为只包含源 same-origin 对于跨源请求,不包含 Referer 头部 对于同源请求,将 Referer 设置为完整 URLstrict-origin 对于从安全 HTTPS 上下文发送到 HTTP URL 的请求,不包含 Referer 头部 对于所有其他请求,将 Referer 设置为只包含源 origin-when-cross-origin 对于跨源请求,将 Referer 设置为只包含源 对于同源请求,将 Referer 设置为完整 URL strict-origin-when-cross-origin 对于从安全 HTTPS 上下文发送到 HTTP URL 的请求,不包含 Referer 头部 对于所有其他跨源请求,将 Referer 设置为只包含源 对于同源请求,将 Referer 设置为完整 URL unsafe-url 对于所有请求,将 Referer 设置为完整 URL 默认为 no-referrer-when-downgrade |
signal | 用于支持通过 AbortController 中断进行中的 fetch()请求 必须是 AbortSignal 的实例 默认为未关联控制器的 AbortSignal 实例 |
常见Fetch请求模式:
1,发送json数据:
let payload=JSON.stringify({foo:'bar'}); let jsonHeaders = new Headers({'Content-type':'application/json'}); fetch('/send-me-json',{ method:'POST', body:payload, headers:jsonHeaders });
2,在请求体中发送参数:
因为请求体支持任意字符串值,所以可以通过他发送请求参数:
let payload = 'foo=bar&baz=qux'; let paramHeaders = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' }); fetch('/send-me-params', { method: 'POST', // 发送请求体时必须使用一种 HTTP 方法 body: payload, headers: paramHeaders });
3,发送文件:
因为请求体支持FormData实现,所以fetch()也可以序列化并发送文件字段中得文件。
let imageFormData = new FormData(); let imageInput = document.querySelector("input[type='file']"); imageFormData.append('image', imageInput.files[0]); fetch('/img-upload', { method: 'POST', body: imageFormData });
这个fetch()实现可以支持多个文件:
let imageFormData = new FormData(); let imageInput = document.querySelector("input[type='file'][multiple]"); for (let i = 0; i < imageInput.files.length; ++i) { imageFormData.append('image', imageInput.files[i]); } fetch('/img-upload', { method: 'POST', body: imageFormData });
4,加载Blob文件:
Blob
(Binary Large Object) 对象代表了一段二进制数据,提供了一系列操作接口。其他操作二进制数据的API(比如 File
对象),都是建立在 Blob
对象基础上的,继承了它的属性和方法。 Fetch API也能提供 Blob 类型的响应,而 Blob 又可以兼容多种浏览器 API。一种常见的做法是明确将 图片文件加载到内存,然后将其添加到 HTML图片元素。为此,可以使用响应对象上暴露的 blob()方法。 这个方法返回一个期约,解决为一个 Blob 的实例。然后,可以将这个实例传给 URL.createObjectUrl() 以生成可以添加给图片元素 src 属性的值:
const imageElement = document.querySelector('img'); fetch('my-image.png').then((response) => response.blob()).then((blob) => { imageElement.src = URL.createObjectURL(blob); });
5,发送跨域请求:
从不同得源请求资源,响应要包含CORS头部才能保证浏览器收到响应。没有这些头部,跨源请求会失败并抛出错误。
6,中断请求:
Fetch API支持通过AbortController/AbortSignal对中断请求。调用AbortController.abort()会中断所有网络传输,特别适合希望停止传输大型负载得情况。中断进行中得fetch()请求会导致包含错误得拒绝。
headers对象:
Headers 对象是所有外发请求和入站响应头部的容器。每个外发的 Request 实例都包含一个空的 Headers 实例,可以通过 Request.prototype.headers 访问,每个入站 Response 实例也可以通过 Response.prototype.headers 访问包含着响应头部的 Headers 对象。这两个属性都是可修改属性。 另外,使用 new Headers()也可以创建一个新实例。
1,:headers与Map得相似之处
HTTP 头部本质上是序列化后的键/值对, 它们的 JavaScript 表示则是中间接口。Headers 与 Map 类型都有 get()、set()、has()和 delete() 等实例方法
2,headers独有得特性:
在初始化 Headers 对象时,也可以使用键/值对形式的对象, 而 Map 则不可以。
3,头部护卫:
某些情况下,并非所有 HTTP 头部都可以被客户端修改,而 Headers 对象使用护卫来防止不被允 许的修改。不同的护卫设置会改变 set()、append()和 delete()的行为。违反护卫限制会抛出 TypeError。 Headers 实例会因来源不同而展现不同的行为,它们的行为由护卫来控制。JavaScript 可以决定 Headers 实例的护卫设置。下表列出了不同的护卫设置和每种设置对应的行为。
护卫 | 使用情景 | 限制 |
---|---|---|
none | 在通过构造函数创建Headers实例时激活 | 无 |
request | 在通过构造函数初始化Request对象,且mode值为非no-cors时激活 | 不允许修改禁止修改得头部 |
request-no-cors | 在通过构造函数初始化 Request对象,且 mode 值为 no-cors 时激活 | 不允许修改非简单头部 |
response | 在通过构造函数初始化 Response 对象时激活 | 不允许修改禁止修改的响应头部 |
immutable | 在通过 error()或 redirect()静态方法初始 化 Response 对象时激活 | 不允许修改任何头部 |
Request对象:
Request 对象是获取资源请求的接口。这个接口暴露了请求的相关信息,也暴露了使 用请求体的不同方式
1,创建Request对象
可以通过构造函数初始化 Request 对象。为此需要传入一个 input 参数,一般是 URL。Request 构造函数也接收第二个参数——一个 init 对象。这个 init 对象与前面介绍的 fetch() 的 init 对象一样。没有在 init 对象中涉及的值则会使用默认值。
2,克隆Request对象:
使用 Request 构造函数和使 用 clone()方法
Response对象:
Response 对象是获取资源响应的接口。这个接口暴露了响应的相关信息,也暴露了使 用响应体的不同方式。
1,创建Response对象:
可以通过构造函数初始化 Response 对象且不需要参数。此时响应实例的属性均为默认值,因为它 并不代表实际的 HTTP 响应。Response 构造函数接收一个可选的 body 参数。这个 body 可以是 null,等同于 fetch()参数 init 中的 body。还可以接收一个可选的 init 对象,这个对象可以包含下表所列的键和值。
键 | 值 |
---|---|
headers | 必须是Headers对象实例或包含字符串键/值对得常规对象实例。 |
status | 表示HTTP响应状态码得整数。 |
statusText | 表示HTTP响应状态得字符串,默认为空字符串 |
2,读取响应状态信息:
response对象包含一组只读属性,描述了请求完成后得状态。如下表所示:
属性 | 值 |
---|---|
headers | 响应包含得headers对象 |
ok | 布尔值,表示HTTP状态码得含义。200~299得状态码返回true,其他状态码返回false |
redirected | 布尔值,表示响应是否至少经过一次重定向 |
status | 整数,表示响应得HTTP状态码 |
statusText | 字符串,包含对HTTP状态码得正式描述。这个值派生自可选得HTTPReason-Phrase字段。因此如果服务器以Reason-Phrase为由拒绝响应,这个字段可能是空字符串。 |
type | 字符串,包含响应类型,可能是下列字符串值之一:basic(表示标准得同源响应),cors(表示标准得跨源响应),error(表示响应对象是通过Response.error()创建得),opaque(表示no-cors得fetch()返回得跨源响应),opaqueredirect(表示对redirect设置为manual得请求得响应) |
url | 包含响应URL得字符串,对于重定向响应,这是最终得url,非重定向响应就是他产生得。 |
WebSocket:
他得目标是通过一个长时连接实现与服务器全双工、双向得通信。在js中 创建webSocket时,一个HTTP请求会发送到服务器以初始化连接。服务器响应后,连接使用HTTP得upgrade头部从HTTP协议切换到WebSocket协议。这意味着WebSocket不能通过标准HTTP服务器实现,而必须使用支持该协议得专有服务器。因为 Web Socket使用了自定义协议,所以 URL方案(scheme)稍有变化:不能再使用 http://或 https://, 而要使用 ws://和 wss://。前者是不安全的连接,后者是安全连接。在指定 Web Socket URL 时,必须包 含 URL 方案,因为将来有可能再支持其他方案。 使用自定义协议而非 HTTP 协议的好处是,客户端与服务器之间可以发送非常少的数据,不会对 HTTP 造成任何负担。使用更小的数据包让 Web Socket 非常适合带宽和延迟问题比较明显的移动应用。 使用自定义协议的缺点是,定义协议的时间比定义 JavaScript API 要长。Web Socket 得到了所有主流浏 览器支持。
第二十五章:客户端存储
cookie:
最初用于在客户端存储会话信息,这个规范要求服务器在响应http请求时,通过发送Set-CookieHTTP头部包含会话信息。例如:
HTTP/1.1 200 OK Content-type:text/html Set-Cookie:name=value Other-header:ohter-header-value
这个HTTP响应会设置一个名为“name",值为"avlue"得cookie。名和值在发送时都会经过URL编码,浏览器会存储这些会话信息,并在之后得每个请求中都会通过HTTP头部cookie在将他们发回服务器,比如:
GET /index.jsl HTTP/1.1 Cookie: name=value Other-header: other-header-value
这些发送回服务器得额外信息可用于唯一标识发送请求得客户端。
限制:
cookie是与特定域绑定得,设置cookie后,他会与请求一起发送到他创建得域。只要遵守以下大致的限制,就不会在任何浏览器中碰到问题:
不超过300个cookie; 每个cookie不超过4096字节(4M) 每个域不超过20个cookie 每个域不超过81920字节(80M)
cookie得构成:
cookie在浏览器中是由以下参数构成得。
参数 | 描述 |
---|---|
名称 | 唯一标识cookie得名称,不区分大小写。 |
值 | 存储在cookie里得字符串值,这个值必须经过URL编码 |
域 | cookie有效得域。发送到这个域的所有请求都会包含对应的 cookie。这个值可能包含子域(如 www.wrox.com),也可以不包含(如.wrox.com 表示对 wrox.com 的所有子域都有效)。如果不明 确设置,则默认为设置 cookie 的域。 |
路径 | 请求URL中包含这个路径才会把cookie发送到服务器。例如,可以指定cookie只能由http://www.wrox.com/books/访问。 |
过期时间 | 表示何时删除cookie得时间戳。这个值是gmt格式,用于指定删除cookie得具体时间。 |
安全标识 | 设置后,只在使用ssl安全连接得情况下才会把cookie发送到服务器。 |
js中得cookie:
在js中只有BOM得document.cookie属性能处理。此属性返回包含页面中所有有效cookid字符串。以分号分隔。所有名和值都是url编码得,因此必须使用decodeURIComponent()解码。
WebStorage:
提供在cookie之外得存储会话数据得途径,提供跨会话持久化存储大量数据得机制。分两个:localStorage(永久存储)和sessionStorage(会话存储)
Storage类型:
用于保存名/值对数据,直至存储空间上限。Storage得实例与其他对象一样,但增加了以下方法:
方法 | 描述 |
---|---|
clear() | 删除所有值;不在火狐实现 |
getItem(name) | 取得给定name得值。 |
key(index) | 取得给定数值位置得名称 |
removeItem(name) | 删除给定name得名/值对 |
setItem(name,value) | 设置给定得值。 |
sessionStorage对象:
此对象只存储会话数据,这意味着数据只会存储到浏览器关闭。sessionStorage 对象应该主要用于存储只在会话期间有效的小块数据。如果需要跨会话持久存储 数据
locationStorage对象:
在修订的 HTML5 规范里,localStorage 对象取代了 globalStorage,作为在客户端持久存储 数据的机制。要访问同一个 localStorage 对象,页面必须来自同一个域(子域不可以)、在相同的端 口上使用相同的协议。
存储事件:
每当Storage对象发生变化时,都会在文档上触发storage事件。使用属性或setItem()设置值,使用delete或removeItem()删除值,以及每次调用clear()时都会触发这个事件。这个事件得事件对象有如下4个属性:
属性 | 描述 |
---|---|
domain | 存储变化对应得域 |
key | 被设置或删除得键。 |
newValue | 键被设置得新值,若键被删除则为null |
oldValue | 键变化之前得值。 |
第二十六章:模块
理解模块模式:
把逻辑分块,各自封装,相互独立,每个块自行决定对外暴露什么,同时自行决定引入执行哪 些外部代码。不同的实现和特性让这些基本的概念变得有点复杂,但这个基本的思想是所有 JavaScript 模块系统的基础。
模块标识符:
模块标识符是所有模块系统通用的概念。模块系统本质上是键/值实体,其中每个模块都有个可用 于引用它的标识符。这个标识符在模拟模块的系统中可能是字符串,在原生实现的模块系统中可能是模 块文件的实际路径。 有的模块系统支持明确声明模块的标识,还有的模块系统会隐式地使用文件名作为模块标识符。不 管怎样,完善的模块系统一定不会存在模块标识冲突的问题,且系统中的任何模块都应该能够无歧义地 引用其他模块。 将模块标识符解析为实际模块的过程要根据模块系统对标识符的实现。原生浏览器模块标识符必须 提供实际 JavaScript 文件的路径。除了文件路径,Node.js 还会搜索 node_modules 目录,用标识符去匹配 包含 index.js 的目录。
模块依赖:
模块系统的核心是管理依赖。指定依赖的模块与周围的环境会达成一种契约。本地模块向模块系统 声明一组外部模块(依赖),这些外部模块对于当前模块正常运行是必需的。
模块加载:
加载模块的概念派生自依赖契约。当一个外部模块被指定为依赖时,本地模块期望在执行它时,依 赖已准备好并已初始化。 在浏览器中,加载模块涉及几个步骤。加载模块涉及执行其中的代码,但必须是在所有依赖都加载 并执行之后。如果浏览器没有收到依赖模块的代码,则必须发送请求并等待网络返回。收到模块代码之 后,浏览器必须确定刚收到的模块是否也有依赖。然后递归地评估并加载所有依赖,直到所有依赖模块 都加载完成。只有整个依赖图都加载完成,才可以执行入口模块。
使用es6模块:
es6模块系统是集AMD和CommonJS之大成者。
模块标签及定义:
带有type=”module“属性得script标签会告诉浏览器相关代码应该作为模块执行。而不是作为传统得脚本执行。模块可以嵌入网页中,也可以作为外部文件引入:
<script type="moudle"> //模块执行代码 </script> ------------------------- <script src="url" type="module" ></script>
模块行为:
模块代码只在加载后执行。 模块只能加载一次。 模块是单例。 模块可以定义公共接口,其他模块可以基于这个公共接口观察和交互。 模块可以请求加载其他模块。 支持循环依赖。 ES6 模块系统也增加了一些新行为。 ES6 模块默认在严格模式下执行。 ES6 模块不共享全局命名空间。 模块顶级 this 的值是 undefined(常规脚本中是 window)。 模块中的 var 声明不会添加到 window 对象。 ES6 模块是异步加载和执行的。
模块导出:
es6模块支持两种导出: 命名导出:export关键字用于声明一个值为命名导出。导出语句必须在模块顶级。 默认导出(default export):
const foo = 'foo'; // 等同于 export default foo; export { foo as default };
模块导入:
模块可以通过使用 import 关键字使用其他模块导出的值。与 export 类似,import 必须出现在 模块的顶级
以下省略。回头再研究。