1. 简述async和await的原理和流程
1.async函数是es6提出的草案,es8出现的,它是generator的语法糖, 2.async定义在函数前,语义表示函数内部有异步操作,它代替了原先的*,await替换了yield。 3.async函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而await命令就是内部then命令的语法糖 async函数内部return语句返回的值,会成为then方法回调函数的参数。
async特点:(1)内置执行器 (2)返回值是promise 2.1 async函数返回的是 Promise 对象,可以作为await命令的参数 2.2 async函数内部抛出错误,会导致返回的 Promise 对象变为reject状。 态。抛出的错误对象会被catch方法回调函数接收到。 2.3:async函数返回的 Promise 对象,必须等到内部所有await命令后面的 Promise 对象执行完,才会发生状态改变,除非遇到return语句或者抛出错误。也就是说,只有async函数内部的异步操作执行完,才会执行then方法指定的回调函数。 (3)更好的语义化 流程: async 函数返回一个 Promise 对象,当函数执行的时候,一旦遇到 await 就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句。
2. 简述事件委托的原理
- 将事件绑定给目标的父级或祖先级元素,给未来元素(js 脚本创建的元素)添加事件。
- 原理:冒泡机制,判断事件源对象
- 优点:(1)减少DOM查找 (2)减少事件添加次数 (3)未来元素添加事件
3. jsonp和ajax的区别,如何实现jsonp
ajax:是一种局部刷新页面的技术 (请求数据的)
ajax用法:
(1)一个对象:XMLHttpRequest
(2)3个常用API:
建立连接:open("method", url , 是否异步) ---------默认true异步
请求头: setRequestHeader(' content-type ' , ' ')
发送请求: send()
(3)四个常用属性:
readystate : ajax状态码 status: http状态码
onreadystatechange: 状态码发生改变的触发的事件 responseText:响应文本
ajax的4个请求步骤(get)
1,实例一个XMLHttpRequest对象
2,使用open()方法,建立连接
3,使用send()方法,发送请求
4,为实例对象,设置readystatechange事件
jsonp:解决同源策略的影响。
利用script标签的src属性,执行js代码的方式实现跨域请求,请求的方式只能是get。
jsonp的实现:1.动态的创建script标签------------ createElement('script') 2.给script标签添加src属性 ----------script.src = "url?数据" 3.将script标签放进页面 document.body . appendChild(script) 4.设置一个全局的回调函数 --------(data中就是请求到的数据) function callback(data){}
4. http的常用请求头有哪些,请举例说明。
accept 请求报头域,指定客户端可以接收的类型有哪些 accept-encoding:指定客户端可接收的内容编码 accept-language:指定客户端可接收的编码语言 host:用户指定请求资源的主机和端口号 cookies:用于存储本地的数据 refer:用于标识这个请求是从哪个页面来的,如登录前是从主页来的,就显示主页的信息 user-agent(UA):用于识别用户的使用的客户端版本等信息 content-type:用于标识具体请求的媒体类型,这里是表单类型
5. 常见http状态码有哪些 举例说明。
200 请求成功 304重定向 404资源不存在 500服务端错误
6. 请简述闭包的应用场景,并编写一个闭包。
闭包概念:是JS独有的函数嵌套结构。内层函数使用了外层函数的参数或变量,内层函数被当做返回值返回。
1:函数嵌套函数,内部函数可以使用外部函数的变量。 2:私有变量,永久存储。 闭包的好处: 1:变量永久存储,延长作用域。 2:避免全局污染,避免变量冲突。 闭包的缺点: 1:变量常驻内存,需要手动销毁 2:栈溢出,内存泄漏,垃圾回收机制无作用。
闭包使用场景:1.能用的计时器的地方就可以使用闭包
2.高频事件:例如点击事件,输入事件
function fn(a){
return function(b){
return a+b;
}
}
console.log(fn(5)(3));
7. 编写一个类 要求实例化的对象可以被 for-of 遍历
class User{ constructor(name, gender, age){ this.name = name; this.gender = gender; this.age = age; }
//[Symbol.iterator]:部署迭代器属性,可以使用for..of
//*: generator函数,解决异步的
*[Symbol.iterator](){
let keys = Object.keys( this ) ;--------获取对象所有的key,组成一个数组
for(let i = 0, j = keys.length; i < j; i++){
yield {
key: keys[i],
value: this[keys[i]]
};
}
}
}
let zhou = new User('zhou', 'male', 1);
for(let {key, value} of zhou){ console.log(key, value); } // 输出结果 // name zhou // gender male // age 1
8. 使用 JS 编写一个queryString类 ,要求实现 stringify 和 parse 函数
/**
- 简单实现一个queryString,具有parse和stringify的能力,
- parse,用于把一个URL查询字符串解析成一个键值对的集合。
- 输入:查询字符串 'foo=bar&abc=xyz&abc=123'
- 输出:一个键值对的对象
- {
- foo: 'bar',
- abc: ['xyz', '123'],
- }
- stringify,相反的,用于序列化给定对象的自身属性,生成URL查询字符串。
- 输入:一个键值对的对象
- {
- foo: 'bar',
- abc: ['xyz', '123'],
- }
- 输出:查询字符串 'foo=bar&abc=xyz&abc=123' */
const queryString = {
parse() {
/* 功能实现 /
let arg = arguments[0];
let obj = {}
let arr = arg.split("&")
arr = arr.map(item => {
return item.split("=");
})
for(let i=0,len=arr.length;i<len;i++){
let item = arr[i][0];
if(obj[item]){
obj[item] = [obj[item]].concat([arr[i][1]])
}else{
obj[arr[i][0]]=arr[i][1]
}
}
return obj;
},
stringify() {
/ 功能实现 */
let obj = arguments[0]
let str = ""
var arr = []
for(let item in obj){
if(Array.isArray(obj[item])){
let m= obj[item].map(i=>{
return item+"="+i
})
arr = arr.concat(m)
}else{
arr.push(item+"="+obj[item])
}
}
str += arr.join("&")
return str
},
};
console.log(queryString.parse('foo=bar&abc=xyz&abc=123')); // { foo: 'bar', abc: [ 'xyz', '123' ] } var res = { foo: 'bar', abc: ['xyz', '123'], } console.log(queryString.stringify(res)) // foo=bar&abc=xyz&abc=123
9. 简述数据类型 Symbol 的作用并举例说明
Symbol表示独一无二的值,是es6新增的基本数据类型,
它没有构造函数,不能通过new实例这个数据,
目的作用:为了解决对象属性名冲突的问题,顺带还具备模拟私有属性的功能。
let sm1 = Symbol('sm');
let sm2 = Symbol('sm');
sm1 === sm2 //结果:false
10. 如何阻止事件的默认行为和事件冒泡
默认事件:event.preventDefault() event.returnValue = false (ie)
事件冒泡:event.stopPropagtion event.cancelBubble = true (ie)