1

虽然现在还需要借助babel的力量但未来一定是属于ES6。(那ES7?-_-|||)

let

在ES6之前javascript只有两种作用域,即全局作用域和函数作用域,let的出现弥补JS了没有块作用域的痛点

let的块作用域

function cat(){
    let mew = '喵'
    let angry = true
    console.log(mew)
    if(angry){
        let mew = '...'  //外层{}成为块作用域
        console.log(mew)
    }
    console.log(mew)
}
cat()
//喵
//...
//喵

让我们和var做一下对比

function cat(){
    var mew = '喵'
    var angry = true
    console.log(mew)
    if(angry){
        var mew = '...'  //外层 mew 被覆盖
        console.log(mew)
    }
    console.log(mew)
}
cat()
//喵
//...
//...
  • 而let由于产生了块作用域似的mew = '...' 只在块作用域内被使用,所以第三次输出mew是'喵'

  • 如上由于var不产生块作用域所以if语句中的var mew = '...'相当于覆盖了函数中第一个mew(即函数作用域中的)所以在次输出mew是'...'

应用

上述例子中,通过let的使用可以避免变量被不必要地覆盖
让我们再看一个栗子:

var a = []
for (var i = 0; i < 5; i++) {
  a[i] = function () {
    console.log(i)
  }
}
a[3]()  // 5

为了输出3,通常会使用闭包来处理

var a = []
for (var i = 0; i < 5; i++) {
  a[i] = (function(i){
      var j = i
      return function () {
          console.log(j)
      }
  })(i)
}
a[3]()  //3

这不仅使代码变得冗长了不少,而且的外层可以访问到i(说明i在使用完并未被清除,内存泄漏)

使用let声明只在块级作用域内有效

var a = []
for (let i = 0; i < 5; i++) {
  a[i] = function () {
    console.log(i)
  }
}
a[3]()  // 3

一些需要注意的点

暂时性死区

在var 声明前使用变量,会得到undefined

console.log(abc) //undefined
var abc

但在let 声明前使用变量,会报错

console.log(abc)  //错误
var abc

这是由于在let的作用域中,let申明之前会形成暂时性死区,在变量定义之前,使该变量都是不可用的。

重复声明

在块级作用域中重复声明会报错

{
var color = "black"
let color = "white"
}
//  报错
{
let color = "black"
var color = "white"
}
//  报错
{
let color = "black"
let color = "white"
}
//  报错

箭头函数

箭头函数的使用可以使书写更为简练

计算数组各项平方
let ary = [1,2,3,5]
let res = ary.map(function(item){return item*item}) //[1, 4, 9, 25]

使用箭头函数可以简化书写

let ary = [1,2,3,5]
let res = ary.map((item) => {return item*item}) //[1, 4, 9, 25]

更进一步可以省略括号(多个参数不能省略括号)

let ary = [1,2,3,5]
let res = ary.map(item => {return item*item}) //[1, 4, 9, 25]

函数可以进一步简化成:

let ary = [1,2,3,5]
let res = ary.map(item => item * item )  //[1, 4, 9, 25]

模板字符串

模版字符串是对字符串拼接的改进,以往输出带有变量的语句时,我们采用字符串拼接的方式,而模板字符串可以在字符串中直接使用变量,即简化书写同时也降低出错的风险

let name = 'Yoda'
console.log('My name is ' + name) //
console.log(`My name is ${name}`) //模板字符串
  • 模板字符串使用反引号 ( ) 来代替普通字符串中的用双引号和单引号;

  • 模板字符串使用包含特定语法(${expression})的占位符;

  • 模板字符串可以不需换行符直接使用换行:

let name = 'Yoda'
console.log(`My name is ${name}
what‘s your name`) 
// My name is Yoda
// what‘s your name
  • 可以直接显示计算结果

let a = 1
let b = 2
console.log(`${a} + ${b} = ${ a + b }) 
// 1 + 2 = 3

延展操作符

let cuboid  = [2,3,4]
let cuboidVolume = (a,b,c) => {console.log(a*b*c)}
cuboidVolume(cuboid[0], cuboid[1], cuboid[2])  //24
//延展操作符
cuboidVolume(...cuboid)
// 24
  • 延展操作符可以将数组拆分传作为参数入函数

  • 延展操作符可以用于数组拼接:

let fruit  = ['orange','apple','banana']
let meat = ['beef']
let breakfast = [...fruit, ...meat , 'bread']
// ["orange", "apple", "banana", "beef", "bread"]

Classes(类)与继承

总所周知,js的原型链继承向来以难以理解外加坑多著称
(构造函数,原型对象,实例对象它们之间剪不断理还乱的关系,如果再加上继承,prototype和[[prototype]]的指向@_@说多了都是泪啊)
由于JS中没有类的概念,许多初学者都掉坑原型链之中。
ES6将类引入了,大大简化了原先复杂的工作(从前要实现继承得多麻烦:工厂模式无法解决对象识别,构造函数模式内存浪费,原型模式私有方法还要结合构造模式...)

  • 定义

class Person {
    constructor(name,age){
        this.name = name
        this.age = age
    }
    say(){
        console.log(`Hello my name is ${this.name}`)
    }
}
//person 实例
let person = new Person('Yoda',2000)
person.name  //'Yoda'
person.say() //Hello my name is Yoda
  • 实现类的继承,我要用到extend:

class Programmer extends Person{
    constructor(name,age, language){
        super(name,age)
        this.language = language
    }
}
let javaProgrammer = new Programmer('Jack',22,'java')
javaProgrammer.language //'java'
  • 继承类可以重写父类的方法:

class Programmer extends Person{
    constructor(name,age, language){
        super(name,age)
        this.language = language
    }
    say(){
        console.log(`I am a programmer using ${this.language}`)
    }
}
let javaProgrammer = new Programmer('Jack',22,'java')
javaProgrammer.say() //I am a programmer using java

这是上帝的杰作
2.2k 声望164 粉丝

//loading...