通过观看PHP中文网中关于ECMAScript6的学习教程,做了如下笔记。
ECMAScript是一种由Ecma国际(前身为欧洲计算机制造商协会,英文名称是European Computer Manufacturers Association)通过ECMA-262标准化的脚本程序设计语言。这种语言在万维网上应用广泛,它往往被称为JavaScript或JScript,但实际上后两者是ECMA-262标准的实现和扩展。
ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准。因为当前版本的ES6是在2015年发布的,所以又称ECMAScript 2015。
1. 块的作用域—let
以前的ES5只有全局作用域,现在可以通过使用ECMAScript的let作为块级作用域。在ES5中的例子:
var name = 'orange';
while (true) {
var name = 'apple';
console.log(name); //apple
break;
}
console.log(name); //apple
在ES6中的例子:
let name = 'orange';
while (true) {
let name = 'apple';
console.log(name); //apple
break;
}
console.log(name); //orange
2. 恒量—const
const也是用来声明变量的,但是声明的是常量,就是不能再更改。例子:
const i=10;
i=20; //Assignment to constant variable.
更改常量,浏览器就会报错。
3. 解构数组—Array Destructuring
在ES5中一般是这样做的:
function breakfast(){
return ["apple","orange","banana"];
}
var tmp=breakfast(),
dessert=tmp[0],drink=tmp[1],fruit=tmp[2];
console.log(dessert,drink,fruit); //apple orange banana
在ES6中是这样的:
function breakfast(){
return ["apple","orange","banana"];
}
let [dessert,drink,fruit]=breakfast();
console.log(dessert,drink,fruit); //apple orange banana
4. 解构数组—Object Destructuring
function breakfast(){
return {dessert:"apple",drink:"orange",fruit:"banana"};
}
let {dessert:dessert,drink:drink,fruit:fruit}=breakfast();
console.log(dessert,drink,fruit); //apple orange banana
5. 模板字符串—Template String
当插入大量代码时可以使用模板字符串来减少代码量
在ES5中往往这样写:
let dessert="apple",
drink="orange";
let breakfast="今天的早餐是"+dessert+"和"+drink+"!";
console.log(breakfast); //今天的早餐是apple和orange !
在ES6中可以这样写:
let dessert="apple",
drink="orange";
let breakfast=`今天的早餐是${dessert}和${drink}!`;
console.log(breakfast); //今天的早餐是apple和orange !
6. 带标签的模板字符串—Tagged Templates
let dessert="apple",
drink="orange";
let breakfast=kitchen`今天的早餐是${dessert}和${drink} !`;
function kitchen(strings,...values){
console.log(strings);
console.log(values);
}
输出结果为:
另一个例子:
let dessert="apple",
drink="orange";
let breakfast=kitchen`今天的早餐是${dessert}和${drink} !`;
function kitchen(strings,...values){
let result="";
for(var i=0;i<values.length;i++){
result+=strings[i];
result+=values[i];
}
result+=strings[strings.length-1];
return result;
}
console.log(breakfast); //今天的早餐是apple和orange !
7. 判断字符串里是否包含其他字符串
判断是以什么字符开头:startsWith()
判断是以什么字符结束:endsWith()
判断是否包含什么字符:includes()
let dessert="apple",
drink="orange";
let breakfast=`今天的早餐是${dessert}和${drink} !`;
console.log(breakfast.startsWith("今天"));//true
console.log(breakfast.endsWith("!"));//true
console.log(breakfast.includes("今天"));//true
8. 默认参数—Default Parameter Values
给默认参数赋值
在ES5中往往是这样做的:
function breakfast(dessert,fruit){
var dessert=dessert||"apple";
var fruit=fruit||"banana";
return dessert+fruit;
}
console.log(breakfast("cheek","orange"));//cheekorange
在ES6可以这样做:
function breakfast(dessert="apple",fruit="banana"){
return `${dessert}${fruit}`;
}
console.log(breakfast("cheek","orange"));
9. 展开操作符—Spread
展开数组为字符串
let fruits=["apple","banana","orange"];
console.log(fruits);//一个对象 ["apple", "banana", "orange"]
console.log(...fruits);//apple banana orange
10. 剩余操作符—Rest
function breakfast(dessert,drink,...foods){
console.log(dessert,drink,foods);
}
breakfast("apple","banana","orange","cheek");//apple banana (2) ["orange", "cheek"]
11. 解构参数—Destructured Parameters
function breakfast(dessert,drink,{location,restaurant}={}){
console.log(dessert,drink,location,restaurant);
}
breakfast("apple","banana",{location:"济南",restaurant:"董小姐"});//apple banana 济南 董小姐
12. 函数的名字—name属性
let breakfast=function(){};
console.log(breakfast.name);//breakfast
13. 箭头函数—Arrow Function
在ES5中:
var breakfast=function breakfast(dessert,drink){
return dessert+drink;
}
在ES6中:
var breakfast=(dessert,drink) => dessert+drink;
下面这段例子是引用于https://segmentfault.com/a/1190000004365693#articleHeader1
除了看上去更简洁以外,arrow function还有一项超级无敌的功能!
长期以来,JavaScript语言的this对象一直是一个令人头痛的问题,在对象方法中使用this,必须非常小心。例如:
class Animal {
constructor(){
this.type = 'animal';
}
says(say){
setTimeout(function(){
console.log(this.type + ' says ' + say);
}, 1000)
}
}
var animal = new Animal()
animal.says('hi') //undefined says hi
运行上面的代码会报错,这是因为setTimeout中的this指向的是全局对象。所以为了让它能够正确的运行,传统的解决方法有两种:
- 第一种是将this传给self,再用self来指代this
says(say){
var self = this;
setTimeout(function(){
console.log(self.type + ' says ' + say)
}, 1000)
}
- 第二种方法是用bind(this),即
says(say){
setTimeout(function(){
console.log(this.type + ' says ' + say)
}.bind(this), 1000)
}
但现在我们有了箭头函数,就不需要这么麻烦了:
class Animal {
constructor(){
this.type = 'animal'
}
says(say){
setTimeout( () => {
console.log(this.type + ' says ' + say)
}, 1000)
}
}
var animal = new Animal()
animal.says('hi') //animal says hi
当我们使用箭头函数时,函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,它的this是继承外面的,因此内部的this就是外层代码块的this。
14. 对象表达式
在ES5中:
var dessert="apple",drink="orange";
var food={
dessert:dessert,
drink:drink
};
console.log(food);
在ES6中:
var dessert="apple",drink="orange";
var food={
dessert,
drink
};
console.log(food);
15. 对象属性名
let food={};
food.dessert="apple";
food["hot drink"]="orange";
16. 对比两个值是否相等—Object.is()
判断两个值相等有时候会用“==”,甚至会判断绝对相等用到“===”,但有时候会不尽人意,这时就用到了Object.is()。
object.is(NaN,NaN);
17. 把对象的值复制到另一个对象里—Object.assign()
let breakfast={};
Object.assign(
breakfast,
{drink:"orange"}
);
console.log(breakfast);//Object {drink: "orange"}
18. 设置对象的prototype
—Object.setPrototypeOf()
可以在创建对象以后去改变对象的prototype。
let breakfast={
getDrink(){
return "apple";
}
};
let dinner={
getDrink(){
return "orange";
}
};
let sunday=Object.create(breakfast);
console.log(sunday.getDrink());//apple
console.log(Object.getPrototypeOf(sunday)===breakfast);//true
Object.setPrototypeOf(sunday,dinner);
console.log(sunday.getDrink());//orange
19. 设置对象的prototype—__proto__
let breakfast= {
getDrink(){
return "apple";
}
};
let dinner={
getDrink(){
return "beer";
}
};
let sunday={
__proto__:breakfast
};
console.log(sunday.getDrink());//apple
console.log(Object.getPrototypeOf(sunday)===breakfast);//true
sunday.__proto__=dinner;
console.log(sunday.getDrink());//beer
console.log(Object.getPrototypeOf(sunday)===dinner);//true
20.super
super关键字,它指代父类的实例(即父类的this对象)。
let breakfast= {
getDrink(){
return "apple";
}
};
let dinner={
getDrink(){
return "beer";
}
};
let sunday={
__proto__:breakfast,
getDrink(){
return super.getDrink() + " orange";
}
};
console.log(sunday.getDrink());//apple orange
21. 迭代器-Iterators
迭代器就是轮流交换。迭代器有几个特点,每一次执行的时候会返回一个对象,其包括{value:xx,done:true/false}
,当这个对象没有值后done就为true。另外迭代器有一个next()
的方法,当执行next()
方法后会返回{value:xx,done:true/false}
,当迭代后没有值了value
为undefined
,done
为true
。
例子:
function chef(foods){
let i=0;
return {
next(){
let done=(i>=foods.length);
let value=!done ? foods[i++]:undefined;
return {
value:value,
done:done
}
}
}
}
let lili=chef(["apple","cheek"]);
console.log(lili.next());
console.log(lili.next());
console.log(lili.next());
输出结果是:
22. 生成器-Generators
手工生成迭代器比较麻烦,可以通过Generators生成迭代器。
例子:
//生成器
function* chef(){
yield "apple";
yield "cheek";
}
//迭代器
let lili=chef();
console.log(lili.next());
console.log(lili.next());
console.log(lili.next());
输出结果是:
还可以这样做:
//生成器
function* chef(foods){
for(let i=0;i<foods.length;i++){
yield foods[i];
}
}
//迭代器
let lili=chef(["apple","cheek"]);
console.log(lili.next());
console.log(lili.next());
console.log(lili.next());
输出结果同上。
23. 类-class
例子:
class Chef {
constructor(food){//构造方法
this.food = food;
}
cook(){
console.log(this.food);
}
}
let lili=new Chef("apple");
lili.cook(); //apple
上面代码首先用class定义了一个“类”,可以看到里面有一个constructor方法,这就是构造方法,而this关键字则代表实例对象。简单地说,constructor内定义的方法和属性是实例对象自己的,而constructor外定义的方法和属性则是所有实例对象可以共享的。一般类名首字母大写。
24. set和get
set,设置方法或属性;get,得到方法或属性
class Chef {
constructor(food){
this.food = food;
this.dish=[];
}
get menu(){
return this.dish;
}
set menu(dish){
this.dish.push(dish);
}
}
let lili=new Chef();
console.log(lili.menu="apple"); //apple
console.log(lili.menu="cheek"); //cheek
console.log(lili.menu); //(2) ["apple", "cheek"]
25. 静态方法—static
静态方法是不需要实例化类。
class Chef {
constructor(food){
this.food = food;
this.dish=[];
}
get menu(){
return this.dish;
}
set menu(dish){
this.dish.push(dish);
}
static cook(food){//静态方法
console.log(food);
}
}
Chef.cook("apple");//apple //不需要实例化就可以调用
26. 继承—extends
通过extends可以实现子类继承父类的方法和属性。
class Person{
constructor(name,birthday){
this.name=name;
this.birthday=birthday;
}
intro(){
return `${this.name},${this.birthday}`;
}
}
class Chef extends Person{
constructor(name,birthday){
super(name,birthday);
}
}
let lili=new Chef("anita","1963-10-10");
console.log(lili.intro());//anita,1963-10-10
27. Set
Set有点像数组Array,但Set里的内容不能重复。
let dessert=new Set(["apple","orange","banana"]);
console.log(dessert);
dessert.add("cheek");//为Set添加内容
console.log(dessert);
console.log(dessert.size);//计算Set里有多少数据
console.log(dessert.has("apple"));//判断是否有某个数据
dessert.delete("apple");//删除某个数据
console.log(dessert);
dessert.forEach(dessert=> {//循环遍历获取数据
console.log(dessert);
});
dessert.clear();//清空Set
console.log(dessert);
输出结果为:
28. Map
Map类内包含的数据是键值对,即key=>value。
let food=new Map();
let fruit={},cook=function(){},dessert="甜点";
food.set(fruit,"apple");//赋值
food.set(cook,"orange");
food.set(dessert,"cheek");
console.log(food);
console.log(food.size);
console.log(food.get(fruit));//获取某个key的value
console.log(food.get(cook));
food.delete(dessert);//删除某个键值对
console.log(food.has(dessert));//判断是否存在某个键值对
food.forEach((value,key)=>{//循环遍历获取数据
console.log(`${key}=${value}`);
});
输出结果:
29. Module
ES6提供了模块,即可以根据需要将应用分割成不同的部分。通过视频可以详细了解。
在这个网址中,对Module进行了详细的讲解。