ES6也被称为ES2015,它带来了很多重大的改变!
https://www.css88.com/archives/9922 https://www.css88.com/archives/9958
ES6的重要改变包括:
- Arrow function(箭头函数)
- Promise
- Generator
- let 和 const
- Class(类)
- Module(模块)
- Multiline strings(多行字符串)
- Template literal(模板字面量)
- Default parameters(默认参数)
- The spread operator(展开操作符)
- Destructuring assignment(解构赋值)
- Enhanced object literals(增强的对象字面量)
- for...of 循环
- Map 和 Set
1. var let const变量
var
: 函数作用域 -> (1) 在函数内部使用var ,只属于函数内部,函数外部无法访问。 (2) 可以重复声明赋值
let
: 块级作用域 -> (1) 作用域只限于for循环
,if语
或者普通块
内部 (2) 可以重复赋值,但不可再次声明。
const
: 块级作用域 -> (1) 不可以再次赋值 (2) 对象本身不可修改,内部属性可以修改 (3) Object.freeze( ) :阻止属性的修改。
let name = 'wxw';
let name = '万达'; // 报错,不可多次声明
name = '万达'; // ok ,正确赋值
const person ={ name:'wxw',age:32 }
person = {name:'www'} // 报错,不可修改person对象本身
person.name="王晓文" // 修改对象内部属性,OK,没有问题,正确赋值
const jerry =Object.freeze(person); // 冻结对象,不可增删改这个对象的已有属性
var name = 'wxw'; // 污染全局window的name属性
// 立即执行函数,可以使变量name私有化
(function () {
var name = 'wxw';
})();
// 使用var声明,会导致结果永远为循环最后值
for (var index = 0; index < 10; index++) {
console.log(index);
setTimeout(function () {
console.log(`index-${index}`);
}, 1000) // var: 10遍10 let: 依次输出 0- 9
}
console.log(`index-${index}`); //10
// 使用 let 代替,解决该问题。
console.log(name);
var name ="wx"; // var : undefined -> 变量的声明会提升
let name ="wxw"; // let: 报错,没有定义 -> 变量声明不提升
2. 箭头函数
- 省略 function { } ,增加 =>
- 一个参数时 :省略( ) 多个参数时: 必须加( ,,,)
- 函数体{ } 内部只有一行代码,可以省略
return
关键字以及{ }
const array =[1,2,3,4,5];
let newArray= array.map(function(ele){return ele*2 });
let newArray1= array.map(ele => ele*3) // 箭头函数
let greet = name => alert(`hello${name}`)
greet('wxw'); // 箭头函数,可赋值给一个变量,以命名函数的形式调用。
//setTimeOut()
setTimeout(function () {
console.log('1秒后出现!');
}, 1000)
setTimeout(() => console.log('1秒后出现!'), 1000);
- 箭头函数并没有自己的this值,它的this是派生而来的,继承于
父级作用域
,并且在调用的时候不会改变!如果箭头函数在另一个函数体内,它共享其父函数的arguments
变量。javascript 的 this 值一般是在运行的时候才绑定的,指向的是
调用他的对象
!!
// 普通函数 this 指向问题
const jerry = {
name: '王晓文',
hobbies: ['sleep', 'coding'],
printHobbies: function () {
console.log('普通函数this指向', this); // 整个jerry对象
//1、 map方法内部是一个独立的函数,不再是对象的方法,指向window对象。
this.hobbies.map(function (hobby) {
console.log('2222', this); //window对象
console.log(`${this.name} love ${hobby}`); // 'love sleep' / 'love coding'
});
// 2、普通函数,通过capply,bind纠正this指向,指向Jerry对象
this.hobbies.map(function (hobby) {
console.log('2222', this); //jerry对象
console.log(`${this.name} love ${hobby}`); // 'love sleep' / 'love coding'
}.bind(this));
// 3、箭头函数纠正this指向 -> 父级作用域 Jerry对象
this.hobbies.map(ele => {
console.log('箭头函数this指向', this); // 箭头函数的this,指向的是父级作用域 -> jerry对象
console.log(`${this.name} love ${ele}`); // '王晓文 love sleep' '王晓文 love coding'
})
}
}
jerry.printHobbies();
3. 模板字符串
反引号 `` , $ { 变量}
var num=Math.random();
console.log(`your num is ${num}`);
4. 参数默认值,不定参数,拓展参数
// 1. ES6 参数默认值 第一种方法:
function animal(type = '王晓文') { // 默认没有参数时候,使用 '王晓文' 作为参数
console.log(type);
}
animal();
// 参数默认值 第二种方法:
function animal(type) {
type = type || '王晓文2'
console.log(type);
}
animal();
// 2. 不定参数:
function animal(...type) {
console.log(type);
}
animal('王晓文1', '王晓文2', '王晓文3', '王晓文4');
// 3. 固定数量参数的函数进行参数数量不等的调用
function sayHello(p1, p2, p3) {
console.log(`hello ${p1},${p2},${p3}`);
}
let array = ['wxw1', 'wxw2', 'wxw3', 'wxw4', 'wxw5'];
sayHello(array); // hello wxw1,wxw2,wxw3,wxw4,wxw5,undefined,undefined
// 普通方法
sayHello.apply(null,array); // hello wxw1,wxw2,wxw3
// ES6
sayHello(...array); // hello wxw1,wxw2,wxw3
5. ...拓展运算符
[...] 拓展运算符
将一个数组转为用逗号分隔的参数序列。
// 如果将扩展运算符用于数组赋值,只能放在参数的最后一位,否则会报错。
console.log(1, ...[2, 3, 4], 5) // 1,2,3,4,5
...拓展运算符
会生成新的数组或对象
let a = [1, 2, 3];
let b = [ ...a ]; //创建新的数组b,不再关联源数组a
let c = a;
b.push(4);
console.log(a); // [1, 2, 3]
console.log(b); // [1, 2, 3, 4] //不同的数组
c.push(5);
console.log(a); // [1, 2, 3, 5]
console.log(c); // [1, 2, 3, 5] //同一个数组
Object.assign()
用于将所有可枚举的属性的值从一个或者多个源对象中复制到目标对象,返回目标对象。object.assign(target , ...sources)
栗子:动态增加删除带有固定字段的行数据!实际原理是向数组动态增加删除对象!
// 常见需求: 点击增加删除按钮动态添加行数据(在数组中添加对象,进行循环)
this.materials = [];
this.itemObject = { name:'', age:'', sex:'' };
//(1)动态增加行数据
const itemObject = Object.assign({}, this.itemObject);
this.materials = [...this.materials , itemObject] // ... 会将数组以 , 分割成多个元素参数
//(2)动态删除行数据
itemDelete(index) {
this.materials = this.materials.filter((item, _index) => {
return _index !== index;
});
}
6. 解构分配,解构赋值
给定一个对象,可以只提取一些值,并将它们放入命名变量中
const person = {
firstName: 'Tom',
lastName: 'Cruise',
actor: true,
age: 54, //made up
}
const {firstName: name, age} = person
// name和age包含了所需的值
console.log(name) // "Tom"
console.log(age) // 54
该语法同样适合数组!
let [x, y] = [1, {name: '王晓文',age: 22}];
console.log(x, y); // 1 {name: "王晓文", age: 22}
const array = [1,2,3,7];
const [first,second,,four] = array;
console.log(first); //1
console.log(four); // 7
7. for ... of
很早便推出了
forEach()
,虽然很好,但是没有办法中断循环(比如像for
循环:使用break
,return
)!ES6推出的
for...of
循环,结合forEach
的简洁和中断循环的能力!
// for ... of 循环的是元素值 (补充:for ... in 循环的是变量的索引值 index)
for (const v of ['a', 'b', 'c']) {
console.log(v); // 'a' ,'b','c'
}
用
for...of
模拟forEach()
for (const [index, ele] of ['a', 'b', 'c'].entries()) {
console.log(index); // 0 , 1, 2 索引
console.log(ele) // 'a' 'b' 'c'
}
8. class(类)
javascript 是唯一一个基于原型集成的主流语言,但是ES6后引入了类Class的概念,这只是JavaScript内部工作的语法糖,但是改变了我们构建JavaScript程序的方式。
class Person {
constructor(name) {
this.name = name;
}
hello() {
return `${this.name},你好呀!`;
}
}
class Actor extends Person {
hello2() {
return super.hello() + ' I am wxw.'; // super()引用父类
}
}
var tom = new Actor('mxy');
console.log(tom.hello2()); // mxy,你好呀! I am wxw.