es6的学习笔记
3.1 对象字面量
三个改进的地方:1.属性值缩写,可计算属性名称,方法定义
3.1.1 属性值缩写
当变量已经定义后,再定义对象的时候可以直接写变量名称,就会给该对象增加一个属性,属性名称为变量名,属性的值就是对应的变量的值
var store = {};
var s=[1,2,3,4];
var api={s,getItem,setItem,clear};
function getItem(key){
return key in store?store[key]:null;
}
function setItem(key,value){
store[key]=value;
}
function clear(){
store = {};
}
console.log(api.getItem);
console.log(api.setItem);
console.log(api.clear);
console.log(api.s);
3.1.2 可计算属性名
定义对象时,用方括号括住的属性名,最终的属性名应该是以该属性名命名的变量的值。不能和第一个特性结合使用
var expertise = 'journalism'
var person = {
name: 'Sharon',
age: 27,
[expertise]: {
years: 5,
interests: ['international', 'politics', 'internet']
}
}
console.log(person[expertise].interests);
3.1.3 方法定义
对象中的函数可以直接定义。不必通过function。setter和getter和以前的用法相同,别的函数可以直接采用函数名+参数+定义的形式定义对象的方法。
var s=4;
var person={
get fule(){
return s;
},
set fule(value){
s=value;
},
add(){
return s+1;
}
}
console.log(person.fule);//4
console.log(person.add());//5
person.fule=10;
console.log(person.fule);//10
3.2 箭头函数
var example = function (parameters) {
// function body
}
var example = (parameters) => {
// function body
}
箭头函数看起来和匿名函数很像,但是实际上有很大的区别:他们没有函数名,他们被绑定了词法范围。
3.2.1 词法范围
var timer={
second:0,
start(){
setInterval(()=>{
console.log(this);//object timer
this.second++;
},1000);
}
}
timer.start();
setTimeout(function(){console.log(timer.second)},3700);//3
var timer={
second:0,
start(){
setInterval(function(){
console.log(this);//window
this.second++;
},1000);
}
}
timer.start();
setTimeout(function(){console.log(timer.second)},3700);//0
var timer={
second:0,
start(){
var that=this;
setInterval(function(){
console.log(that);//window
that.second++;
},1000);
}
}
timer.start();
setTimeout(function(){console.log(timer.second)},3700);//3
通过使用箭头函数,可以保证调用对象的方法时this一直绑定在方法的词法范围内,也就是this一直指向对象(不太完善,大部分情况下)。而如果使用匿名函数,词法范围由使用该匿名函数的此法范围决定,一般是window
3.2.2 箭头函数的简写
var example = (parameters) => {
// function body
}
var double = value => {//只有一个参数
return value * 2
}
var double = (value) => value * 2
var double = value => value * 2
3.2.3 优点和使用场景
十分适合用在词法绑定的匿名函数上。
[1, 2, 3, 4]
.map(value => value * 2)
.filter(value => value > 2)
.forEach(value => console.log(value))
// <- 4
// <- 6
// <- 8
注意事项
当箭头函数的隐含返回值(没有用return)时,必须在对象外围加上()不然和函数的定义是一致的。
var objectFactory = () => ({ modular: 'es6' })
[1, 2, 3].map(value => { number: value })
// <- [undefined, undefined, undefined]
[1, 2, 3].map(value => { number: value, verified: true })
// <- SyntaxError
[1, 2, 3].map(value => ({ number: value, verified: true }))
/* <- [
{ number: 1, verified: true },
{ number: 2, verified: true },
{ number: 3, verified: true }]
*/
3.3 assign destructuring
最简单的特性,方便了把对象的属性值赋值给变量
3.3.1 解构对象
var pseudonym = character.pseudonym//es5
var {pseudonym} = character //es6
var alias = character.pseudonym//es5
var { pseudonym: alias } = character//es6
var person = { scientist: true }
var type = 'scientist'
var { [type]: value } = person //es6
console.log(value)
// <- true
value = person[type] //es5
3.3.2 解构数组
跟解构对象一样,只是采用方括号。毕竟操作的对象是数组
var left = 5
var right = 7
[left, right] = [right, left]
3.3.3 解构函数
function sumOf (a = 1, b = 2, c = 3) {
return a + b + c
}
console.log(sumOf(undefined, undefined, 4))
// <- 1 + 2 + 4 = 7
function carFactory ({ brand = 'Volkswagen', year = 1999 } = {}) {
console.log(brand)
console.log(year)
}
carFactory()
// <- 'Volkswagen'
// <- 1999
3.3.4 使用场景
function getCoordinates () {
return { x: 10, y: 22, z: -1, type: '3d' }
}
var { x, y } = getCoordinates()
function splitDate (date) {
var rdate = /(\d+).(\d+).(\d+)/
return rdate.exec(date)
}
var [, year, month, day] = splitDate('2015-11-06')
3.4 rest参数和扩散运算操作符
function print () {
var list = Array.prototype.slice.call(arguments)
console.log(list)
}
print('a', 'b', 'c')
// <- ['a', 'b', 'c']
在es5中,获取参数比较繁琐,在es6中,使用rest参数可以很好的获取函数的参数
3.4.1 rest 参数
function print (...list) {
console.log(list)
}
print('a', 'b', 'c')
// <- ['a', 'b', 'c']
function print (first, ...list) {
console.log(first)
console.log(list)
}
print('a', 'b', 'c')
// <- 'a'
// <- [b', 'c']
通过3个点来获取参数到list,…前面的参数可以按照原来的方式进行赋值,后面的多余参数会直接赋值给list
箭头函数必须加括号如果使用…参数,即便只有一个参数。否则会报错。
3.4.2 spread操作符
符号和…操作符一样,可以将数组或者类数组的元素返回到一个数组中。
var a=[1,2,3,...[2,3],...[3,4],5];
console.log(a);//1,2,3,2,3,3,4,5
3.5 模板字面量
可以使用``来定义字符串,这样在字符串内部使用单引号双引号都可以。另外一个好处是可以在其中插入js表达式
var text = `This is my first template literal`
3.5.1 字符串插值
var s=`This a template literal ${ `with another ${ 'one' } embedded inside it` }`
// <- 'This a template literal with another one embedded inside it'
3.5.2 多行模板字面量
可以方便的定义多行字符串
var escaped =
'The first line\n\
A second line\n\
Then a third line'
var concatenated =
'The first line\n' +
'A second line\n' +
'Then a third line'
var joined = [
'The first line',
'A second line',
'Then a third line'
].join('\n')
//es6 with template literal
var multiline =
`The first line
A second line
Then a third line`
3.5.3 Tagged Templates
不是很懂,有待下一次研究
3.6 let 和 const
js变量提升以及作用域很让人困惑,没有块级作用域
3.6.1 let声明和块级作用域
let变量具有块级作用域
let topmost = {}
{
let inner = {}
{
let innermost = {}
}
// attempts to access innermost here would throw
}
// attempts to access inner here would throw
// attempts to access innermost here would throw
最常用的地方就是for循环
for (let i = 0; i < 2; i++) {
console.log(i)
// <- 0
// <- 1
}
console.log(i)
// <- i is not defined
3.6.2 临时死区 TDZ
进入一个块级作用域,如果在let变量定义之前使用了该变量名,会抛出异常,如果代码在let定义之前企图访问用let定义的变量,都会抛出异常,因为let的变量有临时死区,也就是let变量定义之前,试图访问let变量都会报错。但是在函数中访问并不会报错,除非在定义之前执行了该函数
{
name = 'Barbara Penner'
// <- ReferenceError: name is not defined
let name = 'Stephen Hawking'
}
3.6.3 const声明
const变量和let变量都具有tdz,也就是在定义之前试图访问均会抛出错误。
const变量定义的时候必须要初始化,而且不能被显式赋值。在非严格模式下不会报错,但是该赋值语句不会起作用。但是只是指向的对象不能更改,对象本身可以被更改。
const people = ['Tesla', 'Musk']
people = []
console.log(people)
// <- ['Tesla', 'Musk']
const people = ['Tesla', 'Musk']
people.push('Berners-Lee')
console.log(people)
// <- ['Tesla', 'Musk', 'Berners-Lee']
const people = ['Tesla', 'Musk']
var humans = people
humans = 'evil'
console.log(humans)
// <- 'evil'