虽然现在还需要借助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
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。