概述
闭包
闭包(closure)指有权访问另一个函数作用域中变量的函数
一个作用域可以访问另一个函数的局部变量
闭包的主要作用:延伸了变量的作用范围
//fun方法访问了fn中的变量,所以fn是闭包函数
function fn() {
var num = 10;
fun();
function fun() {
console.log(num);//打印10
}
}
fn();
因为函数内部可以访问函数外部的变量,但是函数外部不可以访问函数内部的变量,即fun可以访问fn的所有变量但是fn不能访问fun的变量。当我们将fun作为返回值后,fn外部的函数就可以访问fn内的变量了
闭包的案例1
循环点击事件-用闭包的方式得到当前小li的索引号
//一般的方法
var lis = document.getElementsByTagName('li');
for (var i = 0; i < lis.length; i++) {
//当点击后执行该函数 i已经为4了 只是不能进入到for循环中
//for循环相当于一个闭包 点击事件内的i引用的是for循环中的变量 当i为4时 打印的结果也为4
// lis[i].onclick = function() {
// console.log(i);//打印结果为都是4
// }
//正确方法
lis[i].index = i;
lis[i].onclick = function() {
//注意这里是this!!!!
console.log(this.index);
}
}
//闭包的方法
var lis = document.getElementsByTagName('li');
for (var i = 0; i < lis.length; i++) {
//立即执行函数会形成一个单独的作用域,我们可以封装一些临时变量或者局部变量,避免污染全局变量
//所以这里的for循环会创建4个立即执行函数,给每个li创建一个独立的作用域
//相当于一个闭包
//记住这个写法!
(function(i){
lis[i].onclick=function(){
console.log(i);
}
})(i);
}
闭包的案例2
在一定时间之后打印所有li元素的内容
//3秒后打印所有li元素的内容
var lis = document.getElementsByTagName('li');
for (var i = 0; i < lis.length; i++) {
//这里跟上面同理
//因为settimeout里的回调函数也是异步的 要等主线程的任务执行完了才执行settimeout
//所以不能直接在for循环里面写settimeout函数
(function(i) {
setTimeout(() => {
console.log(lis[i].innerText);
}, 3000);
})(i);
}
例题1
//例题1
var name = "The window";
var object = {
name: "my object",
getNameFunc: function() {
return function() {
return this.name;
}
}
}
console.log(object.getNameFunc()());//打印 the window
//可以一步一步分解成
// var f = object.getNameFunc();
// 即f = function() {
// return this.name;
// }
// object.getNameFunc()() 则为f(), 即
//f()=(function(){
// return this.name;
// })();
//这就是执行了一个匿名函数,匿名函数的调用者是window
//所以这里面的this指的是window
//所以打印出来是the window
//这里没有闭包
例题2
//例题2
var name = "The window";
var object = {
name: "my object",
getNameFunc: function() {
var that = this;
return function() {
return that.name;
}
}
}
console.log(object.getNameFunc()());//打印my object
//可以一步一步分解成
// var f = object.getNameFunc();
// 即f = function() {
// return that.name;
// }
// object.getNameFunc()() 则为f(), 即
//f()=(function(){
// return that.name;
// })();
//这里的that是getnamefunc方法里面的this,getnamefunc的调用者是object
//所以这里面的this指的是object
//所以打印出来是my object
//这里使用了闭包 getnamefunc就是一个闭包函数
闭包的问题:
由于闭包回携带包含它的函数的作用域,因此会比其他函数占用更多的内存,过度使用闭包可能会导致内存占用过多。
作用域链的配置机制引出了一个值得注意的副作用,即闭包只能取得包含函数中任何变量的最后一个值
js中的栈内存和堆内存
栈内存主要存储各种基本类型的变量,包括boolean,number,string,undefined,null, * * 以及对象变量的指针 。比如var a=new A()中,变量a就是存储在栈中,而new出来的对象存储在堆上,对应地址是指针a存的内容
堆内存主要存储像对象Object这种变量类型的存储
promise
解决回调地狱的问题
假如有好几个函数依赖调用,即b依赖a,c依赖b,d依赖c。因为ajax的依赖关系会导致一个很深的回调嵌套,这就是回调地狱
promise是一个对象,用来传递异步操作的消息。
promise对象代表一个异步操作,有三种状态:
Pending(进行中)
Resolved(已完成 也叫做fulfilled)
Rejected(已失败)
只有异步操作的结果,可以决定当前是哪一种状态。一旦状态设定了就不能改变。
promise中的回调函数(即.then中的内容)是在微任务中的,其他的是在主线程中。
promise必须有一个then方法,then方法必须返回一个promise
基本语法:
//pending 准备阶段
//resolved 成功状态
//rejected 失败状态
new Promise((resolve, reject) => {
//resolve和reject中的参数会传递到then中
resolve("成功状态");
//reject("拒绝状态");
}).then(
//成功
value => {
console.log(value + ":成功后的业务处理1");
},
//失败
reason => {
console.log(reason + ":失败后的业务处理1");
}
)
//Promise.then返回的也是一个Promise对象
var p1 = new Promise((resolve, reject) => {
//resolve和reject中的参数会传递到then中
resolve("成功状态");
//reject("拒绝状态");
})
var p2 = p1.then(
//成功
value => {
console.log(value + ":成功后的业务处理1");
},
//失败
reason => {
console.log(reason + ":失败后的业务处理1");
}
)
console.log(p2);//p2也是一个promise
简单实现一个promise-原生js实现promise的封装
//简单实现一个promise
function myPromise(constructor) {
this.status = "pending";//定义状态改变前的初始状态
this.value = undefined;//定义状态为resolved的时候的状态
this.reason = undefined;//定义状态为rejected的时候的状态
function resolve(value) {
//两个==="pending",保证了状态的改变是不可逆的
if (this.status === "pending") {
this.value = value;
this.status = "resolved";
}
}
function reject(reason) {
//两个==="pending",保证了状态的改变是不可逆的
if (this.status == "pending") {
this.reason = reason;
this.status = "rejected";
}
}
//捕获构造异常
try {
constructor(resolve, reject);
} catch (e) {
reject(e);
}
}
//在myPromise的原型上定义链式调用的then方法
myPromise.prototype.then = function(onFullfilled, onRejected) {
let self = this;
switch (self.status) {
case "resolved":
onFullfilled(self.value);
break;
case "rejected":
onRejected(self.reason);
break;
default:
}
}
//为什么这里的status是undefined呢
//用已有的promise对象打印出status也是undefined
var p = new Promise(function(resolve, reject) {
resolve("成功2222");
})
console.log(p.status); //undefined
p.then(function(value, reason) {
console.log(value);//成功2222
console.log(reason);//undefined
})
then返回值的处理
如果then里面有返回值,则后一个then是对这个返回值进行处理,即接受到的参数就是这个返回值,默认是成功状态。
如果then里面没有另加返回值,则后一个then是对前一个then返回的promise对象进行处理。例如:
new Promise(resolve => {
resolve("resolve");
}).then(value => {
return "then1";
}, reason => {
return "reason1"
}).then(value => {
console.log(value); //这里的value是上一个then返回的"then1" 默认是成功状态
}, reason => {
console.log(reason); //打印then1
})
其他类型的promise封装
promise对象还可以封装成
{
then(resolve, reject) {
resolve(“这是对象”);
}
}
这样的形式。例如:
new Promise(resolve => {
resolve("resolve");
}).then(
value => {
return {
then(resolve, reject) {
resolve("这是对象");
}
} //这样的对象会被封装成promise
},
reason => {
return "reason1"
}).then(
value => {
console.log(value); //这里的value是上一个then返回的promise对象中的值 即“这是对象”
},
reason => {
console.log(reason);
})
**promise中catch的使用 **
可以在then后面加上catch进行错误处理。
reason没有捕捉到的错误或者是没有写reason进行错误处理,则会进入到catch中进行错误处理。例如:
new Promise((resolve, reject) => {
//resolve和reject中的参数会传递到then中
//resolve("成功状态");
reject("拒绝状态");
}).then(
value => {
console.log(value);
}
//下面这里没有写错误处理
//但是有catch 所以不会报错
//catch会进行错误处理
).catch(
error => {
console.log(error);
}
)
promise中finally的使用
finally中的代码始终都会被执行,不管是成功还是失败
const promise = new Promise((resolve, reject) => {
resolve("resolve");
//reject("reject");
})
.then(msg => {
console.log(msg);
})
//捕捉错误
.catch(error => {
console.log(error);
})
.finally(() => {
console.log("finally中永远会执行");
})
promise异步加载图片
function loadImage(src) {
return new Promise((resolve, reject) => {
const image = new Image();
image.src = src;
image.onload = () => {
resolve(image);
}
image.onerror = () => {
reject("加载失败")
};
//为什么下面的写法不行
//image.onerror = reject("加载失败");
document.body.appendChild(image);
})
}
loadImage("images/img1.jpeg").then(image => {
image.style.width = "100px";
image.style.height = "100px";
image.style.border = "solid 10px red";
});
下面是阮一峰博客上面的写法
function loadImageAsync(url) {
return new Promise(function(resolve, reject) {
const image = new Image();
image.onload = function() {
resolve(image);
};
image.onerror = function() {
reject(new Error('Could not load image at ' + url));
};
image.src = url;
});
}
用promise封装settimeout定时器
宏任务和微任务
js是单线程的,同步的任务进入主线程,异步的任务进入Event Table并注册函数。当指定的事情完成时,Event Table会将这个函数移入Event Queue。(宏任务和微任务是不同的Event Queue)。主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,进入主线程执行。上述过程会不断重复,也就是常说的Event Loop(事件循环)。
js遇到宏任务先执行宏任务,将宏任务放入eventquene任务队列,再执行微任务,将微任务放入eventquene任务队列。但是这两种任务的任务队列不是一样的。当主线程的任务执行完后,先寻找微任务去执行,再寻找宏任务去执行。
宏任务一般是:script中的整体代码,setTimeout(settimeout不是直接的把你的回掉函数放进上述的异步队列中去,而是在定时器的时间到了之后,把回掉函数放到执行异步队列中去。如果此时这个队列已经有很多任务了,那就排在他们的后面。这也就解释了为什么setTimeOut为什么不能精准的执行的问题了),setInterval
微任务一般是:Promise,process.nextTick
promise中的回调函数是在微任务中的,其他的是在主线程中。例如:
//1
setTimeout(() => {
console.log("settimeout"); //4 这是在宏任务中
})
new Promise(resolve => {
resolve();//创建微任务 这个执行了才会执行回调函数中表示成功的代码
console.log("promise"); //1 注意!!这是在主线程中
}).then(
value => {
console.log("成功"); //3 这里的回调函数是在微任务中
}
);
console.log("主任务"); //2 主线程
//2
new Promise(resolve => {
setTimeout(() => {
console.log("settimeout"); //3
resolve();//创建微任务 这个执行了才会将then里面的函数加入到微任务中
}, 0)
console.log("promise"); //1
}).then(
value => {
console.log("成功"); //4
}
);
console.log("主任务"); //2
ES6中的Set()和Map()方法
- Set
Set集合是一种无重复元素的列表
声明一个set集合
let s = new Set();
let s1 = new Set([1,2,3,4,5]);
求元素的个数
console.log(s1.size);
添加元素
s1.add('55');
删除元素
s1.delete(1);//参数是set集合的内容 不是索引
检测set集合中是否存在某个值,存在返回true,不存在返回false
console.log(s1.has('55'))
清空元素
s1.clear();
遍历
//注意这里是of不是in!!!
for(let v of s1){
console.log(v);
}
//或者
var a = ['A', 'B', 'C'];
a.forEach(function (element, index, array) {
//forEach是iterable内置的方法,它接收一个函数,每次迭代就自动回调该函数。
// element: 指向当前元素的值
// index: 指向当前索引
// array: 指向Array对象本身
alert(element);
});
- Set对象的作用
数组去重
var arr = [1, 2, 3, 4, 5, 6, 7, 6, 5, 4, 8];
var set = new Set(arr);
console.log(...set);//打印 1 2 3 4 5 6 7 8
//或者
//arr = Array.from(set);//Array.from方法会将一个类数组对象或者可遍历对象(例如set集合,字符串,键值对对象(里面必须要含有length属性用来指定数组的长度))转换成一个真正的数组
//console.log(arr);打印 [1,2,3,4,5,6,7,8]
交集
let arr = [1,2,3,4,5,4,3,2,1];
let arr2 = [4,5,6,5,6];
let result = [...new Set(arr)].filter(item=>{
let s2 = new Set(arr2); // 4,5,6
if(s2.has(item)){
return true;
}else{
return false;
}
})
console.log(result)//打印 [4,5]
并集
let arr3 = [1, 2, 3, 4, 5, 4, 3, 2, 1];
let arr4 = [4, 5, 6, 5, 6];
//注意Set()括号里面是一个数组!!!这里是两个数组合并 要注意用[]括起来!!!
let set2 = new Set([...arr3, ...arr4]);
console.log(...set2);//打印 1 2 3 4 5 6
差集
let arr = [1,2,3,4,5,4,3,2,1];
let arr2 = [4,5,6,5,6];
let diff = [...new Set(arr)].filter(item=> !(new Set(arr2).has(item)))
console.log(diff);//打印 [1,2,3]
- Map
Map集合内含有多组键值对,集合中每个元素分别存放着可以访问的键名和它对应的值
键名的等价性是通过调用Object.is()方法实现的,所以数字5和字符串5会被识别为两种类型,可以分别作为独立的两个键出现在程序中。
声明一个Map
let m = new Map();
添加元素
m.set('name','galaxy');
m.set('change',function(){
console.log('我们可以改变你')
})
获取元素的个数
console.log(m.size);
删除元素
m.delete('name');
获取元素
console.log(m.get('change'));
清空Map
m.clear()
遍历
for(let v of m){
console.log(v);
}
ES6中Map相对于Object对象有几个区别:
- Object对象有原型, 也就是说他有默认的key值在对象上面,
除非我们使用Object.create(null)创建一个没有原型的对象; - 在Object对象中, 只能把String和Symbol作为key值, 但是在Map中,key值可以是任何基本类型(String,
Number, Boolean, undefined, NaN….),或者对象(Map, Set, Object, Function ,
Symbol , null….); - 通过Map中的size属性, 可以很方便地获取到Map长度, 要获取Object的长度, 你只能用别的方法了;
Map实例对象的key值可以为一个数组或者一个对象,或者一个函数,比较随意
,而且Map对象实例中数据的排序是根据用户push的顺序进行排序的, 而Object实例中key,value的顺序就是有些规律了,
(他们会先排数字开头的key值,然后才是字符串开头的key值);
typeOf和instanceOf
- typeOf
typeOf的返回值是一个字符串,说明运算符的类型
typeof 一般只能返回如下几个结果:“number”、“string”、“boolean”、“object”、“function” 和 “undefined”。
运算数为数字 typeof(x) = “number”
字符串 typeof(x) = “string”
布尔值 typeof(x) = “boolean”
对象,数组和null typeof(x) = "object"
函数 typeof(x) = “function”
若运算数未定义,则返回“undefined”
若运算数是Symbol类型,则返回“symbol”
console.log(typeof Undefined); //undefined
let a = Symbol();
console.log(typeof a); //symbol
我们可以使用 typeof 来获取一个变量是否存在,如 if(typeof a!=“undefined”){alert(“ok”)},而不要去使用 if(a) 因为如果 a 不存在(未声明)则会出错,对于 Array,Null 等特殊对象使用 typeof 一律返回 object,这正是 typeof 的局限性。
- instanceOf
instanceof 运算符用来判断一个变量是否是某个对象的实例
语法:object instanceof constructor
参数:object(要检测的对象.)constructor(某个构造函数)
描述:instanceof 运算符用来检测 constructor.prototype 是否存在于参数 object 的原型链上。
例如:a instanceof b?alert(“true”):alert(“false”); //a是b的实例?真:假
如 :var a=new Array();
alert(a instanceof Array); // true,
同时 alert(a instanceof Object) //也会返回 true;
这是因为 Array 是 object 的子类。
再如:function test(){};
var a=new test();
alert(a instanceof test) 会返回true
以上图为参考
// 定义构造函数
function C(){}
function D(){}
var o = new C();
// true,因为o是C的实例 o在C的原型链上
o instanceof C;
// false,因为 o不是D的实例
o instanceof D;
o instanceof Object; // true,因为o的原型链上存在Object
C.prototype instanceof Object // true,同上
C.prototype = {};
var o2 = new C();
o2 instanceof C; // true
o instanceof C; // false,C.prototype指向了一个空对象,o此时不在C的原型链上
D.prototype = new C(); // 继承
var o3 = new D();
o3 instanceof D; // true
o3 instanceof C; // true
判断数组的四种方法
- instanceof
let a = [];
a instanceof Array; //true
- constructor
let a = [1,3,4];
a.constructor === Array;//true
- Object.prototype.toString.call()
let a = [1,2,3]
Object.prototype.toString.call(a) === '[object Array]';//true
- Array.isArray()
let a = [1,2,3]
Array.isArray(a);//true
Boolean()函数
可以对任何数据类型的值调用Boolean()函数,并且总会返回一个Boolean值。
返回的值是true还是false,取决于要转换值的数据类型及其实际值。下表给出了各种数据类型及其对应转换规则
先记住值为false的参数有哪些
Number()函数
转换规则:
- 如果是Boolean值,true和false分别被转换为1和0
- 如果是数字值,简单的传入和返回
- 如果是null值,返回0
- 如果是undefined,返回NaN
- 如果是字符串,遵循下列规则:
- 如果字符串中只包含数字(包括前面带正号或负号的情况),则将其转换为十进制数值,即"1"会变成1,"123"会变成123,而"011"会变成11(前导的零被忽略了);
- 如果字符串中包含有效的浮点格式,如"1.1",则将其转换为对应的浮点数值(同样会忽略前导零)
- 如果字符串包含有效的十六进制格式,例如"0xf",则将其转换为相同大小的十进制整数值
- 如果字符串是空的(不包含任何字符),则将其转换为0
- 如果字符串中包含除上述字符格式之外的字符,则将其转换为NaN
- 如果是对象,则调用对象的valueOf()方法,然后依照前面的规则转换返回的值.如果转换的结果是NaN,则调用对象的toString()方法,然后再次依照前面的规则转换返回的字符串
var num1 = Number("Hello world!");//NaN
var num2 = Number("");//0
var num3 = Number("000011");//11
var num4 = Number(true);//1
console.log(Number(undefined));//NaN
console.log(Number(11.22));//11.22
console.log(Number(0x16));//22
isNaN()函数
NaN和任何数都不相等,包括它本身
NaN(not a number)是Number类型中的中一个特殊的属性,表示非数字。可以通过Number.NaN来访问
isNaN() 函数用于检查其参数是否是非数字值。
如果参数值为 NaN 或字符串、对象、undefined等非数字值则返回 true, 否则返回 false。
需要注意的是,isNaN() 函数其实并不能像它的描述中所写的那样,数字值返回 false,其他返回 true。
实际上,它是判断一个值能否被 Number() 合法地转化成数字。
这中间有什么区别呢,主要提现在一些特别的情况如下:
**1、数字形式的字符串。**例如 “123”、"-3.14",虽然是字符串型,但被 isNaN() 判为数,返回 false。(“12,345,678”,“1.2.3” 这些返回 true)
2、空值。 null、空字符串""、空数组[],都可被Number()合法的转为0,于是被isNaN认为是数,返回false。(undefined、空对象{}、空函数等无法转数字,返回true)
**3、布尔值。**Number(true)=1,Number(false)=0,所以isNaN对布尔值也返回false。
**4、长度为 1 的数组。**结果取决于其中元素,即:isNaN([a])=isNaN(a),可递归。例如isNaN([[“1.5”]])=false。
**5、数字特殊形式。**例如"0xabc"、“2.5e+7”,这样的十六进制和科学计数法,即使是字符串也能转数字,所以也返回false。
可能还有其他情况,一时想不到了。
总之,很多时候不能用单纯用 isNaN() 取判断。
比如一个空值或者数组,甚至是包含字母和符号的字符串,它都有可能告诉你这是数值。还是要结合具体情况使用。
ajax
- 定义及作用
定义:Ajax(Asynchronous Java and XML的缩写)是一种异步请求数据的web开发技术,在不需要重新刷新页面的情况下,Ajax 通过异步请求加载后台数据,并在网页上呈现出来。
作用:提高用户体验,减少网络数据的传输量
-
原理
-
ajax涉及的知识点
-
readyState:xhr的属性 可以知道当前请求所处的状态
0-(未初始化)还没有调用open()方法
1-(启动)已调用open()方法,但尚未调用send()方法
2-(发送)已调用send()方法,但尚未接收到响应
3-(接收)已经接收到部分响应数据
4-(完成)已经接收到全部响应数据,而且已经可以在客户端使用了
-
status:HTTP状态码 根据响应状态判断请求是否成功
1XX:信息性状态码 ,表示接收的请求正在处理
2XX:成功状态码 , 表示请求正常处理
3XX:重定向状态码 ,表示需要附加操作来完成请求
4XX:客户端错误状态 ,表示服务器无法处理请求
5XX:服务器错误状态 ,表示服务器处理请求出错
-
get和post的区别
而post请求的参数放在send()里面
xhr对象的setRequestHeader()方法的请求头: -
原生JS封装ajax
<script>
//url type data 这三个是必须的
function ajax(options) {
//调用函数时如果options没有指定,就给它赋值{},一个空的Object
options = options || {};
// 请求格式GET、POST,默认为GET
options.type = (options.type || "GET").toUpperCase();
//响应数据格式,默认json
options.dataType = options.dataType || "json";
//初始化同步或异步请求 默认为异步
options.async = options.async || true;
//格式化参数
var params = formatParams(options.data);
var xhr; //创建对象
//考虑兼容性
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
} else if (window.ActiveObject) { //兼容IE6以下版本
xhr = new ActiveXobject('Microsoft.XMLHTTP');
}
//----------启动并发送一个请求----------
if (options.type == "GET") {
xhr.open("GET", options.url + '?' + params, options.async);
//设置超时
xhr.timeout = 20000;
xhr.ontimeout = function() {
console.log('connect timeout');
}
xhr.send(null);
} else if (options.type == "POST") {
//"方式" "地址" "标志位"
xhr.open("post", options.url, options.async); //初始化请求
xhr.timeout = 20000;
xhr.ontimeout = function() {
console.log('connect timeout');
}
//设置表单提交时的内容类型
//Content-type:数据请求的格式
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); //设置http头信息
xhr.send(params); //发送请求
}
//可以通过这个设置超时
//设置有效时间
// setTimeout(() => {
// if (xhr.readyState != 4) {
// xhr.abort(); //终止ajax异步请求
// }
// }, options.timeout);
//格式化参数
function formatParams(data) {
var arr = [];
for (var key in data) {
//encodeURIComponent()把字符串作为URL组件进行编码
arr.push(encodeURIComponent(key) + "=" + encodeURIComponent(data[name]));
}
//防止页面缓存
//浏览器为了提高用户访问同一页面的速度,会对页面数据进行缓存。当url请求地址不变时,
//有时候会导致浏览器不发送请求,直接从缓存中读取之前的数据。
//如果数据改变了,而没加随机数,读取的数据会跟之前一样。
//加上随机数,就是欺骗浏览器url改变了,会每次都向服务器发送请求而不去读缓存
arr.push(("randonNumber=" + Math.random()).replace(".", ""));
return arr.join("&");
}
//----------接收----------
//options.success成功之后的回调函数 options.error失败后的回调函数
//xhr.responseText,xhr.responseXML 获得字符串形式的响应数据或者XML形式的响应数据
//必须要在调用open()之前指定onreadystatechange时间处理程序才能确保跨浏览器兼容性
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
var status = xhr.status;
if (status >= 200 && status < 300 || status == 304) {
options.success && options.success(xhr.responseText, xhr.responseXML);
} else {
options.error && options.error(status);
}
}
}
}
//基本的使用实例
ajax({
url: "http://server-name/login",
type: 'post',
data: {
username: 'username',
password: 'password'
},
dataType: 'json',
//可以通过timeout设置超时
//timeout: 10000,
contentType: "application/json",
success: function(data) { //服务器返回响应,根据响应结果,分析是否登录成功
},
//异常处理
error: function(e) {
console.log(e);
}
})
</script>
创建xhr对象之后,要指定onreadystatechange方法,然后调用open()方法,然后调用setRequestHeader()方法,然后再调用send()方法,调用overrideMimeType()方法必须要在send()方法之前,onprogress()方法要在open()之前,要按这个顺序来
用promise实现对ajax的封装
const myAjax = function(url) {
const promise = new Promise(function(resolve, reject) {
//声明一个XMLHttpRequest对象
const xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.onreadystatechange = function() {
if (this.readyState !== 4) {
return;
}
if (this.status === 200) {
resolve(this.response);
} else {
reject(new Error(this.statusText));
}
};;
xhr.responseType = "json";
//设置请求头 Accept:浏览器能够处理的内容类型
xhr.setRequestHeader("Accept", "application/json");
xhr.send();
});
return promise;
};
myAjax("/posts.json").then(function(value) {
console.log('Contents: ' + value);
}, function(reason) {
console.error('出错了', reason);
});
最后
以上就是幸福白开水为你收集整理的javascript综合 二(闭包,堆内存和栈内存,promise,宏任务和微任务,Set和Map,typeOf和instanceOf,ajax,Boolean()和Number(),判断数组的方法)的全部内容,希望文章能够帮你解决javascript综合 二(闭包,堆内存和栈内存,promise,宏任务和微任务,Set和Map,typeOf和instanceOf,ajax,Boolean()和Number(),判断数组的方法)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复