var promise = new Promise(function(resolve, reject) {
// 异步操作的代码
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
promise应用-图片加载
var preloadImage = function (path) {
return new Promise(function (resolve, reject) {
var image = new Image();
image.onload = resolve;
image.onerror = reject;
image.src = path;
});
};
Ajax
function search(term, onload, onerror) {
var xhr, results, url;
url = 'http://example.com/search?q=' + term;
xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onload = function (e) {
if (this.status === 200) {
results = JSON.parse(this.responseText);
onload(results);
}
};
xhr.onerror = function (e) {
onerror(e);
};
xhr.send();
}
search("Hello World", console.log, console.error);
or
function search(term) {
var url = 'http://example.com/search?q=' + term;
var xhr = new XMLHttpRequest();
var result;
var p = new Promise(function (resolve, reject) {
xhr.open('GET', url, true);
xhr.onload = function (e) {
if (this.status === 200) {
result = JSON.parse(this.responseText);
resolve(result);
}
};
xhr.onerror = function (e) {
reject(e);
};
xhr.send();
});
return p;
}
search("Hello World").then(console.log, console.error);
var xhr = new XMLHttpRequest();
// 指定通信过程中状态改变时的回调函数
xhr.onreadystatechange = function(){
// 通信成功时,状态值为4
if (xhr.readyState === 4){
if (xhr.status === 200){
console.log(xhr.responseText);
} else {
console.error(xhr.statusText);
}
}
};
xhr.onerror = function (e) {
console.error(xhr.statusText);
};
// open方式用于指定HTTP动词、请求的网址、是否异步
xhr.open('GET', '/endpoint', true);
// 发送HTTP请求
xhr.send(null);
字符串
是个特殊的数组
想要使用数组方法需要借助call方法。 unicode编码 \n 反斜杠转义 base64编码:btoa()编码 atob()解码 中文在进行base编码时,先用encodeURIComponent()进行编码,解码一样
对象
创建方法:
其他,大括号问题 eval('{foo: 123}') // 123 eval('({foo: 123})') // {foo: 123}
检查变量是否声明: if ('a' in window) { // 变量 a 声明过 } else { // 变量 a 未声明 }
查看对象属性:Object.keys(obj) 删除属性:delete //不能删除继承属性(不可枚举)
in运算符检查对象是否包含对应属性 不能识别继承的,可以用hasOwnproperty()
for in 循环遍历对象 它遍历的是对象所有可遍历(enumerable)的属性,会跳过不可遍历的属性 它不仅遍历对象自身的属性,还遍历继承的属性(使用构造函数和原型创建的对象)。
with语句 它的作用是操作同一个对象的多个属性时,提供一些书写的方便。
单纯从上面的代码块,根本无法判断x到底是全局变量,还是o对象的一个属性。 这非常不利于代码的除错和模块化,编译器也无法对这段代码进行优化,只能留到运行时判断,这就拖慢了运行速度。 因此,建议不要使用with语句,可以考虑用一个临时变量代替with。
数组
数组是个特殊的对象 伪数组转为数组 var arr = Array.prototype.slice.call(arrayLike); 数组空位 var arr = [1,,2] 空位就是数组没有这个元素,所以不会被遍历到,而undefined则表示数组有这个元素,值是undefined,所以遍历不会跳过。
函数
给函数参数设置默认值
改进
函数参数传递分为:传值传递、传址传递。 函数参数获取的是一个拷贝
arguments
变为真正的数组
闭包
闭包的最大用处有两个,一个是可以读取函数内部的变量,另一个就是让这些变量始终保持在内存中,即闭包可以使得它诞生环境一直存在。 请看下面的例子,闭包使得内部变量记住上一次调用时的运算结果。
闭包的另一个用处,是封装对象的私有属性和私有方法。
注意,外层函数每次运行,都会生成一个新的闭包,而这个闭包又会保留外层函数的内部变量,所以内存消耗很大。因此不能滥用闭包,否则会造成网页的性能问题。
立即执行函数
var = function(){}(); (function(){})(); +function(){}();
eval函数
将字符串当做语句执行
操作符
void(0)返回undefined
数据类型转换
Number()
Number函数将字符串转为数值,要比parseInt函数严格很多。基本上,只要有一个字符无法转成数值,整个字符串就会被转为NaN。
String() Boolean()
错误处理机制
Error对象
JavaScript解析或执行时,一旦发生错误,引擎就会抛出一个错误对象。JavaScript原生提供一个Error构造函数,所有抛出的错误都是这个构造函数的实例。
JavaScript的原生错误类型
SyntaxError 语法错误
ReferenceError ReferenceError是引用一个不存在的变量时发生的错误。
TypeError TypeError是变量或参数不是预期类型时发生的错误
URIError URIError是URI相关函数的参数不正确时抛出的错误
可以人为设置错误信息
实例的message属性获取
自定义错误
throw语句
JavaScript引擎一旦遇到throw语句,就会停止执行后面的语句,并将throw语句的参数值,返回给用户。
try catch 结构
为了对错误进行处理,需要使用try...catch结构。
finally代码块
try...catch结构允许在最后添加一个finally代码块,表示不管是否出现错误,都必需在最后运行的语句。
内置对象
Object
如果Object方法的参数是一个对象,它总是返回原对象。
Object 对象的静态方法 Object.keys():不包含不可枚举类型属性 Object.getOwnPropertyNames():包含 但两者都不包货继承属性
Object.prototype valueOf():返回当前对象对应的值。 toString():返回当前对象对应的字符串形式。 toLocaleString():返回当前对象对应的本地字符串形式。 hasOwnProperty():判断某个属性是否为当前对象自身的属性,还是继承自原型对象的属性。 isPrototypeOf():判断当前对象是否为另一个对象的原型。 propertyIsEnumerable():判断某个属性是否可枚举。
Array
Array.isArray()判断是否是数组
sort
some some方法是只要有一个数组成员的返回值是true,则整个some方法的返回值就是true,否则false。
every every方法则是所有数组成员的返回值都是true,才返回true,否则false。 注意,对于空数组,some方法返回false,every方法返回true,回调函数都不会执行
Number
属性:MAX_VALUE MIN_VALUE 方法:toFixed() toString() toExponential() // 科学计数表示 toPrecision() // 保留有效位数
自定义方法
String
match() match方法用于确定原字符串是否匹配某个子字符串,返回一个数组,成员为匹配的第一个字符串。如果没有找到匹配,则返回null。
match方法还可以使用正则表达式作为参数
search() 等同于match,但是返回值为匹配的第一个位置。如果没有找到匹配,则返回-1。
replace() 用于替换匹配的子字符串,一般情况下只替换第一个匹配(除非使用带有g修饰符的正则表达式)。
正则表达式
test esec
Promise
Promise对象只有三种状态。 异步操作“未完成”(pending) 异步操作“已完成”(resolved,又称fulfilled) 异步操作“失败”(rejected)
promise应用-图片加载
Ajax
or
跨域
CORS Q 请求 GET /cors HTTP/1.1 Origin: http://api.bob.com Host: api.alice.com Accept-Language: en-US Connection: keep-alive User-Agent: Mozilla/5.0... 相应 Access-Control-Allow-Origin: http://api.bob.com Access-Control-Allow-Credentials: true Access-Control-Expose-Headers: FooBar Content-Type: text/html; charset=utf-8
JSONP只支持GET请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。
本地存储
localStorage sessionStorage 方法: getItem setItem removeItem clear()
遍历操作
storage事件
除了key属性,event对象的属性还有三个: oldValue:更新前的值。如果该键为新增加,则这个属性为null。 newValue:更新后的值。如果该键被删除,则这个属性为null。 url:原始触发storage事件的那个网页的网址。
IndexedDB
现有的浏览器端数据储存方案,都不适合储存大量数据:Cookie 不超过4KB,且每次请求都会发送回服务器端;LocalStorage 在 2.5MB 到 10MB 之间(各家浏览器不同)。 所以,需要一种新的解决方案,这就是 IndexedDB 诞生的背景。
indexedDB.open()打开数据库
上面代码表示,打开一个名为test、版本为1的数据库。如果该数据库不存在,则会新建该数据库。如果省略第二个参数,则会自动创建版本为1的该数据库。
打开数据库的结果是,有可能触发4种事件。
success:打开成功。 error:打开失败。 upgradeneeded:第一次打开该数据库,或者数据库版本发生变化。 blocked:上一次的数据库连接还未关闭。
target.result属性就指向打开的IndexedDB数据库。
indexedDB实例对象的方法: 就是上面的DB
createObjectStore方法 用于创建存放数据的“对象仓库”(object store),类似于传统关系型数据库的表格。
同源限制-跨文档通信
cookie localStorage indexedDB iframe DOM Ajax document.getElementById("myIFrame").contentWindow.document // 父窗口获取子窗口 不同源把偶偶 window.parent.document.body // 同理
对于完全不同源的网站,目前有两种方法,可以解决跨域窗口的通信问题。
片段识别符(fragment identifier)
http://example.com/x.html#fragment的#fragment // 父窗口可以把信息,写入子窗口的片段标识符。 var src = originURL + '#' + data; document.getElementById('myIFrame').src = src; // 子窗口通过监听hashchange事件得到通知。 window.onhashchange = checkMessage;
function checkMessage() { var message = window.location.hash; // ... } // 子对父 parent.location.href= target + “#” + hash;
跨文档通信API(Cross-document messaging) window.postMessage
ajax跨域:
单线程模型
JavaScript同时只能执行一个任务,其他任务都必须在后面排队等待。
挂起处于等待中的任务,先运行排在后面的任务。等到IO设备返回了结果,再回过头,把挂起的任务继续执行下去。这种机制就是JavaScript内部采用的Event Loop机制。
消息队列:
运行线程只要发现消息队列不为空,就会取出排在第一位的那个消息,执行它对应的回调函数。等到执行完,再取出排在第二位的消息,不断循环,直到消息队列变空为止。
进入消息队列的消息,必须有对应的回调函数。
另一种情况是setTimeout会在指定时间向消息队列添加一条消息。如果消息队列之中,此时没有其他消息,这条消息会立即得到处理;否则,这条消息会不得不等到其他消息处理完,才会得到处理。因此,setTimeout指定的执行时间,只是一个最早可能发生的时间,并不能保证一定会在那个时间发生。
一旦当前执行栈空了,消息队列就会取出排在第一位的那条消息,传入程序。程序开始执行对应的回调函数,等到执行完,再处理下一条消息。
Event Loop:
所谓Event Loop机制,指的是一种内部循环,用来一轮又一轮地处理消息队列之中的消息,即执行对应的回调函数。
下面是一些常见的JavaScript任务
同步任务指的是,在JavaScript执行进程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;异步任务指的是,不进入JavaScript执行进程、而进入“任务队列”(task queue)的任务,只有“任务队列”通知主进程,某个异步任务可以执行了,该任务(采用回调函数的形式)才会进入JavaScript进程
所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。
运行以后的程序叫做“进程”(process)