es6新特性

es6新特性


ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布了。它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。


https://es6.ruanyifeng.com/

ECMAScript是JavaScript的一套标准

ES6(JavaScript语言的下一个版本)

ES6的第一个版本是在2015年6月发布的----ECMAScript2015(ES2015)

一、let 和 const 命令

let的特点

let关键字就是用来声明变量的
let声明的变量具有块级作用域
在一个大括号中,使用let声明的变量才具有块级作用域 var是不具有这个特点的

{
  let a = 10;
  var b = 1;
}
a // ReferenceError: a is not defined.
b // 1

防止循环变量变成全局变量

for (let i = 0; i < 10; i++) {
  // ...
}
console.log(i);
// ReferenceError: i is not defined
for (let i = 0; i < 3; i++) {
  let i = 'abc';
  console.log(i);
}
// abc
// abc
// abc

使用let声明的变量没有变量的提升

// var 的情况
console.log(foo); // 输出undefined
var foo = 2;
// let 的情况
console.log(bar); // 报错ReferenceError
let bar = 2;

使用let声明的变量具有暂时性死区的特性

var t = 134
if (true) {
   t = 'abc' //Cannot access 't' before initialization
   let t
}

不能重复声明

// 报错
function func() {
  let a = 10;
  var a = 1;
}
// 报错
function func() {
  let a = 10;
  let a = 1;
}
const的特点

声明一个只读的常量。一旦声明,常量的值就不能改变。

const PI = 3.1415;
PI // 3.1415
PI = 3;
// TypeError: Assignment to constant variable.

常量是不能重新进行赋值,如果是基本数据类型不能更改值,复杂数据类型 不能更改地址值

声明const的时候必须要给定值

let ,const,var的区别

var 声明的变量,其作用域为该语句所在的函数内,存在变量提升

let声明的变量,其作用域为该语句所在的代码块内,不存在变量提升

const声明的常量,在后面出现的代码中不能再修改该常量的值

二、变量的解构赋值

数组解构

ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。

以前,为变量赋值,只能直接指定值。

let a = 1;
let b = 2;
let c = 3;

ES6 允许写成下面这样。

let [a, b, c] = [1, 2, 3];

上面代码表示,可以从数组中提取值,按照对应位置,对变量赋值。

	  // var aa = 2
      // var bb = true
      // var cc = 'hello'
      // 从数组中提取值,按照位置,给变量赋值
      // // let [aa, bb, cc, dd] = [2, true, 'hello']
      // console.log(aa, bb, cc)
      // console.log(dd) //undefined

      // let [aa, bb, cc, dd] = [2, true, 'hello', 1, 34]
      // console.log(aa, bb, cc)

      // 嵌套数组进行解构
      // let [a, [b, c]] = [1, ['22', '33']]
      // console.log(a, b, c)

      // let [a, [[b], c]] = [1, [[2], 3]]
      // console.log(a, b, c) //1 2 3

      let [a] = []
      let [c, b] = [2]
      // 以上两种都属于解构不成功 a的值等于undefined   b的值为undefined

对象解构

解构不仅可以用于数组,还可以用于对象。

let { foo, bar } = { foo: 'aaa', bar: 'bbb' };
foo // "aaa"
bar // "bbb"

对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。

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

      // let obj = {
      //   name: 'ls',
      //   age: 23,
      //   sex: '男',
      //   score: 100,
      // }

      // // 变量名和对象的属性名要一一对象
      // let { name, sex, age, score, a } = obj
      // console.log(a) //undefined

      let obj = {
        name: 'ls',
        age: 23,
        sex: '男',
        score: 100,
        msg: {
          des: 'hello',
        },
      }

      let {
        name,
        age,
        sex,
        score,
        msg,
        msg: { des },
      } = obj

      console.log(des) //hello
      console.log(msg)

三、函数扩展

箭头函数

ES6 允许使用“箭头”(=>)定义函数。

var f = v => v;
// 等同于var f = function (v) 
        {  
            return v;
        };

如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分。

var f = () => 5;
// 等同于var f = function () 
    {
    	return 5 
    };
var sum = (num1, num2) => num1 + num2;
// 等同于var sum = function(num1, num2) 
    {
    	return num1 + num2;
    };
// --------------函数的代码块有多条语句
      // var fn = function (a, b) {
      //   console.log(a + b)
      //   return a + b
      // }

      // var fn = (a, b) => {
      //   console.log(a + b)
      //   return a + b
      // }

// ----------------代码块有一条语句 返回的是一个对象,对象要用括号括起来
      // var fn = function () {
      //   return { name: '张三', age: 23 }
      // }

      // var fn = () => ({ name: '张三', age: 23 })
      // console.log(fn())

      // ;[1, 2, 3].map(function (item) {
      //   return x * 2
      // })

      // ;[1, 2, 3].map((item) => item * 2)
      // var newArr = [1, 2, 3, 4]
      //   .filter((item) => item % 2 === 0)
      //   .map((x) => x * 2)

      // console.log(newArr)

函数参数默认值

es6之前,不能直接为函数的参数指定默认值

	  // function fn(a, b) {
      //   b = b || '123'
      //   console.log(a, b)
      // }
      // fn(1, 2)
      // fn(1)
      // es6允许为函数的参数设置默认值,直接写在参数定义的后面
      // function fn(a, b = '123') {
      //   console.log(a, b)
      // }
      // fn(1, 3)
      // fn(2)
      // fn(4, '')

      // 和解构赋值默认值结合使用
      // function fn({ x, y = 10 }) {
      //   console.log(x, y)
      // }
      // fn({}) //undefined 10
      // fn({ x: 12 }) //12 10
      // fn({ x: 12, y: 23 }) //12 23
      // fn() //annot destructure property 'x' of 'undefined' as it is undefined.

      // 默认值的位置
      function fn(x = 12, y) {
        console.log(x, y)
      }

      fn() //12 undefined
      fn(23) //23 undefined
      // fn(,23)  报错
      fn(undefined, 12) //12 12

四、数组扩展

扩展运算符

扩展运算符(spread)是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。

	  // var arr1 = [1, 2, 3]
      // console.log(...arr1) //1 2 3
      // var arr2 = [3, 4, 5]
      // var newArr = [...arr1, ...arr2]

      // arr1.push(...arr2)
      // console.log(arr1)
	  var o = {
        name: '张三',
        age: 12,
      }
      var obj = {
        ...o,
        sex: '男',
      }
      console.log(obj)
      
      // function show(a, b, c) {
      //   console.log(a, b, c)
      // }

      // let arr = [11, 22, 33]
      // show(...arr)

      // 不知道参数的个数
      function demo(...args) {
        console.log(args)
      }

      demo(1, 2, 3, 4, 5, 6, 7, 8)

Array.from

Array.from 把伪数组转换为真正的数组

// let arr = {
      //   0: 'hello',
      //   1: 123,
      //   2: true,
      //   length: 3,
      // }
      // let arr2 = Array.from(arr)
      // console.log(arr2) //['hello', 123, true]
      let pArr = document.querySelectorAll('p')
      let newArr = Array.from(pArr).filter((item) => {
        return item.textContent.length > 3
      })
      console.log(newArr)

五,字符串控制

模板字符串

  <body>
    <ul id="oul">
      <!-- <li>
        <p>姓名:张三</p>
        <p>年龄:12</p>
      </li> -->
    </ul>
    <script>
      function fn(age) {
        var s = age > 20 ? '青年' : '未成年'
        return s
      }
      var arr = [
        { id: 1, name: '张三', age: 12 },
        { id: 2, name: '李四', age: 22 },
        { id: 3, name: '王五', age: 33 },
        { id: 4, name: '赵六', age: 44 },
      ]
      let str = ''
      arr.forEach((item) => {
        // str +=
        // ' <li><p>姓名:' + item.name + '</p><p>年龄:' + item.age + '</p></li>'

        str += `
        <li>
          <p>姓名:${item.name}</p>
          <p>年龄:${item.age}</p>
          <p>${fn(item.age)}</p>
        </li>
        `
      })

      var oul = document.querySelector('#oul')
      oul.innerHTML = str
    </script>
  </body>

字符串的扩展

includes(字符串,start) 判断父串中是否包含子串的内容,返回布尔值
startsWith(字符串,start) 判断父串中是否以指定的子 串开头,返回布尔值
endsWith(字符串,start) 判断父串中是否以指定的子串结尾,返回布尔值
repeat() 重复指定的字符串,返回字符串

	  var str = 'how do you do'
      console.log(str.includes('do', 4)) //true
      console.log(str.startsWith('do', 4)) //true
      console.log(str.endsWith('do', 6)) //true

      var ch = 'o'
      console.log(ch.repeat(3)) //"ooo"
      console.log(ch.repeat(3.3)) //"ooo"
      // console.log(ch.repeat(-3)) //报错 Invalid count value
      console.log(ch.repeat(-0.3)) //""

Symbol

ES6新增了第7种基本数据类型Symbol

Symbol符号,象征,标记,记号,在js中独一无二的值

	  // symbol 是独一无二的
      const s = Symbol()
      const s1 = Symbol()
      // console.log(typeof s) //symbol
      // console.log(s === s1) //false

      // Symbol方法接收一个参数,表示对生成symbol值的一种描述

      // 传入相同的参数,生成的symbol的值也是不相等的
      const foo = Symbol('foo')
      const bar = Symbol('foo')
      console.log(foo === bar) //false

作为属性名的 Symbol

由于每一个 Symbol 值都是不相等的,这意味着 Symbol 值可以作为标识符,用于对象的属性名,就能保证不会出现同名的属性。这对于一个对象由多个模块构成的情况非常有用,能防止某一个键被不小心改写或覆盖。

let mySymbol = Symbol();

// 第一种写法
let a = {};
a[mySymbol] = 'Hello!';

// 第二种写法
let a = {
    [mySymbol]: 'Hello!'
};

// 第三种写法
let a = {};
Object.defineProperty(a, mySymbol, { value: 'Hello!' });

// 以上写法都得到同样结果a[mySymbol] // "Hello!"
 // [重点] 作为对象的属性 一个复杂的对象有多个属性的时候,很容易将某个属性名覆盖,利用symbol值作为属性名可以避免

      const name = Symbol('name')
      const obj = {
        // 对象以变量作为属性名  用到[]
        [name]: 'lucy',
      }

Set 和 Map 数据结构

Set

基本用法

ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。

Set本身是一个构造函数,用来生成 Set 数据结构。

set 无序 元素不可重复
array 有序 元素可重复

const s = new Set();
[2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x));
for (let i of s) {
  console.log(i);
}
// 2 3 5 4

set常用的方法
set.add(value) 添加元素到集合内
set.delete(value) 删除指定的元素
set.clear() 清空集合内元素
set.forEach(callback) 遍历集合内所有元素
set.has(value) 检查集合内是否有某个元素

	  let set = new Set('hello')
      // console.log(set)
      set.add(12) //add 给set结构添加成员
      console.log(set.has('h')) //true   判断set结构是否有某个成员
      console.log(set.size) // 获取长度

      set.delete(12) //删除指定的set结构成员
      console.log(...set)
      set.clear() //删除所有的成员
set的遍历

set集合没有键名 只有键值

	  let ss = new Set(['red', 'green', 'yellow', 'blue'])

      // for (let item of ss.keys()) {
      //   console.log(item)
      //   // red
      //   // green
      //   // yellow
      //   // blue
      // }

      // for (let item of ss.values()) {
      //   console.log(item)
      //   // red
      //   // green
      //   // yellow
      //   // blue
      // }

      // for (let item of ss.entries()) {
      //   console.log(item)
      //   // ['red', 'red']
      // }

      ss.forEach((item) => {
        console.log(item)
        // red
        // green
        // yellow
        // blue
      })
// 实现数组去重
      // let arr = new Set([3, 4, 5, 5, 2, 3, 2, 5]).values()
      let arr = Array.from(new Set([3, 4, 5, 5, 2, 3, 2, 5]))
        console.log(arr)  // [3, 4, 5, 2]

map

含义和基本用法

JavaScript 的对象(Object),本质上是键值对的集合(Hash 结构),但是传统上只能用字符串当作键。这给它的使用带来了很大的限制。

es6提供了map数据结构,类似于对象 属性名(键)的范围不限于字符串,各种类型的值都可以作为键

	  const o = {}
      const ele = document.querySelector('div')
      o[ele] = 'element' //ele 被自动转换为字符串
  	  const m = new Map()
      const oo = { name: 'hello world' }
      // 添加成员
      m.set(oo, 'content')
      console.log(m)
      // 获取
      console.log(m.get(oo)) //"content"
      // 判断是否有该键
      console.log(m.has(oo)) //true

      // 删除
      m.delete(oo)
      console.log(m.size) // 0

      // 一个key只能对应一个value  多次对一个key放入value  后面的值会把前面的值覆盖

      var map = new Map()
      map.set('a', '女')
      map.set('a', '男')
      console.log(map)

map和set的区别

1 具有极快的查找速度

	  // var arr = new Array()
      // var set = new Set()
      // var map = new Map()

      // for (var i = 0; i < 30; i++) {
      //   arr[i] = i
      //   set.add(i)
      //   map.set(i, arr[i])
      // }
      // console.log('---------------------------')

      // console.time()
      // for (var j = 0; j < 30; j++) {
      //   arr.includes(j)
      // }
      // console.timeEnd()

      // console.time()
      // for (var j = 0; j < 30; j++) {
      //   set.has(j)
      // }
      // console.timeEnd()
      // console.time()
      // for (var j = 0; j < 30; j++) {
      //   map.has(j)
      // }
      // console.timeEnd()

2 map需要的是一个二维数组 set需要的是一个一维数组
map 和set都不需要键重复

	  const map = new Map([
        ['name', '张三'],
        ['age', 12],
      ])

      const set = new Set([2, 3, 4, 5])

      // map是键值对  set没有value只有key

      // set去重
      let s = new Set([1, 2, 1, 4, 5, 2, 3, 1, 4])
      const arr = [...s]
      // console.log(arr) //[1, 2, 4, 5, 3]

      // map去重
      let arr1 = [1, 2, 1, 4, 5, 2, 3, 1, 4]
      const mm = new Map()
      let res = arr1.filter((item) => !mm.has(item) && mm.set(item, 1))
      console.log(res) //[1, 2, 4, 5, 3]

Proxy

Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程。

Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”

Proxy 实例的方法
get()

get方法用于拦截某个属性的读取操作,可以接受三个参数,依次为目标对象、属性名和 proxy 实例本身(严格地说,是操作行为所针对的对象),其中最后一个参数可选。

get方法的用法,上文已经有一个例子,下面是另一个拦截读取操作的例子。

var person = {
  name: "张三"
};
var proxy = new Proxy(person, {
  get: function(target, propKey) {
    if (propKey in target) {
      return target[propKey];
    } else {
      throw new ReferenceError("Prop name \"" + propKey + "\" does not exist.");
    }
  }
});
proxy.name // "张三"
proxy.age // 抛出一个错误

//上面代码表示,如果访问目标对象不存在的属性,会抛出一个错误。如果没有这个拦截函数,访问不存在的属性,只会返回undefined

set()

set方法用来拦截某个属性的赋值操作,可以接受四个参数,依次为目标对象、属性名、属性值和 Proxy 实例本身,其中最后一个参数可选。

假定Person对象有一个age属性,该属性应该是一个不大于 200 的整数,那么可以使用Proxy保证age的属性值符合要求。

let validator = {
  set: function(obj, prop, value) {
    if (prop === 'age') {
      if (!Number.isInteger(value)) {
        throw new TypeError('The age is not an integer');
      }
      if (value > 200) {
        throw new RangeError('The age seems invalid');
      }
    }
    // 对于满足条件的 age 属性以及其他属性,直接保存
    obj[prop] = value;
    return true;
  }
};
let person = new Proxy({}, validator);
person.age = 100;
person.age // 100
person.age = 'young' // 报错
person.age = 300 // 报错

Promise 对象

Promise对象有以下两个特点。

(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。

(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

下面代码创造了一个Promise实例。

const promise = new Promise(function(resolve, reject) {
  // ... some code
  if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});

Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。

promise.then(function(value) {
  // success
}, function(error) {
  // failure
});

then方法可以接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为resolved时调用,第二个回调函数是Promise对象的状态变为rejected时调用。这两个函数都是可选的,不一定要提供。它们都接受Promise对象传出的值作为参数。

下面是一个Promise对象的简单例子。

function timeout(ms) {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, ms, 'done');
  });
}
timeout(100).then((value) => {
  console.log(value);
});
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值