Menu

js知识总结—ES6篇(二)

1.Fetch替代Ajax

Fetch并不是ES6的语法(应该是ES7),而是未来用于替代XMLHttpRequest的API, 它是W3C的正式标准。

Fetch API提供了一个fetch()方法,它被定义在BOM的window对象(全局方法)中。 该方法返回的是一个Promise对象。

fetch 规范与 jQuery.ajax() 不同:

  1. 当接收到一个代表错误的 HTTP 状态码时,从 fetch() 返回的 Promise 不会被标记为 reject, 即使响应的 HTTP 状态码是 404 或 500。相反,它会将 Promise 状态标记为 resolve (但是会将 resolve 的返回值的 ok 属性设置为 false ),仅当网络故障时或请求被阻止时,才会标记为 reject。
  2. fetch() 可以接受跨域 cookies;你也可以使用 fetch() 建立起跨域会话。跨域网站的Set-Cookie 头部字段将会被无视。
  3. fetch 不会发送 cookies。除非你使用了same-origin 的初始化选项。
  4. 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可以确保值的唯一,即使采用相同的名称,也会产生不同的值。

  1. Symbol一般用于对象的key。let id = Symbol("id"); let obj = {[id]:1}; 
  2. 获取obj对象的所有Symbol:Object.getOwnPropertySymbols(obj)
  3. 获取含Symbol的对象的所有key不能使用Object.keys(obj),而是Reflect.ownKeys(obj)
  4. 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与对象比较,其优势

  1. Object的键只能是字符串,Map的键可以是任意类型的值(包括对象)。所以Map是一种更完善的Hash结构实现。
  2. 我们可以轻易得改变或删除Object的属性或方法,安全性较低。但Map能够避免这个问题。Map提供了set和delete方法来重设或删除属性。
  3. 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

区别:

  1. WeakMap只接受对象(null除外、Symbol除外)作为键名,不接受其他类型的值作为键名。而Map键名可以是任意类型。
  2. WeakMap键名所指向的对象不计入垃圾回收机制。(键名所指向的对象被删除,该键值对就会自动清除。该键名指向的对象所占内存会被清除)
  3. WeakMap弱引用只针对键名而不是键值。键值依然正常引用。(键值引用的对象被删除,该键值对依然存在,该值引用的对象所占内存依然不被回收)

作用:

  1. 之所以键只接受对象,就是为了应对键所对应的对象可能会在将来消失的场景
  2. 有助于防止内存泄漏。

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

  1. 遍历的是数据结构中的key(遍历对象返回的对象key值,遍历数组返回的数组的索引)
  2. 不仅可以遍历对象构造器上的key,还会遍历对象原型上的可枚举key
  3. 也可以用来遍历数组,但是他是为遍历对象属性而构建的,所以不建议遍历数组。(而且他会遍历原型上可枚举的属性或方法,所以在原型上若有自定义的可枚举的方法也会被遍历出来导致出错,比如自定义:Array.prototype.a = xxx
  4. 不支持遍历MapSet
  5. 不支持breakcontinuereturn关键字
  6. 遍历是随机的
  7. 更适合用来遍历对象

将原型上可枚举的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

  1. 遍历的是数据结构中的value,且只能遍历可迭代的对象,或者说类数组结构,如Array, Map, Set, String, arguments, NodeList(Dom元素集合)等
  2. ES6新引入的特性
  3. 支持SetMap对象类型
  4. 不能循环普通的对象(会直接报错,因为普通对象不是类数组结构),需要通过和Object.keys()搭配
  5. 它可以与breakcontinuereturn关键字配合使用
  6. 遍历是有序的
// 遍历Map
var bbb = new Map([['a',1],['b',2]])

for(let val of bbb){ console.log(val) }

// ['a', 1]
// ['b', 2]

forEach()

  1. 用来遍历数组,不能遍历普通对象
  2. 不能使用breakcontinue中断循环,也不能使用 return 语句返回到外层函数
  3. 可以遍历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区别

ES6之includes方法详解及其与indexOf区别

本文固定连接:https://code.zuifengyun.com/2019/05/2018.html,转载须征得作者授权。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

¥ 打赏支持