一.JS 同步与异步
JS是单线程执行的语言,同一时间只做一件事,为了解决程序假死问题,Js把待行任务分为同步任务和异步任务。
同步任务一完就执行后面的任务(非耗时);异步任务:JS将其委托给宿主环境执行,当异步任务完成后,会通知JS主线程执行异步任务的回调函数。
同步任务和异步任务的执行过程:
1.同步交给JS主线程按次序执行任务;
2.异步委托在宿主环境执行;
3.异步任务执行完毕后对应的回调函数会被添加到任务队列中等待执行;
4.JS主线程的执行栈清空后,任务队列中的回调函数次序执行;
5.JS主线程不断执行第四步,这种运行机制被称为EventLoop(事件循环)
二.Ajax
AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
传统的网页(不使用 AJAX)如果需要更新内容,必需重载整个网页面。
有很多使用 AJAX 的应用程序案例:新浪微博、Google 地图、开心网等等。
XMLHttpRequest 是 AJAX 的基础。
XMLHttpRequest 对象用于在后台与服务器交换数据。
XMLHttpRequest 对象是开发者的梦想,因为您能够:
- 在不重新加载页面的情况下更新网页
- 在页面已加载后从服务器请求数据
- 在页面已加载后从服务器接收数据
- 在后台向服务器发送数据
创建Ajax过程
1.创建XHR对象
2.设置请求参数 .open(Methods,服务器接口地址,异步trueor同步false)
3.发送请求,如果是post发送数据可以传递数据
4.监听请求成功后的状态变化 (readyState==4 && status==200)
- 0: 请求未初始化
- 1: 服务器连接已建立
- 2: 请求已接收
- 3: 请求处理中
- 4: 请求已完成,且响应已就绪
200: "OK" 500:服务器发生内部错误 |
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script>
function loadXMLDoc()
{
var xmlhttp;
xmlhttp=new XMLHttpRequest();//1.创建XHR对象
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)//4.
{
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET","/try/ajax/ajax_info.txt",true);//2.设置请求参数
xmlhttp.send();//3.发送请求(如果是post请求可以添加参数)
}
</script>
</head>
<body>
<div id="myDiv"><h2>使用 AJAX 修改该文本内容</h2></div>
<button type="button" onclick="loadXMLDoc()">修改内容</button>
</body>
</html>
三.Promise
promise是异步微任务,解决了异步多层嵌套回调的问题,让代码的可读性更高,更容易维护;promise是ES6提供的一个构造函数,新建一个promise对象,接收一个函数,这个函数有两个参数:resolve && reject (resolve和reject都是函数,调用resolve代表一切正常,reject是出现异常时所调用的)
使用:
new Promise(function (resolve, reject){
//要做的事
});
Promise 类有 .then() .catch() 和 .finally() 三个方法,这三个方法的参数都是一个函数,.then() 可以将参数中的函数添加到当前 Promise 的正常执行序列,.catch() 则是设定 Promise 的异常处理序列,.finally() 是在 Promise 执行的最后一定会执行的序列。 .then() 传入的函数会按顺序依次执行,有任何异常都会直接跳到 catch 序列
new Promise(function (resolve, reject) {
var a = 0;
var b = 1;
if (b == 0) reject("Divide zero");
else resolve(a / b);
}).then(function (value) {
console.log("a / b = " + value);
}).catch(function (err) {
console.log(err);
}).finally(function () {
console.log("End");
});
执行结果
a / b = 0
End
四. 箭头函数
箭头函数简化了函数的定义
1.当函数体是单条语句时,可以省略,return && {} ; 当函数体时多条语句时,不可省略
const x = (x, y) => x * y;
const x = (x, y) => { return x * y };
2. 箭头函数最大的特点是没有this,所以this是从外部获取的,继承上下文的this
3.箭头函数是不能提升的,所以需要在使用之前定义。
4.箭头函数适合简单的函数表达
五.JS继承的方法和优缺点
1.原型链继承
优点:父类方法可以复用
缺点:1.父类所有的引用数据类型(对象,数组)会被子类共享,
更改一个子类的数据,其他子类的数据也会受影响
2.子类实例不能给父类构造函数传参
例子:
function Pe() {
this.name = "小明"
this.eats = ["苹果"]
this.getName = () => {
console.log(this.eats)
}
}
Pe.prototype.get = () => {
console.log("原型属性上的方法")
}
function St() { }
St.prototype = new Pe();
const st1 = new St();
st1.name = "小红"
st1.eats.push("香蕉")
console.log(st1.name);
st1.getName()
console.log("-----------------------")
const st2 = new St();
console.log(st2.name);
st2.getName()
结果:
2.构造函数的继承
优点:父类的引用数据类型的数据不会被子类共享,不会相互影响
缺点:子类不能访问父类原型属性上的方法和参数
改变一点(改变this指向)
function St() {
Pe.call(this);
}
原来是
function St() { }
St.prototype = new Pe();
缺点
3.组合继承
将构造函数继承和原型链继承结合起来
优点:1.父类可以复用
2.父类中的引用属性不会被共享
3.可以访问到父类原型属性上的方法和参数
缺点:会调用两次父类的构造函数,会有两份一样的属性和方法,会影响性能
4.寄生组合继承(有一个中转)
前四种都是es5
5.Es6 class继承extends
class Person {
constructor() {
this.name = "小明"
this.eats = ["苹果"]
this.getName = () => {
console.log(this.eats)
}
};
get = () => {
console.log("原型属性上的方法")
}
}
class Student extends Person { }
const st1 = new Student();
st1.name = "小红"
st1.eats.push("香蕉")
console.log(st1.name);
st1.getName()
st1.get()
console.log("-----------------------")
const st2 = new Student();
console.log(st2.name);
st2.getName()