es6-常见使用方法

这里写目录标题


ECMAScript 6 / ECMAScript 2015 新增了哪些新特性?

-跳转==开发常用的es6方法

*01.let与const

默认使用 const,只有当确实需要改变变量的值的时候才使用 let。这是因为大部分的变量的值在初始化后不应再改变,而预料之外的变量的修改是很多 bug 的源头;let在一个模块不能重复声明;
1.let不存在变量提升

var a=[];
for(var i=0;i<10;i++){
 let c=i;//变成var的话 就是9
 a[i]=function(){
     console.log(c)
   };
}
a[5]();//5

*02.类class

// 例子 1
//构造函数尽可能使用 Class 的形式

class Foo {
  static bar () {
    this.baz();
  }
  static baz () {
    console.log('hello');
  }
  baz () {
    console.log('world');
  }
}
Foo.bar(); // hello

//例2

class person{
        constructor(name='alex',age=18){
            this.name=name;
            this.age=age;
        }
        showname(){
            console.log(this.name)
        }
        showage(){
            console.log(this.age)
        }

    }
    let v=new person();
    v.showname()
    v.showage()

import:es6的导入=== 属于加载前置的机制,因此将其全放在代码顶部,代码解析逐个import获取一个引入的列表,先引入依赖,再向下执行代码,加载前置
require :commonJs的导入===加载滞后,代码执行到哪一行才进行加载;if(true){letquerystring=require(‘querystring’) }

2.1.静态函数

function obj(){}
obj.prototype.age=1;//实例属性
obj.staticTest="abc"
let o=new obj();

这个用类class来表示
class obj{
 myAge=123//静态属性
 static staticAge=999;
 static staticFn=function(){
    console.log("静态函数")
}
//箭头函数才向上用的别人的this
 myFn(){//上下文this与function是一致的,用的就是自己的
     console.log("实例的函数",this.myAge)
 }
}
let o1=new obj();
o1.myFn()

2.2继承

function P1(XXX){
  this.xxx=xxx;
  类似继承 this.prototype=p2.prototype
     继承玩的就是原型链
}

//例1
实例继承

class Person{
      age=100;
}
class Boy extends Person{
            name="jack";
}
const p=new Boy();
console.log(p)

例2

class Person{
      constructor(props){//这就是构造函数
            this.age=props.age
            console.log('触发了person')
      }
}
class Boy extends Person{
      constructor(props){
           super(props)//初始化父类构造器class person
//先person 后Boy
           this.name=props.name;
           console.log('触发了Boy')
     }
}

const p=new Boy({name:"apple",age:18});
console.log(p)

例3

class Shape {
  constructor(width, height) {
    this._width = width;
    this._height = height;
  }
  get area() {
    return this._width * this._height;
  }
}

const square = new Shape(10, 10);
console.log(square.area);    // 100
console.log(square._width);  // 10

* 03.模板字符串

需要拼接字符串的时候尽量改成使用模板字符串
标签模板:

let x = 'Hi', y = 'jack';
var res = message`${x}, I am ${y}`;
function message(content, value1, value2) {
	console.log(content); // [ "", ", I am ", "" ]
	console.log(value1); // Hi
	console.log(value2); // jack
}

这些参数将其拼合回去

function message(content, ...values) {
	let result = '';

	for (let i = 0; i < values.length; i++) {
		result += literals[i];
		result += values[i];
	}

	result += literals[literals.length - 1];

	return result;
}
function message(content, ...values) {
	let result = content.reduce((prev, next, i) => {
	    let value = values[i - 1];
	    return prev + value + next;
	});

	return result;
}

*04.箭头函数

注意什么东西

  • 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象
  • 不可以当作构造函数,也就是说,不可以使用new关键字,否则抛出错误
  • 不可以使用arguments对象,该对象在函数体内不存在(可用rest参数代替)
  • 不可以使用yield命令,因此箭头函数不能用作Generator函数
    ====不能使用箭头函数的情况:
    //例1
    —使用箭头函数定义对象的方法
let foo = {
  value: 1,
  getValue: () => console.log(this.value)
}
foo.getValue();  // undefined

例2

var person = {
    name:'alex',
    fav:()=>{
        console.log(this);//window
    },
    showName(){
        console.log(this);//person
    }
}

//例3
----定义原型方法

function Foo() {
  this.value = 1
}
Foo.prototype.getValue = () => console.log(this.value)
let foo = new Foo()
foo.getValue();  // undefined

//例4
-----作为事件的回调函数

const button = document.getElementById('myButton');
button.addEventListener('click', () => {
    console.log(this === window); // => true
    this.innerHTML = 'Clicked button';
});

箭头函数的this指向
this指向问题;
ES5中 this永远指向最后调用它的那个对象;

var name = "window";
var a = {
name : null,
fn : function () {
console.log(this.name);
}
}
var f = a.fn;
f(); // console.log(window);

ES6中 箭头函数的指向;

  • 箭头函数本身没有this对象,会引用外层函数或者对象的作用域。
  • 箭头函数本身没有this对象,会沿着作用域链去查找this绑定的对象;是基于作用域链去找this对象;
  • 箭头函数本身没有this对象,所以谈不上用call,apply,bind来改变this指向;
const name = 'window';
function out() {
setTimeout(()=> {console.log(this.name)});
}
const obj = {
name: 'hhhh'
};
out.apply(obj) 

*05.对象字面量

05.1.增强的对象字面量

// 例子1

// bad
const something = 'y'
const x = {
  something: something
}

// good
const something = 'y'
const x = {
  something
};

05.2动态属性

// 例子2

const x = {
  ['a' + '_' + 'b']: 'z'
}

console.log(x.a_b); // z

*06.解构赋值

06.1.对象的基本解构

// 例子1

componentWillReceiveProps(newProps) {
	this.setState({
		active: newProps.active
	})
}

componentWillReceiveProps({active}) {
	this.setState({active})
}

// 例子 2

// bad
handleEvent = () => {
  this.setState({
    data: this.state.data.set("key", "value")
  })
};

// good
handleEvent = () => {
  this.setState(({data}) => ({
    data: data.set("key", "value")
  }))
};

06.2.对象深度解构

// 例子4

// bad
function test(fruit) {
  if (fruit && fruit.name)  {
    console.log (fruit.name);
  } else {
    console.log('unknown');
  }
}

// good
function test({name} = {}) {
  console.log (name || 'unknown');
}
// 例子 5

let obj = {
    a: {
      b: {
        c: 1
      }
    }
};

const {a: {b: {c = ''} = ''} = ''} = obj;

06.3.数组解构

// 例子6

// bad
const spliteLocale = locale.splite("-");
const language = spliteLocale[0];
const country = spliteLocale[1];

// good
const [language, country] = locale.splite('-');

06.4变量重命名

// 例子8

let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
console.log(baz); // "aaa"

06.5仅获取部分属性

// 例子 9

function test(input) {
  return [left, right, top, bottom];
}
const [left, __, top] = test(input);

function test(input) {
  return { left, right, top, bottom };
}
const { left, right } = test(input);

*07.Promise函数

07.1 Promise有几种状态

         Promise对象有以下特点
         * 对象的状态不受外界影响,Promise对象代表一个异步操作,具有三种状态:pending(进行中)、fulfilled(已成功)、rejected(已失败)。只有异步操作的结果可以决定当前是哪一种状态,任何其他操作都无法改变这个状态
         * 一旦状态改变,就不会再次改变
         * 任何时候都可以得到结果
        (Promise对象的状态改变,只有两种可能  1.从pending变为fulfilled    2.从pending变为rejected
         只要这两种情况发生,状态就凝固了(不会再变化),会一直保持这个结果,这时就称为resolved(已定型),如果改变已经发生,再对Promise对象添加回调函数,也会立即得到这个结果

07.2. catch与reject的区别

   reject - 返回一个新的 Promise 实例,该实例的状态为rejected
    catch - 用于指定发生错误时的回调函数

07.2.1基本示例

// bad

  request(url, function(err, res, body) {
    if (err) handleError(err);
    fs.writeFile('1.txt', body, function(err) {
        request(url2, function(err, res, body) {
            if (err) handleError(err)
        })
    })
  });

   // good
   request(url)
   .then(function(result) {
    return writeFileAsynv('1.txt', result)
   })
   .then(function(result) {
    return request(url2)
   })
   .catch(function(e){
      handleError(e)
   });

07.2.2.finally

      fetch('file.json')
    .then(data => data.json())
    .catch(error => console.error(error))
   .finally(() => console.log('finished'));

07.3手写promise

基础版

const p1 = new Promise((resolve, reject) => {
  console.log('create a promise');
  resolve('成功了');
})

console.log("after new promise");

const p2 = p1.then(data => {
  console.log(data)
  throw new Error('失败了')
})

const p3 = p2.then(data => {
  console.log('success', data)
}, err => {
  console.log('faild', err)
})

A+规范

const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';

class Promise {
  constructor(executor) {
    this.status = PENDING;
    this.value = undefined;
    this.reason = undefined;
    // 存放成功的回调
    this.onResolvedCallbacks = [];
    // 存放失败的回调
    this.onRejectedCallbacks= [];

    let resolve = (value) => {
      if(this.status ===  PENDING) {
        this.status = FULFILLED;
        this.value = value;
        // 依次将对应的函数执行
        this.onResolvedCallbacks.forEach(fn=>fn());
      }
    } 

    let reject = (reason) => {
      if(this.status ===  PENDING) {
        this.status = REJECTED;
        this.reason = reason;
        // 依次将对应的函数执行
        this.onRejectedCallbacks.forEach(fn=>fn());
      }
    }

    try {
      executor(resolve,reject)
    } catch (error) {
      reject(error)
    }
  }

  then(onFulfilled, onRejected) {
    if (this.status === FULFILLED) {
      onFulfilled(this.value)
    }

    if (this.status === REJECTED) {
      onRejected(this.reason)
    }

    if (this.status === PENDING) {
      // 如果promise的状态是 pending,需要将 onFulfilled 和 onRejected 函数存放起来,等待状态确定后,再依次将对应的函数执行
      this.onResolvedCallbacks.push(() => {
        onFulfilled(this.value)
      });

      // 如果promise的状态是 pending,需要将 onFulfilled 和 onRejected 函数存放起来,等待状态确定后,再依次将对应的函数执行
      this.onRejectedCallbacks.push(()=> {
        onRejected(this.reason);
      })
    }
  }
}

总结:
promise 有三个状态:pending,fulfilled,or rejected;「规范 Promise/A+ 2.1」
new promise时, 需要传递一个executor()执行器,执行器立即执行;
executor接受两个参数,分别是resolve和reject;
promise 的默认状态是 pending;
promise 有一个value保存成功状态的值,可以是undefined/thenable/promise;「规范 Promise/A+ 1.3」
promise 有一个reason保存失败状态的值;「规范 Promise/A+ 1.5」
promise 只能从pending到rejected, 或者从pending到fulfilled,状态一旦确认,就不会再改变;
promise 必须有一个then方法,then 接收两个参数,分别是 promise 成功的回调 onFulfilled, 和 promise 失败的回调 onRejected;「规范 Promise/A+ 2.2」
如果调用 then 时,promise 已经成功,则执行onFulfilled,参数是promise的value;
如果调用 then 时,promise 已经失败,那么执行onRejected, 参数是promise的reason;
如果 then 中抛出了异常,那么就会把这个异常作为参数,传递给下一个 then 的失败的回调onRejected;

      Promise.all([GetPlayList(data), GetPayTips(data)]).then((res) => {
        this.performList = (res[0] && res[0].body && res[0].body.performList) || [];
        var SESSION_BOOLEAN = res[0].body && res[0].body.clearSession;
        var payCode = res[1].body && res[1].body.payTypes && res[1].body.payTypes[0] && res[1].body.payTypes[0].payCode;
        // console.log(SESSION_BOOLEAN, '5555', res[1].body.payTypes[0], payCode);
        localStorage.setItem('payCode', JSON.stringify(payCode));
        this.payTypeTip = res[1].body.payTypes[0];
        if (SESSION_BOOLEAN) {
          this.dbclickHandle();
          return;
        }
      });

7.4Promise 的链式调用,和axios处理高并发?
应用场景:下一个操作依赖于上一个操作的结果或状态;
前提条件:.then方法中必须返回一个promise对象
运行过程:
1…then在链式调用时,
会等其前一个then 中的回调函数执行完毕;
2.并且返回成功状态的promise,才会执行下一个then的回调函数

//链式调用,回调地域
axios.get(_api_1)
.then(_d1=>{
    console.log(_d1.data)
	axios.get(_api_2).then(_d2=>{
         console.log(_d2.data)
	     axios.get(_api_3).then(_d3=>{
 	        console.log(_d3.data)
         })	
   })	
}) 

//axios.get()  这就是个promise对象
//链式调用,ok的方法
axios.get(_api_1)
.then(_d1=>{
    console.log(_d1.data)
	return axios.get(_api_2)	
}) 
.then(_d2=>{
    console.log(_d2.data)
	return axios.get(_api_3)	
}).then(_d3=>{
 	console.log(_d3.data)
})

08.Generator生成器

Generator生成器与普通函数相比具有2个特征:

08.1.function与函数名之间有一个*。

当在调用生成器时,它不允许使用new关键字,也不会立即执行,而是返回一个Iterator对象,允许通过遍历器、for…of、解构语法等表达式执行。
每一个 yield 表达式,会使 Generator 生成一种新的状态,并转交控制权给外部函数,此时我们需要调用遍历器对象的next方法,才能使 Generator 继续执行。需要注意的是,Generator函数内部如果不存在yield表达式,它也不会立即执行,而是需要手动使用next方法触发:
function* test() { console.log(‘hello’) }
const fn = test(); // 没有任何输出
fn.next(); // hello
复制代码Generator函数结束的标志为 return,return 返回的值也会作为next方法返回对象的value,而此时 done 属性为:true(如果函数体内无 return 关键字,则会执行到函数结束,默认返回值为undefined)。

08.2.函数内部使用yield表达式。

yield表达式
yield表达式用于定义Generator不同的内部状态,它同时作为函数暂停的标志,将执行权交给外部的其他函数,并将 yield 关键字紧邻的表达式作为接下来遍历器的next()方法返回的对象的value键值。外部函数在调用了next()方法以后,Generator才得以恢复执行:
function* test() {
yield ‘hello’
yield ‘world’
return ‘!’
}

const executer = test();
executer.next(); // {value: “hello”, done: false}
executer.next(); // {value: “world”, done: false}
executer.next(); // {value: “!”, done: true}

for (item of test()) { console.log(item) } // hello world

09.模块概念

09.1.导出模块

// export1.js

// 导出变量
export let name = 'jack';

// 导出函数
export function print() {
    console.log("function");
}

// 导出类
export class Person {
    constructor(name) {
        this.name = name;
    }
}
// 私有函数
function privateFunction () {
    console.log('我是私有函数,外部访问不了我');
}

// export2.js

// 导出变量
let name = 'jack'// 导出函数
function print() {
    return 'function';
}

// 导出类
class Person {
    constructor(name) {
        this.name = name;
    }
}

// 私有函数
function privateFunction () {
    return '我是私有函数,外部访问不了我';
}

export { name, print, Person }

09.2.导入模块

// import1.js
import { name, print, Person } from './export1.js';

console.log(name); //jack

console.log(print()); // function

// 报错, 不能定义相同名字变量
let name = 2333; 

// 报错,不能重新赋值
name = "小猪";

10.Symbol类型

ES6引入了Symbol数据类型很好的解决了对象属性名冲突的问题。
唯一性
例1

// bad
// 1. 创建的属性会被 for-in 或 Object.keys() 枚举出来
// 2. 一些库可能在将来会使用同样的方式,这会与你的代码发生冲突
if (element.isMoving) {
  smoothAnimations(element);
}
element.isMoving = true;

// good
if (element.__$jorendorff_animation_library$PLEASE_DO_NOT_USE_THIS_PROPERTY$isMoving__) {
  smoothAnimations(element);
}
element.__$jorendorff_animation_library$PLEASE_DO_NOT_USE_THIS_PROPERTY$isMoving__ = true;

// better

var isMoving = Symbol("isMoving");

...

if (element[isMoving]) {
  smoothAnimations(element);
}
element[isMoving] = true;

11.proxy

11.1Proxy 构造函数

在Es6 中 提供了原生的 Proxy 构造函数,可以用来生成 Proxy实例。
let p = {
name: ‘李四’
}

let proxy = new Proxy(p, {
get: function(target, property) {
if (property in target) {
retrun target[property]
} else {
console.log(‘报错’)
}
}
})

proxy.name // ‘李四’
proxy.age // ‘报错’

get方法可以继承
get方法可以进行链式操作

11.3. 使用 JavaScript Proxy 实现简单的数据绑定?

<body>
  hello,world
  <input type="text" id="model">
  <p id="word"></p>
</body>
<script>
  const model = document.getElementById("model")
  const word = document.getElementById("word")
  var obj= {};

  const newObj = new Proxy(obj, {
      get: function(target, key, receiver) {
        console.log(`getting ${key}!`);
        return Reflect.get(target, key, receiver);
      },
      set: function(target, key, value, receiver) {
        console.log('setting',target, key, value, receiver);
        if (key === "text") {
          model.value = value;
          word.innerHTML = value;
        }
        return Reflect.set(target, key, value, receiver);
      }
    });

  model.addEventListener("keyup",function(e){
    newObj.text = e.target.value
  })
</script>

11.2.this指向

虽然 Proxy 可以代理针对目标对象的访问,但它不是目标对象的透明代理,即不做任何拦截的情况下,也无法保证目标对象的行为一致。主要原因就是在Proxy代理的情况下,目标对象内部的this关键字会指向Proxy代理

*12.set与map的区别

12.1.数组去重:

[…new Set(array)]

12.2.条件语句的优化 (Map)

原来:

// 根据颜色找出对应的水果
// bad
function test(color) {
  switch (color) {
    case 'red':
      return ['apple', 'strawberry'];
    case 'yellow':
      return ['banana', 'pineapple'];
    case 'purple':
      return ['grape', 'plum'];
    default:
      return [];
  }
}
test('yellow'); // ['banana', 'pineapple']
现在
// good
const fruitColor = {
  red: ['apple', 'strawberry'],
  yellow: ['banana', 'pineapple'],
  purple: ['grape', 'plum']
};

function test(color) {
  return fruitColor[color] || [];
}
// better
const fruitColor = new Map()
  .set('red', ['apple', 'strawberry'])
  .set('yellow', ['banana', 'pineapple'])
  .set('purple', ['grape', 'plum']);

function test(color) {
  return fruitColor.get(color) || [];
}

或者
function tests(color){
	const myMap = new Map([
            ['red',['apple', 'strawberry']],
            ['yellow',['banana', 'pineapple']],
            ['purple',['grape', 'plum']],
		])
	return	myMap.get(color) ? myMap.get(color) :  [] ;
}

12.3.新的数据结构 Map

是 Es6 提供的一种新的数据结构,它类似于对象,也是键值对的集合,但是’键’的范围不限于字符串,各种类型的值(包括对象)都可以当作键,即 Map 提供了一种值 - 值的对应,是一种更完善的Hash结构实现
作为构造函数,Map 可以接受一个数组作为参数,该数组的成员是一个个表示键值对的数组
const map = new Map([[‘name’,‘张三’],[‘title’,‘Author’] ])
map.size // 2
map.has(‘name’) // true
map.get(‘name’) // ‘张三’
map.has(‘title’) // true
map.get(‘title’) // ‘Author’
总结Map实例的属性和方法 属性 Map.prototype.size - 返回Map实例的成员总数

12.4. 方法(操作方法 & 遍历方法)

* 操作方法
    * Map.prototype.set(key,value) - 设置键名Key对应的键值Value,然后返回整个Map结构,如果Key已经存在,则键值更新
    * Map.prototype.get(key) - 读取Key对应的键值,如果找不到则返回undefined
    * Map.prototype.has(key) - 返回一个布尔值,表示某个键是否在当前Map对象中存在
    * Map.prototype.delete(key) - 删除某个键,返回true,如果删除失败,则返回false
    * Map.prototype.clear() - 清除所有成员,没有返回值
* 遍历方法
    * Map.prototype.keys() - 返回键名的遍历器
    * Map.prototype.values() - 返回键值的遍历器
    * Map.prototype.entries() - 返回键值对的遍历器
    * Map.prototype.forEach() - 使用回调函数遍历每个成员

12.5…es6里面操作数组API 类似map和set map是干嘛用的 **

es6的对象结合,数组结合 ,找到序号是5的对象 Map.prototype.keys(5) - 返回键名的遍历器
map基本用法跟forEach方法类似
map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
map() 方法按照原始数组元素顺序依次处理元素。
    注意: map() 不会对空数组进行检测。
    注意: map()返回的是新数组,map() 不会改变原始数组。
语法:
    array.map(function(currentValue,index,arr), thisValue)
参数说明:
    function(currentValue, index,arr):
        必须。函数,数组中的每个元素都会执行这个函数
        函数参数:
            currentValue     必须。当前元素的值
            index             可选。当前元素的索引值
            arr             可选。当前元素属于的数组对象
    thisValue:
        可选。对象作为该执行回调时使用,传递给函数,用作 "this" 的值。
        如果省略了 thisValue,或者传入 null、undefined,那么回调函数的 this 为全局对象。
注意:
    function(currentValue, index,arr)回调函数必须要return返回值,不然会返回一个undefind的数组
实际使用的时候,可以利用map方法方便获得对象数组中的特定属性值们。

实例:

var users = [
{name: "熊大", "email": "zhang@email.com"},
{name: "熊二", "email": "jiang@email.com"},
{name: "光头强", "email": "li@email.com"}
];
// emails => email的数组
var emails = users.map(function (user) { return user.email; });

12.6.新的数据解构 Set

Es 6 提供了新的数据结构Set,它类似于数组,但是成员的值是唯一的,没有重复的值
Set()接受一个数组(或者具有iterable接口的其他数据结构)作为参数,用来初始化
const arr = new Set([1,2,3,4,4])
console.log([…set]) // Array(4) [1, 2, 3, 4] […xxx]转化为Array
const items = new Set([1,2,3,4,5,5,5,5])
console.log(items) // Set(5) {1, 2, 3, 4, 5}
总结Set实例的属性和方法

  • Set.prototype.constructor - 构造函数,默认就是Set函数 Set.prototype.size - 返回Set实例的成员总数

12.7.set 方法(操作方法 & 遍历方法)

* 操作方法
    * Set.prototype.add(value) - 添加某个值,返回Set结构本身
    * Set.prototype.delete(value) - 删除某个值,返回一个布尔值
    * Set.prototype.has(value) - 返回一个布尔值,表示该值是否为Set成员
    * Set.prototype.clear() - 清除所有成员,没有返回值
* 遍历方法
    * Set.prototype.keys() - 返回键名的遍历器
    * Set.prototype.values() - 返回键值的遍历器
    * Set.prototype.entries() - 返回键值对的遍历器
    * Set.prototype.forEach() - 使用回调函数遍历每个成员

*13.函数默认参数

13.1. 默认值

// 例子1

// bad
function test(quantity) {
  const q = quantity || 1;
}

// good
function test(quantity = 1) {
  ...
}

// 例子2

doSomething({ foo: 'Hello', bar: 'Hey!', baz: 42 });

// bad
function doSomething(config) {
  const foo = config.foo !== undefined ? config.foo : 'Hi';
  const bar = config.bar !== undefined ? config.bar : 'Yo!';
  const baz = config.baz !== undefined ? config.baz : 13;
}

// good
function doSomething({ foo = 'Hi', bar = 'Yo!', baz = 13 }) {
  ...
}

// better
function doSomething({ foo = 'Hi', bar = 'Yo!', baz = 13 } = {}) {
  ...
}

//例子3

// bad
const Button = ({className}) => {
	const classname = className || 'default-size';
	return <span className={classname}></span>
};
// good
const Button = ({className = 'default-size'}) => (
	<span className={classname}></span>
);
// better
const Button = ({className}) =>
	<span className={className}></span>
}
Button.defaultProps = {
	className: 'default-size'
}

// 例子4

const required = () => {throw new Error('Missing parameter')};

const add = (a = required(), b = required()) => a + b;

add(1, 2) // 3
add(1); // Error: Missing parameter.

*14 拓展运算符

14.1 . arguments 转数组

// 例1

// bad
function sortNumbers() {
  return Array.prototype.slice.call(arguments).sort();
}

// good
const sortNumbers = (...numbers) => numbers.sort();

14.2. 调用参数

// 例2

// bad
Math.max.apply(null, [14, 3, 77])

// good
Math.max(...[14, 3, 77])
// 等同于
Math.max(14, 3, 77);

14.3.构建对象

   14.3.1.剔除部分属性,将剩下的属性构建一个新的对象

// 例子 3

let [a, b, ...arr] = [1, 2, 3, 4, 5];

const { a, b, ...others } = { a: 1, b: 2, c: 3, d: 4, e: 5 };
  14.3.2.有条件的构建对象

// 例子 4

// bad
function pick(data) {
  const { id, name, age} = data

  const res = { guid: id }

  if (name) {
    res.name = name
  }
  else if (age) {
    res.age = age
  }

  return res
}

// good
function pick({id, name, age}) {
  return {
    guid: id,
    ...(name && {name}),
    ...(age && {age})
  }
}
   14.3.3.合并对象
let obj1 = { a: 1, b: 2,c: 3 }
let obj2 = { b: 4, c: 5, d: 6}
let merged = {...obj1, ...obj2};

14.4.将对象全部传入组件(jsx)

  ````c
 const parmas =  {value1: 1, value2: 2, value3: 3}

  <Test {...parmas} />
  ```

14.5.双冒号运算符

// 例子 1

foo::bar;
// 等同于
bar.bind(foo);

foo::bar(...arguments);
// 等同于
bar.apply(foo, arguments);

15.数组的拓展方法

15.1. keys

//例 1

var arr = ["a", , "c"];

var sparseKeys = Object.keys(arr);
console.log(sparseKeys); // ['0', '2']

var denseKeys = [...arr.keys()];
console.log(denseKeys);  // [0, 1, 2]

15.2.entries

// 例子 2

var arr = ["a", "b", "c"];
var iterator = arr.entries();

for (let e of iterator) {
    console.log(e);
}

15.3. values

// 例子 16-3

let arr = ['w', 'y', 'k', 'o', 'p'];
let eArr = arr.values();

for (let letter of eArr) {
  console.log(letter);
}

15.4. includes

// 例子 16-4

// bad
function test(fruit) {
  if (fruit == 'apple' || fruit == 'strawberry') {
    console.log('red');
  }
}

// good
function test(fruit) {
  const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
  if (redFruits.includes(fruit)) {
    console.log('red');
  }
}

15.5 find

// 例子 16-5

var inventory = [
    {name: 'apples', quantity: 2},
    {name: 'bananas', quantity: 0},
    {name: 'cherries', quantity: 5}
];

function findCherries(fruit) {
    return fruit.name === 'cherries';
}

console.log(inventory.find(findCherries)); // { name: 'cherries', quantity: 5 }

15.6 findIndex

// 例子 16-6

function isPrime(element, index, array) {
  var start = 2;
  while (start <= Math.sqrt(element)) {
    if (element % start++ < 1) {
      return false;
    }
  }
  return element > 1;
}

console.log([4, 6, 8, 12].findIndex(isPrime)); // -1, not found
console.log([4, 6, 7, 12].findIndex(isPrime)); // 2

*16.for—of

16.1. 遍历范围

for…of 循环可以使用的范围包括:

数组
Set
Map
类数组对象,如 arguments 对象、DOM NodeList 对象
Generator 对象
字符串

16.2. 优势

ES2015 引入了 for…of 循环,它结合了 forEach 的简洁性和中断循环的能力:
// 例子 6-1

for (const v of ['a', 'b', 'c']) {
  console.log(v);
}
// a b c

for (const [i, v] of ['a', 'b', 'c'].entries()) {
  console.log(i, v);
}
// 0 "a"
// 1 "b"
// 2 "c"
```
### 16.3. 遍历 Map
// 例子 6-2
```c
let map = new Map(arr);

// 遍历 key 值
for (let key of map.keys()) {
  console.log(key);
}

// 遍历 value 值
for (let value of map.values()) {
  console.log(value);
}

// 遍历 key 和 value 值(一)
for (let item of map.entries()) {
  console.log(item[0], item[1]);
}

// 遍历 key 和 value 值(二)
for (let [key, value] of data) {
  console.log(key)
}
### 16.4遍历 flatMap 二维数组转一维数组
[1,[2],3].flatMap(v=>v)

16.4 for-each for-in for-of

for in 与 for of 的区别

  • for in
  • 遍历对象及其原型链上可枚举的属性
  • 如果用于遍历数组,除了遍历其元素外,还会遍历数组对象自定义的可枚举属性及其原型链上的可枚举属性
  • 遍历对象返回的属性名和遍历数组返回的索引都是字符串索引
  • 某些情况下,可能按随机顺序遍历数组元素
  • for of
  • es6 中添加的循环遍历语法
  • 支持遍历数组,类数组对象(DOM NodeList),字符串,Map 对象,Set 对象
  • 不支持遍历普通对象
  • 遍历后输出的结果为数组元素的值
  • 可搭配实例方法 entries(),同时输出数组的内容和索引
    forEach()
    对数组每一项运行函数,没有返回值 (forEach无法中途跳出forEach循环,break、continue和return都不奏效。)

*17.Async +Await

async 是“异步”的简写,async 用于申明一个 function 是异步的,
async 是“异步”的简写,async 用于申明一个 function 是异步的, 而 await 用于等待一个异步方法执行完成,await 只能出现在 async 函数中
 async await和generator的写法很像,就是将 Generator 函数的星号(*)替换成 async,将 yield 替换成await
  但async 函数对 Generator 函数做了改进:

17.1、内置执行器:Generator函数的执行必须靠执行器,所以才有了 co 函数库,而 async 函数自带执行器.也就是说,async 函数的执行,与普通函数一模一样。
17.2、更好的语义:async 和 await,比起星号和 yield,语义更清楚了。async 表示函数里有异步操作,await 表示紧跟在后面的表达式需要等待结果。
17.3、更广的适用性: co 函数库约定,yield 命令后面只能是 Thunk 函数或 Promise 对象,而 async 函数的 await 命令后面,可以跟 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时等同于同步操作)
async 函数是非常新的语法功能,新到都不属于 ES6,而是属于 ES7。目前,它仍处于提案阶段,但是转码器 Babel 和 regenerator 都已经支持,转码后就能使用。
async 的作用
17.4. async 函数负责返回一个 Promise 对象
如果在async函数中 return 一个直接量,async 会把这个直接量通过Promise.resolve() 封装成 Promise 对象;
如果 async 函数没有返回值,它会返回 Promise.resolve(undefined)
await 在等待什么
一般我们都用await去等带一个async函数完成,不过按语法说明,await 等待的是一个表达式,这个表达式的计算结果是 Promise 对象或者其它值,所以,await后面实际可以接收普通函数调用或者直接量
如果await等到的不是一个promise对象,那跟着的表达式的运算结果就是它等到的东西;
如果是一个promise对象,await会阻塞后面的代码,等promise对象resolve,得到resolve的值作为await表达式的运算结果
虽然await阻塞了,但await在async中,async不会阻塞,它内部所有的阻塞都被封装在一个promise对象中异步执行
Async Await使用场景
如上面的例子,当需要用到promise链式调用的时候,就体现出Async Await的优势;
假设一个业务需要分步完成,每个步骤都是异步的,而且依赖上一步的执行结果,甚至依赖之前每一步的结果,就可以使用Async Await来完成

    function takeLongTime(n) {
         return new Promise(resolve => {
         setTimeout(() => resolve(n + 200), n);
    });
     }
     function step1(n) {
          console.log(`step1 with ${n}`);
          return takeLongTime(n);
    }
    function step2(m, n) {
          console.log(`step2 with ${m} and ${n}`);
          return takeLongTime(m + n);
    }
    function step3(k, m, n) {
          console.log(`step3 with ${k}, ${m} and ${n}`);
          return takeLongTime(k + m + n);
    }
    async function doIt() {
          console.time("doIt");
          const time1 = 300;
          const time2 = await step1(time1);
          const time3 = await step2(time1, time2);
          const result = await step3(time1, time2, time3);
          console.log(`result is ${result}`);
          console.timeEnd("doIt");
    }
    doIt();
```c
  17.5.代码更简洁 
  //例1
  ```c
  // good  
    function fetch() {
      return (
        fetchData()
        .then(() => {
          return "done"
        });
      )
    }

    // better
    async function fetch() {
      await fetchData()
      return "done"
    };
 //例2
      // good
      function fetch() {
        return fetchData()
        .then(data => {
          if (data.moreData) {
              return fetchAnotherData(data)
              .then(moreData => {
                return moreData
              })
          } else {
            return data
          }
        });
      }

      // better
      async function fetch() {
        const data = await fetchData()
        if (data.moreData) {
          const moreData = await fetchAnotherData(data);
          return moreData
        } else {
          return data
        }
      };
  // 例3
 // good
      function fetch() {
        return (
          fetchData()
          .then(value1 => {
            return fetchMoreData(value1)
          })
          .then(value2 => {
            return fetchMoreData2(value2)
          })
        )
      }

      // better
      async function fetch() {
        const value1 = await fetchData()
        const value2 = await fetchMoreData(value1)
        return fetchMoreData2(value2)
      };
17.6.async 地狱
  // 例子
      // bad
      (async () => {
        const getList = await getList();
        const getAnotherList = await getAnotherList();
      })();

      // good
      (async () => {
        const listPromise = getList();
        const anotherListPromise = getAnotherList();
        await listPromise;
        await anotherListPromise;
      })();

      // good
      (async () => {
        Promise.all([getList(), getAnotherList()]).then(...);
      })();
  17.7.错误处理
  // 例子 
      // good
      function fetch() {
        try {
          fetchData()
            .then(result => {
              const data = JSON.parse(result)
            })
            .catch((err) => {
              console.log(err)
            })
        } catch (err) {
          console.log(err)
        }
      }

      // better
          async function fetch() {
        try {
          const data = JSON.parse(await fetchData())
        } catch (err) {
          console.log(err)
        }
      };

17.8.1.async函数返回的是一个Promise对象

function fn1(){ return new Promise(resolve=>{ 
setTimeout(function(){ 
 msg='wait me 3000'; 
 resolve(msg) },3000); }); }
 async function asyncCall(){ var result=await fn1(); console.log(result); } 
asyncCall();

17.9怎么把异步执行操作变成同步执行**

async/await的作用就是使异步操作以同步的方式去执行

*18.Decorator装饰器

// 例子1

class Math {
@log
add(a, b) {
return a + b;
}
}
// 例子 2

class Toggle extends React.Component {
  @autobind
  handleClick() {
    console.log(this)
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        button
      </button>
    );
  }
}

总结:

reduce可以操作字符串,数组,第二个参数可以是数字0就是从0开始加法运算,第二个参数是[],就是数组的去重之类的操作,是对象{}就是对象的合并等方法

map,filter,some 操作数组

map对象可以替代switch case

数组去重可以用reduce,set

1.ECMAScript 6 / ECMAScript 2015 新增了哪些新特性?

类Class
模板字符串
箭头函数
字面量
对象解构赋值
Promise
Generator生成器
模块概念
Symbol类型
Proxy代理
Set & Map
函数默认参数
rest与展开运算符…
块级作用域

2.箭头函数注意什么东西

函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象
不可以当作构造函数,也就是说,不可以使用new关键字,否则抛出错误
不可以使用arguments对象,该对象在函数体内不存在(可用rest参数代替)
不可以使用yield命令,因此箭头函数不能用作Generator函数

3.set与map的区别

新的数据结构 Map
是 Es6 提供的一种新的数据结构,它类似于对象,也是键值对的集合,但是’键’的范围不限于字符串,各种类型的值(包括对象)都可以当作键,即 Map 提供了一种值 - 值的对应,是一种更完善的Hash结构实现
作为构造函数,Map 可以接受一个数组作为参数,该数组的成员是一个个表示键值对的数组
const map = new Map([[‘name’,‘张三’],[‘title’,‘Author’] ])
map.size // 2
map.has(‘name’) // true
map.get(‘name’) // ‘张三’
map.has(‘title’) // true
map.get(‘title’) // ‘Author’

总结Map实例的属性和方法 属性 Map.prototype.size - 返回Map实例的成员总数
方法(操作方法 & 遍历方法)
操作方法
Map.prototype.set(key,value) - 设置键名Key对应的键值Value,然后返回整个Map结构,如果Key已经存在,则键值更新
Map.prototype.get(key) - 读取Key对应的键值,如果找不到则返回undefined
Map.prototype.has(key) - 返回一个布尔值,表示某个键是否在当前Map对象中存在
Map.prototype.delete(key) - 删除某个键,返回true,如果删除失败,则返回false
Map.prototype.clear() - 清除所有成员,没有返回值
遍历方法
Map.prototype.keys() - 返回键名的遍历器
Map.prototype.values() - 返回键值的遍历器
Map.prototype.entries() - 返回键值对的遍历器
Map.prototype.forEach() - 使用回调函数遍历每个成员
新的数据解构 Set Es 6 提供了新的数据结构Set,它类似于数组,但是成员的值是唯一的,没有重复的值
Set()接受一个数组(或者具有iterable接口的其他数据结构)作为参数,用来初始化
const arr = new Set([1,2,3,4,4])
console.log([…set]) // Array(4) [1, 2, 3, 4] […xxx]转化为Array
const items = new Set([1,2,3,4,5,5,5,5])
console.log(items) // Set(5) {1, 2, 3, 4, 5}
总结Set实例的属性和方法
Set.prototype.constructor - 构造函数,默认就是Set函数 Set.prototype.size - 返回Set实例的成员总数
方法(操作方法 & 遍历方法)
操作方法
Set.prototype.add(value) - 添加某个值,返回Set结构本身
Set.prototype.delete(value) - 删除某个值,返回一个布尔值
Set.prototype.has(value) - 返回一个布尔值,表示该值是否为Set成员
Set.prototype.clear() - 清除所有成员,没有返回值
遍历方法
Set.prototype.keys() - 返回键名的遍历器
Set.prototype.values() - 返回键值的遍历器
Set.prototype.entries() - 返回键值对的遍历器
Set.prototype.forEach() - 使用回调函数遍历每个成员

4.Promise有几种状态

5.这几种状态的关系

Promise对象有以下特点
对象的状态不受外界影响,Promise对象代表一个异步操作,具有三种状态:pending(进行中)、fulfilled(已成功)、rejected(已失败)。只有异步操作的结果可以决定当前是哪一种状态,任何其他操作都无法改变这个状态
一旦状态改变,就不会再次改变
任何时候都可以得到结果
(Promise对象的状态改变,只有两种可能 1.从pending变为fulfilled 2.从pending变为rejected
只要这两种情况发生,状态就凝固了(不会再变化),会一直保持这个结果,这时就称为resolved(已定型),如果改变已经发生,再对Promise对象添加回调函数,也会立即得到这个结果

6.catch与reject的区别

reject - 返回一个新的 Promise 实例,该实例的状态为rejected
catch - 用于指定发生错误时的回调函数

7.for-each for-in for-of

for in 与 for of 的区别
for in

  • 遍历对象及其原型链上可枚举的属性

  • 如果用于遍历数组,除了遍历其元素外,还会遍历数组对象自定义的可枚举属性及其原型链上的可枚举属性

  • 遍历对象返回的属性名和遍历数组返回的索引都是字符串索引

  • 某些情况下,可能按随机顺序遍历数组元素

for of

  • es6 中添加的循环遍历语法

  • 支持遍历数组,类数组对象(DOM NodeList),字符串,Map 对象,Set 对象

  • 不支持遍历普通对象

  • 遍历后输出的结果为数组元素的值

  • 可搭配实例方法 entries(),同时输出数组的内容和索引
    forEach()

对数组每一项运行函数,没有返回值 (forEach无法中途跳出forEach循环,break、continue和return都不奏效。)

8.Async +Await

async 是“异步”的简写,async 用于申明一个 function 是异步的,而 await 用于等待一个异步方法执行完成,await 只能出现在 async 函数中
async的内部阻塞 都在Promise对象中异步执行了,直接返回的就是promise对象 await会等promise对象resolve
.then已经被添加到链式回调
async await和generator的写法很像,就是将 Generator 函数的星号(*)替换成 async,将 yield 替换成await
但async 函数对 Generator 函数做了改进:
1、内置执行器:Generator函数的执行必须靠执行器,所以才有了 co 函数库,而 async 函数自带执行器.也就是说,async 函数的执行,与普通函数一模一样。
2、更好的语义:async 和 await,比起星号和 yield,语义更清楚了。async 表示函数里有异步操作,await 表示紧跟在后面的表达式需要等待结果。
3、更广的适用性: co 函数库约定,yield 命令后面只能是 Thunk 函数或 Promise 对象,而 async 函数的 await 命令后面,可以跟 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时等同于同步操作)
async 函数是非常新的语法功能,新到都不属于 ES6,而是属于 ES7。目前,它仍处于提案阶段,但是转码器 Babel 和 regenerator 都已经支持,转码后就能使用。
async 的作用
async 函数负责返回一个 Promise 对象
如果在async函数中 return 一个直接量,async 会把这个直接量通过Promise.resolve() 封装成 Promise 对象;
如果 async 函数没有返回值,它会返回 Promise.resolve(undefined)
await 在等待什么
一般我们都用await去等带一个async函数完成,不过按语法说明,await 等待的是一个表达式,这个表达式的计算结果是 Promise 对象或者其它值,所以,await后面实际可以接收普通函数调用或者直接量
如果await等到的不是一个promise对象,那跟着的表达式的运算结果就是它等到的东西;
如果是一个promise对象,await会阻塞后面的代码,等promise对象resolve,得到resolve的值作为await表达式的运算结果
虽然await阻塞了,但await在async中,async不会阻塞,它内部所有的阻塞都被封装在一个promise对象中异步执行
Async Await使用场景
如上面的例子,当需要用到promise链式调用的时候,就体现出Async Await的优势;
假设一个业务需要分步完成,每个步骤都是异步的,而且依赖上一步的执行结果,甚至依赖之前每一步的结果,就可以使用Async Await来完成
function takeLongTime(n) {
return new Promise(resolve => {
setTimeout(() => resolve(n + 200), n);
});
}
function step1(n) {
console.log(step1 with ${n});
return takeLongTime(n);
}
function step2(m, n) {
console.log(step2 with ${m} and ${n});
return takeLongTime(m + n);
}
function step3(k, m, n) {
console.log(step3 with ${k}, ${m} and ${n});
return takeLongTime(k + m + n);
}

async function doIt() {
console.time(“doIt”);
const time1 = 300;
const time2 = await step1(time1);
const time3 = await step2(time1, time2);
const result = await step3(time1, time2, time3);
console.log(result is ${result});
console.timeEnd(“doIt”);
}

doIt();

9.怎么把异步执行操作变成同步执行

https://juejin.im/post/6844903984889593863
async/await的作用就是使异步操作以同步的方式去执行
1.async函数返回的是一个Promise对象
function fn1(){ return new Promise(resolve=>{ setTimeout(function(){ msg=‘wait me 3000’; resolve(msg) },3000); }); } async function asyncCall(){ var result=await fn1(); console.log(result); } asyncCall();
10.rem计算单位的原理
rem是相对于根元素html的font-size进行计算的
浏览器给的字体大小是16px,按照转化关系16px = 1rem
使用rem布局的时候,为了兼容不同的分辨率,我们应该要动态的修正根字体的大小,让所有的用rem单位的子元素跟着一起缩放,从而达到自适应的效果。


19.es6里面操作数组API 类似map和set map是干嘛用的 es6的对象结合,数组结合 ,找到序号是5的对象 Map.prototype.keys(5) - 返回键名的遍历器

map基本用法跟forEach方法类似
map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
map() 方法按照原始数组元素顺序依次处理元素。
注意: map() 不会对空数组进行检测。
注意: map()返回的是新数组,map() 不会改变原始数组。
语法:
array.map(function(currentValue,index,arr), thisValue)
参数说明:
function(currentValue, index,arr):
必须。函数,数组中的每个元素都会执行这个函数
函数参数:
currentValue 必须。当前元素的值
index 可选。当前元素的索引值
arr 可选。当前元素属于的数组对象
thisValue:
可选。对象作为该执行回调时使用,传递给函数,用作 “this” 的值。
如果省略了 thisValue,或者传入 null、undefined,那么回调函数的 this 为全局对象。
注意:
function(currentValue, index,arr)回调函数必须要return返回值,不然会返回一个undefind的数组
实际使用的时候,可以利用map方法方便获得对象数组中的特定属性值们。
实例:
var users = [
{name: “熊大”, “email”: “zhang@email.com”},
{name: “熊二”, “email”: “jiang@email.com”},
{name: “光头强”, “email”: “li@email.com”}
];
// emails => email的数组
var emails = users.map(function (user) { return user.email; });

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值