ES6常⽤语法总结
let、const关键字
在ES6之前,JavaScript中变量默认是全局性的,只存在函数级作⽤域,声明函数曾经是创造作⽤域的唯⼀⽅法。这点和其他编程语⾔存在差异,其他语⾔⼤多数都存在块级作⽤域。所以在ES6中,新提出的let和const关键字使这个缺陷得到了修复。
if (true) {
let a = 'name';
}
console.log(a); // ReferenceError: a is not defined
同时还引⼊的概念const,⽤来定义⼀个常量,⼀旦定义以后不可以修改,如果是引⽤类型,那么可以修改其引⽤属性,不可以修改其引⽤。
const MYNAME = 'liangyin';
MYNAME = 'doke';
// TypeError: Assignment to constant variable.
const MYNAME = {
first: 'liang'
};
MYNAME.last = 'yin';
// {first: "liang", last: "yin"}
有以下⼏点需要注意:
尽量使⽤let和const代替var
声明⽅法尽量使⽤const以防⽌后期⽆意覆盖
const定义的变量使⽤⼤写形式
函数
箭头函数
箭头函数是⼀种更简单的函数声明⽅式,可以把它看作是⼀种语法糖,箭头函数永远是匿名的。
let add = (a, b) => {
return a + b;
}
// 当后⾯是表达式(expression)的时候,还可以简写成
let add = (a, b) => a + b;
// 等同于
let add = function(a, b) {
return a + b;
}
// 在回调函数中应⽤
let number = [1, 2, 3];
let doubleNumber = number.map(number => number * 2);
console.log(doubleNumber);
// [2, 4, 6] 看起来很简便吧
this在箭头函数中的使⽤
在⼯作中经常会遇到this在⼀个对象⽅法中嵌套函数作⽤域的问题。
var age = 2;
var kitty = {
age: 1,
grow: function() {
setTimeout(function() {
console.log(++this.age);
}, 100)
}
};
// 3
其实这是因为,在对象⽅法的嵌套函数中,this会指向global对象,这被看做是JavaScript在设计上的⼀个重⼤缺陷,⼀般都会采⽤⼀些hack 来解决它。
let kitty = {
age: 1,
grow: function() {
const self = this;
setTimeout(function() {
console.log(++self.age);
}, 100);
}
}
es6字符串转数组// 或者
let kitty = {
age: 1,
grow: function() {
setTimeout(function() {
console.log(this.age);
}.bind(this), 100)
}
}
现在有了箭头函数,可以很轻松地解决这个问题。
let kitty = {
age: 1,
grow: function() {
setTimeout(() => {
console.log(this.age);
}, 100)
}
}
但是箭头函数并不是万能的,任何事物都具有两⾯性,语⾔的新特性常常被误解、滥⽤,⽐如箭头函数的使⽤就存在很多误区。⼤家可以移步☞。
函数默认参数
ES6出现以前,⾯对默认参数都会让⼈感到很痛苦,不得不采⽤各种hack⼿段,⽐如说:values = values || []。现在⼀切都变得轻松很多。function desc(name = 'liangyin', age = 18) {
return name + '已经' + age + '岁了'
}
desc();
// liangyin已经18岁了
Rest参数
当⼀个函数的最后⼀个参数有...这样的前缀,它就会变成⼀个参数的数组。
function test(...args) {
console.log(args);
}
test(1, 2, 3);
// [1,2,3]
function test2(name, ...args) {
console.log(args);
}
test2('liangyin', 2, 3);
/
/ [2,3]
它和arguments参数有如下区别:
Rest参数只是没有指定变量名称的参数数组,⽽arguments是所有参数的集合。
arguments对象并不是⼀个真正的数组,⽽Rest参数是⼀个真正的数组,可以使⽤各种数组⽅法,⽐如sort,map等。
展开操作符
刚刚讲到了Rest操作符来实现函数参数的数组,其实这个操作符的能⼒不仅如此。它被称为展开操作符,允许⼀个表达式在某处展开,在存在多个参数(⽤于函数调⽤),多个元素(⽤于数组字⾯量)或者多个变量(⽤于解构赋值)的地⽅就会出现这种情况。
⽤于函数调⽤
之前在JavaScript中,想让函数把⼀个数组依次作为参数进⾏调⽤,⼀般会采取以下措施:
function test(x, y, z) {};
var args = [1, 2, 3];
test.apply(null, args);
有了ES6的展开运算符,可以简化这个过程:
function test(x, y, z) {};
let args = [1, 2, 3];
test(...args);
⽤于数组字⾯量
在之前的版本中,如果想创建含有某些元素的新数组,常常会⽤到splice、concat、push等⽅法:
var arr1 = [1, 2, 3];
var arr2 = [4, 5, 6];
var arr3 = at(arr2);
console.log(arr3);
// [1,2,3,4,5,6]
使⽤展开运算符以后就简便了很多:
let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];
let arr3 = [...arr1, ...arr2];
console.log(arr3);
// [1,2,3,4,5,6]
对象的展开运算符(ES7)
数组的展开运算符简单易⽤,那么对象有没有这个特性?
let uzi = {
name: 'uzi',
age: 50
};
uzi = {
...uzi,
sex: 'male'
};
console.log(uzi);
// {name: "uzi", age: 50, sex: "male"}
这是ES7的提案之⼀,它可以让你以更简洁的形式将⼀个对象可枚举属性复制到另外⼀个对象上去。
模板字符串
在ES6之前的时代,字符串拼接总是⼀件令⼈很很很不爽的⼀件事,但是在ES6的时代,这个痛点终于被治愈了!!!// 之前的做法
var name = 'uzi';
var a = 'My name is ' + uzi + '!';
// 多⾏字符串
var longStory = 'This is a long story,' + 'this is a long story,' + 'this is a long story.'
// 有了 ES6 之后我们可以这么做
let name = 'uzi';
let a = `My name is ${name} !`;
let longStory = `This is a long story,
this is a long story,
this is a long story.`
解构赋值
解构语法可以快速从数组或者对象中提取变量,可以⽤⼀个表达式读取整个结构。
解构数组
let number = ['one', 'two', 'three'];
let [one, two, three] = number;
console.log(`${one},${two},${three}`);
// one,two,three
解构对象
let uzi = {
name: 'uzi',
age: 20
};
let {
name,
age
} = uzi;
console.log(`${name},${age}`);
// uzi,20
解构赋值可以看做⼀个语法糖,它受Python语⾔的启发,提⾼效率之神器。
众所周知,在JavaScript的世界⾥是没有传统类的概念,它使⽤的是原型链的⽅式来完成继承,但是声明⽅式总是怪怪的(很⼤⼀部分⼈不遵守规则⽤⼩写变量声明⼀个类,这就导致类和普通⽅法难以区分)。
在ES6中提供了class这个语法糖,让开发者模仿其他语⾔类的声明⽅式,看起来更加明确清晰。需要注意的是,class并没有带来新的结构,只是原来原型链⽅式的⼀种语法糖。
class Animal {
// 构造函数
constructor(name, age) {
this.name = name;
this.age = age;
}
shout() {
return `My name is ${this.name}, age is ${this.age}`;
}
// 静态⽅法
static foo() {
return 'this is static method';
}
}
const cow = new Animal('uzi', 2);
cow.shout();
// "My name is uzi, age is 2"
Animal.foo();
// "this is static method"
class Dog extends Animal {
constructor(name, age = 2, color = 'black') {
/
/ 在构造函数中直接调⽤ super ⽅法
super(name, age);
}
shout() {
// ⾮构造函数中不能直接使⽤ super ⽅法
// 但是可以采⽤ super. + ⽅法名调⽤⽗类⽅法
return super.shout() + `, color is ${lor}`;
}
}
const uzisDog = new Dog('uzi');
uzisDog.shout();
// "My name is uzi, age is 2, color is black"
对象
Object.assign⽅法⽤来将源对象的所有可枚举属性复制到⽬标对象.
let target = {
a: 1
};
// 后边的属性值,覆盖前⾯的属性值
Object.assign(target, {
b: 2,
c: 3
}, {
a: 4
});
console.log(target);
// {a: 4, b: 2, c: 3}
为对象添加属性
class add {
constructor(obj) {
Object.assign(this, obj);
}
}
let p = new add({
x: 1,
y: 2
});
console.log(p);
// add {x: 1, y: 2}
为对象添加⽅法
Object.assign(add.prototype, {
getX() {
return this.x;
},
setX(x) {
this.x = x;
}
});
let p = new add(1, 2);
console.X()); // 1
克隆对象
function cloneObj(origin) {
return Object.assign({}, origin);
}
Set、Map和Array.from
Set
Set⾥⾯的成员的值都是唯⼀的,没有重复的值,Set加⼊值时不会发⽣类型转换,所以5和"5"是两个不同的值。    // 数组去重
function dedupe(array) {
return Array.from(new Set(array));
}
console.log(dedupe([1, 2, 2, 3])); // 1, 2, 3
Map
Map类似于对象,也是键值对的集合,但是"键"的范围不限于字符串,各种类型的值(包括对象)都可以当做键.
let m = new Map();
let o = {
p: 'Hello World'
};
m.set(o, 'content');
<(o); // content
m.has(o); // true
m.delete(o); // true
m.has(o); // false
m.set(o, 'my content').set(true, 7).set('foo', 8);
console.log(m);
// Map(3) {{…} => "my content", true => 7, "foo" => 8}
// Map/数组/对象三者之间的相互转换
console.log([...m]);
// (3) [Array(2), Array(2), Array(2)]
Array.from
转换Map
Map对象的键值对转换成⼀个⼀维数组。
const map1 = new Map();
map1.set('k1', 1);
map1.set('k2', 2);
map1.set('k3', 3);
console.log(Array.from(map1))
// [Array(2), Array(2), Array(2)]

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。