1.Fetch替代Ajax
Fetch并不是ES6的语法(应该是ES7),而是未来用于替代XMLHttpRequest
的API, 它是W3C的正式标准。
Fetch API提供了一个fetch()
方法,它被定义在BOM的window
对象(全局方法)中。 该方法返回的是一个Promise对象。
fetch 规范与 jQuery.ajax() 不同:
- 当接收到一个代表错误的 HTTP 状态码时,从
fetch()
返回的 Promise 不会被标记为 reject, 即使响应的 HTTP 状态码是 404 或 500。相反,它会将 Promise 状态标记为 resolve (但是会将 resolve 的返回值的 ok 属性设置为 false ),仅当网络故障时或请求被阻止时,才会标记为 reject。 fetch()
可以接受跨域 cookies;你也可以使用fetch()
建立起跨域会话。跨域网站的Set-Cookie
头部字段将会被无视。- fetch 不会发送 cookies。除非你使用了
same-origin
的初始化选项。 - fetch发送post请求的时候发送2次,第一次状态码是204,第二次才成功原因,因为你用fetch的post请求的时候,导致fetch 第一次发送了一个Options请求,询问服务器是否支持修改的请求头,如果服务器支持,则在第二次中发送真正的请求。(跨域)
使用方法:
fetch('http://example.com/movies.json')
.then(function(response) {
return response.json();
})
.then(function(myJson) {
console.log(myJson);
});
// 传参
var url = 'https://example.com/profile';
var data = {username: 'example'};
fetch(url, {
method: 'POST', // or 'PUT'
body: JSON.stringify(data), // data can be `string` or {object}!
headers: new Headers({
'Content-Type': 'application/json'
})
}).then(res => res.json())
.catch(error => console.error('Error:', error))
.then(response => console.log('Success:', response));
2.介绍一下Symbol
Symbol是ES6新属性(不是构造函数,不能使用new关键字),代表用给定名称作为唯一标识,这种类型的值可以这样创建:let id = Symbol("id")
Symbol可以确保值的唯一,即使采用相同的名称,也会产生不同的值。
Symbol
一般用于对象的key。let id = Symbol("id"); let obj = {[id]:1};
- 获取obj对象的所有Symbol:
Object.getOwnPropertySymbols(obj)
- 获取含Symbol的对象的所有key不能使用
Object.keys(obj)
,而是Reflect.ownKeys(obj)
Reflect
是一个内置的对象,它提供拦截 JS 操作的方法。这些方法与proxy handlers的方法相同
3.Map数据结构
js的对象,本质上是键值对的集合,但是传统上只能用字符串当作键。
ES6提供了Map数据结构,它类似于对象,也是键值对的集合,但是"键"的范围不限于字符串(优势),各种类型的值(包括对象)都可以当作键。
let m=new Map();
let o={p:'key'};
m.set(o,'aaa');
m.get(o); // 'aaa'
作为构造函数,Map也可以接受一个数组作为参数。该数组的成员是一个个表示键值对的数组。
let map=new Map([
['name','张三'],
['age',18]
])
map.size // 2
map.get("name") //"张三"
4.Map与对象比较,其优势
- Object的键只能是字符串,Map的键可以是任意类型的值(包括对象)。所以Map是一种更完善的Hash结构实现。
- 我们可以轻易得改变或删除Object的属性或方法,安全性较低。但Map能够避免这个问题。Map提供了set和delete方法来重设或删除属性。
- Object使用for.in遍历会将其原型链上的属性和方法同时遍历。我们需要通过
obj.hasOwnProperty
来筛选当前的属性是在自己,还是在原型链上的。或者使用Object.keys(obj)
方法取出键数组再进行遍历。而Map提供了forEach/keys/values等方法。
5.Map 与 WeakMap 的区别
Map
和 WeakMap
是两种数据结构,可用于操纵键和值之间的关系。WeakMap
(弱引用的Map)也用于生成键值对的集合。
WeakMap
可以使用set
方法添加成员,也可以用get
方法获取值。也可以接收一个数组作为构造函数的参数。
const wm1 = new WeakMap()
const key = {foo:1}
wm1.set(key,2)
wm1.get(key) //2
// 接受复合数组为参数
const key2 = [1,2,3]
const wm2 = new WeakMap([
[key,'foo'],
[key2,'bar']
])
wm2.get(key2) //bar
区别:
WeakMap
只接受对象(null除外、Symbol除外)作为键名,不接受其他类型的值作为键名。而Map
键名可以是任意类型。WeakMap
键名所指向的对象不计入垃圾回收机制。(键名所指向的对象被删除,该键值对就会自动清除。该键名指向的对象所占内存会被清除)WeakMap
弱引用只针对键名而不是键值。键值依然正常引用。(键值引用的对象被删除,该键值对依然存在,该值引用的对象所占内存依然不被回收)
作用:
- 之所以键只接受对象,就是为了应对键所对应的对象可能会在将来消失的场景。
- 有助于防止内存泄漏。
WeakMap
设计目的在于,有时候我们想在某个对象上面放一些数据,但是会形成对这个对象的引用,一旦不在需要这个对象,我们除删除这个对象之外,也必须删除这个引用,否则垃圾回收机制就不会释放这个对象所占的内存,如果忘了删,就会造成内存泄漏。
var aaa = {a:1}
var bbb = [aaa,'sadad']
// 当不在需要aaa时
aaa = null
// 但bbb对aaa的引用依然存在
而WeakMap
键名所引用的对象都是弱引用,即垃圾回收机制(CG)不该将该引用考虑在内,因此,只要引用的对象及其他引用都删除,CG就会释放该对象的内存。也就是说,一旦不需要,WeakMap
中键名对象和所对应的键值对就会消失(亲测不会立即清除,而是在下次CG回收时清除),不需要手动删除。
6.for...in、for...of、forEach()有什么区别
for...in
- 遍历的是数据结构中的key(遍历对象返回的对象key值,遍历数组返回的数组的索引)
- 不仅可以遍历对象构造器上的key,还会遍历对象原型上的可枚举key
- 也可以用来遍历数组,但是他是为遍历对象属性而构建的,所以不建议遍历数组。(而且他会遍历原型上可枚举的属性或方法,所以在原型上若有自定义的可枚举的方法也会被遍历出来导致出错,比如自定义:
Array.prototype.a = xxx
) - 不支持遍历
Map
、Set
- 不支持
break
、continue
和return
关键字 - 遍历是随机的
- 更适合用来遍历对象
将原型上可枚举的key设为不可枚举方式:
function aaa(){
this.a=1
}
aaa.prototype.b = 2
for(let key in new aaa()){
console.log(key)
}
// 结果 a b
// 设为不可枚举
Object.defineProperty(aaa.prototype, 'b',
{ enumerable: false }
)
for(let key in new aaa()){
console.log(key)
}
// 结果 a
for...of
- 遍历的是数据结构中的value,且只能遍历可迭代的对象,或者说类数组结构,如
Array
,Map
,Set
,String
,arguments
,NodeList
(Dom元素集合)等 - ES6新引入的特性
- 支持
Set
和Map
对象类型 - 不能循环普通的对象(会直接报错,因为普通对象不是类数组结构),需要通过和
Object.keys()
搭配 - 它可以与
break
、continue
和return
关键字配合使用 - 遍历是有序的
// 遍历Map
var bbb = new Map([['a',1],['b',2]])
for(let val of bbb){ console.log(val) }
// ['a', 1]
// ['b', 2]
forEach()
- 用来遍历数组,不能遍历普通对象
- 不能使用
break
、continue
中断循环,也不能使用return
语句返回到外层函数 - 可以遍历value和引索
7.在js中使用ES6的模块化语法ES Module
在script
标签中使用type="module"
属性可以原生实现ES Module
// 方法 1 : 引入module.js,然后在script标签里面调用
<script type="module">
import test from './module.js';
console.log(test())
</script>
// 方法 2 : 直接引入index.js,使用src引入
<script type="module" src="./index.js"></script>
8.includes方法及其与indexOf区别
http://code.zuifengyun.com/2021/03/2154.html
本文固定连接:https://code.zuifengyun.com/2019/05/2018.html,转载须征得作者授权。