ES6,ES7,ES8,ES9常用特性总结

ES6(ES2015)

1. 变量 let 和常量 const

  • var 的问题

    • 可以重复声明,没有报错和警告
    • 无法限制修改
    • 没有块级作用域, { }
  • let 和 const

    • 不能重复声明
    • 都是块级作用域, { } 块内声明的,块外无效
    • let 是变量,可以修改
    • const 是常量,不能修改
  • 块级作用域举例

    • 原来用 var 的方式,结果弹出的都是 3
    • 或者将变量 封装到函数里,限制作用域,但比较麻烦
    • 用 let 最简单,直接 var 改 let,解决作用域问题
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script>
        window.onload= function () {
            /*
            var aBtn = document.getElementsByTagName('input')
            for (var i=0; i < aBtn.length; i++) {
                aBtn[i].onclick = function () {
                    alert(i)
                }
            }*/
            var aBtn = document.getElementsByTagName('input')
            for (let i = 0; i < aBtn.length; i++) {
                aBtn[i].onclick = function () {
                    alert(i)
                }
            }
            /*
            var aBtn = document.getElementsByTagName('input')
            for (var i = 0; i < aBtn.length; i++) {
                // 封装到函数里,限制作用域
                (function (i) {
                    aBtn[i].onclick = function () {
                        alert(i)
                    }
                })(i)
            }*/
        }
    </script>
</head>
<body>
    <input type="button" value="按钮1">
    <input type="button" value="按钮2">
    <input type="button" value="按钮3">
</body>
</html>

2. 箭头函数

引入箭头函数有两个方面的作用:简化函数和不需要绑定 this

x => x * x
上面的箭头函数相当于:

function (x) {
    return x * x;
}

箭头函数相当于匿名函数,并且简化了函数定义。箭头函数有两种格式,一种像上面的,只包含一个表达式,连{ ... }return都省略掉了。还有一种可以包含多条语句,这时候就不能省略{ ... }return

x => {
    if (x > 0) {
        return x * x;
    }
    else {
        return - x * x;
    }
}

如果参数不是一个,就需要用括号()括起来:

// 两个参数:
(x, y) => x * x + y * y

// 无参数:
() => 3.14

// 可变参数:
(x, y, ...rest) => {
    var i, sum = x + y;
    for (i=0; i<rest.length; i++) {
        sum += rest[i];
    }
    return sum;
}

如果要返回一个对象,就要注意,如果是单表达式,这么写的话会报错:

// SyntaxError:
x => { foo: x }
因为和函数体的{ ... }有语法冲突,所以要改为:

// ok:
x => ({ foo: x })

箭头函数看上去是匿名函数的一种简写,但实际上,箭头函数和匿名函数有个明显的区别:箭头函数内部的this是词法作用域,由上下文确定。

回顾前面的例子,由于JavaScript函数对this绑定的错误处理,下面的例子无法得到预期结果:

var obj = {
    birth: 1990,
    getAge: function () {
        var b = this.birth; // 1990
        var fn = function () {
            return new Date().getFullYear() - this.birth; // this指向window或undefined
        };
        return fn();
    }
};

现在,箭头函数完全修复了this的指向,this总是指向词法作用域,也就是外层调用者obj

var obj = {
    birth: 1990,
    getAge: function () {
        var b = this.birth; // 1990
        var fn = () => new Date().getFullYear() - this.birth; // this指向obj对象
        return fn();
    }
};
obj.getAge(); // 25

如果使用箭头函数,以前的那种hack写法:

var that = this;

就不再需要了。

由于this在箭头函数中已经按照词法作用域绑定了,所以,用call()或者apply()调用箭头函数时,无法对this进行绑定,即传入的第一个参数被忽略:

var obj = {
    birth: 1990,
    getAge: function (year) {
        var b = this.birth; // 1990
        var fn = (y) => y - this.birth; // this.birth仍是1990
        return fn.call({birth:2000}, year);
    }
};
obj.getAge(2015); // 25

3. ...扩展参数符

  • 参数扩展/展开 ...args
    • 收集剩余的参数,必须当到最后一个参数位置
    • 展开数组,简写,效果和直接把数组的内容写在这儿一样
  • 默认参数
function show(a, b, ...args) {
    console.log(a)        //  1
    console.log(b)       //  2
    console.log(args)      // [3,4,5]
}
show(1, 2, 3, 4, 5)

let arr1 = [1, 2, 3]
let arr2 = [4, 5, 6]
let arr3 = [...arr1, ...arr2]
console.log(arr3)        // [1,2,3,4,5,6]

function show2(a, b=5, c=8) {
    console.log(a, b, c)  // 88 12 8
}
show2(88, 12)

4. 解构赋值

解构赋值

  • 左右两个边结构必须一样
  • 右边必须是个东西
  • 声明和赋值赋值不能分开,必须在一句话里

数组:

let [a, b, c] = [1, 2, 3];
//等同于
let a = 1;
let b = 2;
let c = 3;

对象:

var {
  StyleSheet,
  Text,
  View
} = React;

等同于
var StyleSheet = React.StyleSheet;
var Text = React.Text;
var View = React.Text;

获取对象中的值:

const student = {
      name: 'bahg',
      age: 18,
      sex: 'girl'
    }
const {name, age, sex} = student
console.log(name); // bahg
console.log(age);  // 18
console.log(sex);  // girl

5. 新增四个方法 map、reduce、filter、forEach

(1)map映射 (一对一,返回新数组)

let arr = [12, 5, 8]
let result1 = arr.map(item=>item*2) // 简写
console.log(result1)  // [ 24, 10, 16 ]

let score = [18, 86, 88, 24]
let result2 = score.map(item => item >= 60 ? '及格' : '不及格')
console.log(result2)  // [ '不及格', '及格', '及格', '不及格' ]

var users = [
  {name: "张XX",  "email": "[email protected]"},
  {name: "江XX",  "email": "[email protected]"},
  {name: "李XX",  "email": "[email protected]"}
];
var emails = users.map(function (user) { return user.email; });
console.log(emails.join(","));  // [email protected], [email protected], [email protected]

(2)reduce 汇总(多变一,返回新数组)

arr.reduce(function(prev,cur,index,arr){
   ...
}, init);
  • prev    表示上一次调用回调时的返回值,或者初始值 init;
  • cur      表示当前正在处理的数组元素;
  • index  表示当前正在处理的数组元素的索引,若提供 init 值,则索引为0,否则索引为1;
  • arr       表示原数组;
  • init      表示初始值

其实必需以及常用的参数只有两个:prev 和 cur。接下来我们跟着实例来看看具体用法吧~

请参考 https://www.cnblogs.com/cckui/p/9267542.htmlhttps://www.cnblogs.com/amujoe/p/11376940.html

(3)filter 过滤器(保留为true的,返回新数组)

var arr = [12, 4, 8, 9]
var result = arr.filter(item => (item % 3 === 0) ? true : false)
console.log(result)  // Array(2)
var result = arr.filter(item => item % 3 === 0)
console.log(result)  // Array(2)

var arr = [
    { title: '苹果', price: 10 },
    { title: '西瓜', price: 20 },
]
var result = arr.filter(json => json.price >= 20)
console.log(result)  // Array(1)

(4)forEach 循环迭代(用于遍历数组,无返回值)

var arr = [12, 4, 8, 9]
var result = arr.forEach(item => console.log(item))
var result = arr.forEach((item, index)=>console.log(item, index))

注意:除了reduce方法之外的其他三个方法,都传入了一个匿名函数作为参数,而该匿名函数实际含有三个参数(我们这里只写了一个)。其依次代表数组遍历时的当前元素item,数组遍历时的当前元素的索引index,以及正在遍历的数组array。有了这三个参数,可以方便我们做很多事情,比如说将每一项数组元素翻倍,这时需要用到第一个参数item。但是,仅仅只是将item乘以2可不行,我们还得将其赋值给原来的数组,这时我们就得用到后面两个参数index和array。根据上述可知,array[index]是全等于item的。

此外,这三个方法除了传递一个匿名函数作为参数之外,还可以传第二个参数,该参数用于指定匿名函数内的this指向,例如:

// 只传一个匿名函数
arr.forEach(function(item,index,array){
    console.log(this);  // window
});
// 传两个参数
arr.forEach(function(item,index,array){
    console.log(this);  // [1, -2, 3, 4, -5]
},arr);

6. 字符串

(1)模板字符串

  • 使用反引号,${变量}
  • 可以折行
 let a = 12
  let str1 = `asdf${a}`
  console.log(str1)  // asdf12

  let title = '标题'
  let content = '内容'
  let str = `<div>
    <h1>${title}</h1>
    <p>${content}</p>
</div>`
  console.log(str)  

<div>
  <h1>标题</h1>
  <p>内容</p>
</div>

(2)两个新方法

startWith   endsWith

var url = 'http://qq.com'
console.log(url.startsWith('http'))
console.log(url.endsWith('com'))
// 都是 true

7. 类

  • 原来写法
    • 类和构造函数一样
    • 属性和方法分开写的
// 老版本
function User(name, pass) {
    this.name = name
    this.pass = pass
}

User.prototype.showName = function () {
    console.log(this.name)
}
User.prototype.showPass = function () {
    console.log(this.pass)
}

var u1 = new User('able', '1233')
u1.showName()
u1.showPass()


// 老版本继承 function VipUser(name, pass, level) { User.call(this, name, pass) this.level = level } VipUser.prototype = new User() VipUser.prototype.constructor = VipUser VipUser.prototype.showLevel = function () { console.log(this.level) } var v1 = new VipUser('blue', '1234', 3) v1.showName() v1.showLevel()
  • 新版面向对象
    • 有了 class 关键字、构造器
    • class 里面直接加方法
    • 继承,super 超类==父类
class User {
    constructor(name, pass) {
        this.name = name
        this.pass = pass
    }

    showName() {
        console.log(this.name)
    }
    showPass() {
        console.log(this.pass)
    }
}

var u1 = new User('able2', '111')
u1.showName()
u1.showPass()

// 新版本继承
class VipUser extends User {
    constructor(name, pass, level) {
        super(name, pass)
        this.level = level
    }
    showLevel(){
        console.log(this.level)
    }
}

v1 = new VipUser('blue', '123', 3)
v1.showLevel()

8. 模块化

ES5 不支持原生的模块化,在ES6中模块作为重要的组成部分被添加进来。模块的功能主要由 export 和 import 组成。每一个模块都有自己单独的作用域,模块之间的相互提供的接口。同时还为模块创造了命名空间,防止函数的命名冲突。

导出(export)

ES6 允许在一个模块 export 来导出多个变量或函数。

 

猜你喜欢

转载自www.cnblogs.com/BAHG/p/12890211.html