回调地狱:
与后台发生数据交互时,ajax请求回调中还有一个或多个ajax请求,这样的现象,形成了回调地狱
缺点:代码复杂,所有的请求一环套一环,逻辑不清晰。不方便阅读,不利于调试
解决方法:promise
一、promise(用于解决回调地狱的现象)
promise:允诺
承诺要去做某件事。
三种状态:
承诺的事情正在进行中。 pending
承诺的事情没有完成(失败了)。rejected
承诺的事情成功完成(成功)。resolved
执行的代码:
<script type="text/javascript">
//创建一个允诺对象
var pro=new Promise(function(success,failed){
//执行承诺的事情的执行过程
//承诺事情已经成功
// success(64726498);
failed("承诺的事情已经失败");
});
//pro.then(function(res){
//接收成功回调函数传递过来的结果,结果保存在res中
// console.log(res);
//});
//pro.catch(function(err){
//catch方法接收失败回调函数床底过来的结果,保存在err中
console.log(err);
//})(这样也可以输出,但是一般不这样输出,用下面的方法)
pro.then(function(res){
//接收成功回调函数传递过来的结果,保存在res中
console.log(res);
return "第一个then返回出来的结果"+res;
},function(err){
console.log(err);//承诺的事情已经失败
return "第一个then失败后返回出来的结果";
}).then(function(result){
console.log(result);
},function(err){
console.log(err);//第一个then失败后返回出来的结果
})
</script>
promise封装:
function promiseAjax(obj){
//回调函数
var pro=new Promise(function(success,failed){
//允诺使事情过程
var xhr=getXHR();
obj.url+="?rand="+new Date().getTime();
if(obj.method.toLowerCase()=="get"){
if(obj.data){
obj.url+="&"+parameter(obj.data);
}
}
xhr.open(obj.method,obj.url);
if(obj.method.toLowerCase()=="post"){
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
if(obj.data){
xhr.send(parameter(obj.data));
}else{
xhr.send();
}
}else{
xhr.send(null);
}
xhr.onreadystatechange=function(){
if(xhr.readyState==4){
if(xhr.status==200){
success(xhr.responseText);//接收后台返回来的值给pro
}else{
failed("响应出错;状态是:"+xhr.status+" 原因是:"+xhr.statusText);
}
}
}
});
return pro;//将后台返回来的值输出
}
function parameter(obj){
var arr=[];
for(var item in obj){
arr.push(item+"="+encodeURIComponent(obj[item]));
}
return arr.join("&");
}
function getXHR(){
var xhr=null;
if(window.XMLHttpRequest){
xhr=new XMLHttpRequest();
}else{
xhr=new ActiveXObject("Microsoft.XMLHTTP");
}
return xhr;
}
三、对象
回顾this
a.函数创建时产生一个this.
b.(谁调用指向谁)当有事件绑定,并执行了事件处理程序时,谁绑定的事件,事件处理程序中的this指向谁。
c.回调函数中的this指向window
d.匿名函数可以使用bind()改变this的指向
call()和apply()可以改变函数中的this指向
e.箭头函数本身没有this,它的this是继承父级而来。
f.箭头函数不能使用call()、apply() 和 bind()来改变this指向
g.严格模式下,全局函数的this是undefined;
"use strict";
function box(){
alert(this);//undefined
}
box();
h:面向对象下的一些this指向的是实例对象
四、对象与类
1)对象:当我们使用一些方法时,这些方法都存在了某个对象下,有了对象我们才能使用方法
对象从何而来?通过new一个构造函数,得到一个对象。
2)构造函数:构造函数就是传说中的类。
3)问题:
要创建很多同一类型的对象,会重复写很多代码。
要解决这个代码重复的问题,
就要应用到面向对象的方式来处理。
var person = {
name : "zhangsan",
age : 20,
run : function(){
alert("在跑步");
}
}
var person2 = {
name : "zhangsan",
age : 20,
run : function(){
alert("在跑步");
}
}
五、面向对象(它是一种高级的开发思想)。
开发思想说明:把一些功能或者共有的属性,进行封装,形成一种类型。通过这种类型可以创建无数个具体的对象,这些对象就可以使用这种类型的属性和方法
1)使用工厂模式来封装一种类型
function penson(name,age,sex){
var obj=new Object();
obj.name=name;
obj.age=age;
obj.sex=sex;
obj.eat=function(){
return this.name+"在吃饭";
}
return obj;
}
var zhangsan=penson("zhangsan",18,"女");
alert(zhangsan.eat());
alert(zhangsan instanceof Object);//true指向不明确,没有指出具体的类型
优点:解决创建多个同类对象代码重复问题;
缺点:这个对象所属类型不明确
写法不规范
2)构造函数方式
function Penson(name,age,sex){
this.name=name;//在构造函数内部定义的属性叫实例属性
this.age=age;
this.sex=sex;
this.eat=function(){//在构造函数内部定义的方法叫实例方法
return this.name+"在吃饭";
}
}
var p1=new Penson("张三",18,"女");// p1是构造函数的实例对象
alert(p1.eat());
alert(p1 instanceof Object);
alert(p1.name);
缺点:浪费内存资源
优点:解决了创建多个同类对象代码重复问题;
解决了对象所属类型不明确。
代码规范。
3)构造函数原型(prototype是构造函数下的原型对象。)
原型属性和方法被所有的实例对象共享。一个改了,大家都改变了。
私有的属性写在实例里面。
公有的方法写在原型下面。
function Penson(name,age,sex){
this.name=name;
this.age=age;
this.sex=sex;
}
Person.prototype.phone = "13488888888";//原型属性
Penson.prototype.eat=function(){//原型方法
return this.name+"在吃饭";
}
Penson.prototype.play=function(){
return this.name+"在玩球";
}
var p1=new Penson("张三",17,"女");
var p2=new Penson("李四",19,"女");
alert (p1.eat());// 张三在吃饭
alert(p2.eat());//李四在吃饭
alert(p1.play());//张三在玩球
alert(p1 instanceof Object);//true
补充:
面向对象开发的优缺点。
优点:
代码结构和逻辑清晰,易于阅读和维护。
缺点:
代码增多,延长了开发周期,增加开发成本。