一、新的变量声明方式
1、let
使用let声明的变量可以重新赋值,但是不能在同一作用域内重新声明,常用来声明一个汇编改变的变量。
2、const
使用const声明的变量必须赋值初始化,但是不能在同一作用域类重新声明也无法重新赋值,常用来声明一个值不会被改变的量。当值为基础数据类型时,那么值就是它本身,不可被改变;如果值为引用数据类型时(对象、数组),值就指的是它的引用,只要引用不变即可,仍可改变引用指向的对象里的值。
const a=1;
a=2; //报错,Uncaught TypeError: Assignment to constant variable.
const obj = {
a:1,
};
obj.a=2;
obj.b=1;
const arr = [1,2];
arr.push(3);
3、两种声明新特性
最重要的两个特性就是提供了块级作用域与不再具备变量提升。
function test(tp){
if(tp){
var a= true;
}else{
var b= false;
console.log(a); //tp=false,undefined
}
}
test(false);
运行test(false)后输出的是undefined,这是因为执行function函数之前,所有变量定义都会被提升到函数块最顶部(变量定义以函数"{}"为块)。
let与const声明的变量解决了这种问题,因为他们是块级作用域(任何"{}"为块), 在块中变量会陷入暂时性死区直到该变量的声明被处理。
function test(tp){
if(tp){
let a = true;
}else {
const b = false;
console.log(a); //tp=false,报错a is not defined
}
}
test(false);
运行test(false)后输出的是ncaught ReferenceError: a is not defined报错,因为 a 没有在 else 语句、上层的函数作用域、全局作用域内声明,所以抛出 ReferenceError。
二、解析结构
1、解构数组
数组以序号位置一一对应,这是一个有序的对应关系。
let [a, b, c] = [1, 2, 3];
// 即: let a = 1;let b = 2;let c = 3;
//[a,,c]忽略b的写法也允许
let [bar, foo] = [1];
// 解构失败: undefined
// 即: let bar = 1; let foo = undefined
let [a] = 1;
// 等号的右边不是数组 (或者严格地说,不是可遍历的解构)
// 报错:Uncaught SyntaxError: Identifier 'a' has already been declared
// 如果赋值的字面量全等undefined, 则默认值生效
let [x = 1] = [undefined]; // x === 1
let [x = 1] = []; //x === 1
// null 不全等 undefined, 所以默认值不生效
let [x = 1] = [null]; // x === null
2、解构对象
对象根据属性名一一对应,这是一个无序的对应关系。
const obj = { a: "aaa", b: "bbb" };
let { a, b,c, d="ddd",a:e} = obj ;
// 变量与属性重名对应赋值,即let a=obj .a;let b=obj .b
// 没有找到对应属性的为undefined,即let c = undefined
// 对应的属性值严格等于undefined,取默认值,即let d = "ddd"
// 匹配属性:真正变量,即let e = obj .a(对象中"a"对应的值)
console.log(a,b,c,d,e); //aaa bbb undefined ddd aaa
3、解析嵌套结构
let obj = {
p: [
'Hello',
{ y: 'World' }
]
};
let { p: [x, { y }] } = obj;
// 注意,这时p是模式,与obj字段对应
// 继续解构
// let x="Hello";y = "World";
console.log(x,y); //Hello World
4、函数参数的解构
function demo(a, b, {c , d} = {}){ // 第三个参数默认值为 {}
console.log(a, b, c, d)
}
demo(1, 2, {c : "c", d:"d"}); //1,2,c,d
5、字符串解构赋值
let [a, b, c, d, e] = 'hello'; //字符串数组
console.log(a,b,c,d,e); //h e l l o
let {length} = 'hello';
//类似数组的对象都有一个length属性,因此还可以对这个属性解构赋值
console.log(length); //5
三、模板字符串
模板字符串是为了解决使用+号拼接字符串的不便利而出现的。使用 反单引号`` 将整个字符串包裹起来,而在其中使用 ${} 来包裹一个变量或者一个表达式。
let name = "Bob";
let time = "today";
console.log(`Hello ${name}, how are you ${time}?`);
console.log(`Hello ${name},
how are you ${time}?`);
// 提示:在模板字符串中需要使用反引号,则前面需要用反斜杠转义
(反单引号内部可各种换行,内容是怎样显示怎样,像<pre>标签,可动态界面时,可用此来取一大段需要动态生成的html标签,即遇到换行不需要用很多"+"号连接)
四、默认参数
1、函数默认参数
//es5
function greet(name, greeting) {
let Name = (typeof name !== 'undefined') ? name : 'Student';
let Greeting = (typeof greeting !== 'undefined') ? greeting : 'Welcome';
console.log(`${Greeting} ${Name}!`);
}
greet(); // Welcome Student!
greet('James'); // Welcome James!
greet('Richard', 'Howdy'); // Howdy Richard!
//es6
function greet(name = 'Student', greeting = 'Welcome') {
console.log(`${Greeting} ${Name}!`);
}
如果不传入参数, 或者传入undefined, 则使用默认值。
2、解构默认参数
解构时已说明。
五、展开运算符
1 、展开字面量对象
在ES6中用(...)来表示展开运算符,它可以将数组或者对象进行展开。
展开结合数组
//es5
const arr1 = [1,2,3];
const arr2 = [3,4];
const arr3 = arr1.concat(arr2);
console.log(arr1); //concat不会改变现有的数组,而仅仅会返回被连接数组的一个副本。
console.log(arr3); //arr1和arr2的合并 */
//es6
const arr1 = [1,2,3];
const arr2 = [3,4];
console.log(...arr1); //1 2 3
const arr3 = [...arr1,...arr2];
console.log(arr3); //arr1和arr2的合并
用于方法中
function func(x, y, z, a, b) {
console.log(x, y, z, a, b);
}
var args = [1, 2];
func(0, ...args, 3, ...[4]); // 0 1 2 3 4
展开结合对象
//jQuery
var obj1 = {
a: 1,
b: 2,
c: 3
}
var obj2 = {
d: 4,
e: 5,
f: 6
}
var obj3 = $.extend({},obj1,obj2); //目标对象(第一个参数)将被修改,所以用{}
console.log(obj3);
//es6
const obj1 = {
a: 1,
b: 2,
c: 3
}
const obj2 = {
d: 4,
e: 5,
f: 6
}
const obj3 = {
...obj1,
...obj2
}
console.log(obj3); //obj1和obj2两对象的结合
2、剩余参数
将变量赋数组值时
使用展开运算符将数组展开为多个元素, 使用剩余参数可以将多个元素绑定到一个数组中
const order = [20.17, 18.67, 1.50, "cheese", "eggs", "milk", "bread"];
const [total, subtotal, tax, ...items] = order;
console.log(items); //数组(4) ["cheese", "eggs", "milk", "bread"]
可变参数函数
展开运算符还用在函数的参数中,来表示函数的不定参。只有放在最后才能作为函数的不定参,否则会报错。
const add = (a, b, ...more) => {
return more.reduce((m, n) => m + n) + a + b
}
console.log(add(1, 23, 1, 2, 3, 4, 5)) // 39
//es6 reduce说明
var numbers = [15.5, 2.3, 1.1, 4.7];
function getSum(total, num) {
return total + Math.round(num); //取最近的整数,0.5向大数的方向算
}
function myFunction(item) {
return item.reduce(getSum, 1);
}
console.log(myFunction(numbers)); //24+1
六、箭头函数
1、写法
let demoFun = (a, b) => a + b
// 返回的是 a + b,当函数直接被return时,可以省略函数体的括号
let demoFun = params => ({foo: bar})
//返回一个对象时,函数体外要加圆括号
let demoFun = (param1, param2, ...rest) => { statements }
// 支持 剩余参数和默认参数,statements为函数处理逻辑
2、箭头函数没有自己的this。箭头函数会捕获其所在上下文的 this 值,作为自己的 this 值。如果上下文没有this, 则this指向Window对象。
const person = {
name: 'tom',
getName: () => this.name
}
console.log(person.getName());
// 实际编译结果却是
var person = {
name: 'tom',
getName: function getName() {
return undefined.name;
}
};
需要用到this可用此种写法
const person = {
name: 'tom',
getName: function() {
return setTimeout(() => {console.log(this.name)}, 1000);
//setTimeout返回一个整数,表示定时器的编号
}
}
const a = person.getName(); //定时器返回1赋值给a,第一次执行定时器;此处延时1s控制台会打印tom
console.log(a); //1
console.log(a); //1
console.log(person.getName());
//2,第二次执行定时器;延时后打印tom
//babel转译结果
'use strict';
var person = {
name: 'tom',
getName: function getName() {
var _this = this; // 使用了我们在es5时常用的方式保存this引用
return setTimeout(function () {
console.log(_this.name);
}, 1000); //setTimeout返回一个整数,表示定时器的编号
}
};
var a = person.getName(); //定时器返回1赋值给a,第一次执行定时器;此处延时1s控制台会打印tom
console.log(a); //1
console.log(a); //1
console.log(person.getName()); //2,第二次执行定时器;延时后打印tom */
七、对象字面量简写法
1、当属性与值的变量同名时。
let type = 'quartz';
let color = 'rose';
let carat = 21.29;
//es5
const gemstone = {
type: type,
color: color,
carat: carat
//es6
const gemstone = {type,color,carat};
console.log(gemstone);
2、简写方法的名称。
let gemstone = {
testFunc() {
console.log("对象字面量方法简写");
}
};
gemstone.testFunc();
3、在对象字面量中可以使用中括号作为属性,表示属性也能是一个变量了。
const name = 'Jane';
const person = {
[name]: true //'Jane':true
}
console.log(person.Jane); //true
八、Class类
// ES5
// 构造函数
function Person(name, age) {
this.name = name;
this.age = age;
}
// 原型方法
Person.prototype.getName = function() {
return this.name
}
//静态属性
Person.info='静态属性';
// ES6
class Person {
constructor(name, age) { // 构造函数
this.name = name;
this.age = age;
}
getName() { // 原型方法(千万不要加上function)
return this.name
}
}
//静态属性
Person.info = '静态属性';
const person = new Person("qiu", 24);
console.log(person.getName()); //qiu
console.log(Person.info); //静态属性
class中,用static修饰即为类(静态)方法(可直接类名访问),即在这个类(构造函数)对象本身身上的方法;实例方法,实例化对象身上的方法。两种挂在的内存区不一样;静态属性需要写在class外面,直接挂载到此类身上。
九、类的继承extends
class PersonExt extends Person{
constructor(name,age,birthday){
super(name,age);
//在继承的构造函数中,必须调用一次super方法,它表示构造函数的继承;必须在this之前被调用
this.birthday = birthday;
}
supGetName(){
console.log(super.getName()); //super直接调用父级的原型方法
}
}
const person = new PersonExt("qiurx",24,"0417");
console.log(person.getName()); //qiurx
person.supGetName(); //qiurx
十、Set和Map
(略)😀
十一、字符串新方法
1、String.prototype.includes('判断要包含的字符串')
判断一段字符串是否包含某项字符,返回布尔值。
const str = '这是一串测试字符串!';
//es5
if(str.indexOf('测试')!=-1){ //返回的是包含字符串的位置,为-1即不存在
//包含
console.log('包含');
}else{
//不包含
console.log('不包含');
}
//es6
if(str.includes('测试')){ //返回的是布尔值
//包含
console.log('包含');
}else{
//不包含
console.log('不包含');
}
2、String.prototype.padStart(maxLength,fillString='')从开始位置填充;
/String.prototype.padEnd(maxLength,fillString='')从结束位置填充。
不改变原来字符串。
maxLength填充完毕之后的长度;fillString='用什么来填充'。
let y = '2019';
//对月和年进行填充
let m = '3'.padStart(2,'0');
let d = '5';
d.padStart(2,'0');
console.log(`日期:${y}-${m}-${d}`);
十二、数组新方法
1、reduce()
用于合并处理数组。接收一个函数作为累加器(calback对数组每个元素进行处理),数组中每个值按顺序开始合并,最终为一个值。
array.reduce(calback(previousValue,currentValue,[index],[array]),[initialValue])
calback处理数组中每个值进行累加的函数,函数参数:
-previousValue:上一次调用回调返回的值,或者是提供的初始值(initialValue)
-currentValue:数组中当前被处理的元素
-index:当前元素在数组中的索引
-array:调用reduce的数组
initialValue作为第一次调用callback的第一个参数,即合并的初始值,这个参数不是必需的。
var numbers = [15.5, 2.3, 1.1, 4.7];
//total上次调用累加处理函数的返回值;num数组当前元素;index当前元素在数组中索引;array数组
function getSum(total, num ,index ,array) {
console.log(`当前元素索引:${index}`);
console.log(`被处理的数组:${array}`);
return total + Math.round(num); //取最近的整数,0.5向大数的方向算
}
function myFunction(item) {
return item.reduce(getSum, 1); //1为循环合并处理的初始值
}
console.log(myFunction(numbers)); //1+24
2、filter()
用于筛选数组元素成新数组。使用指定函数测试数组所有元素,并创建一个包含通过测试元素的新数组。
array.filter(callback(currentValue,[index],[arr]), [thisArg])
calback对数组每个元素进行测试的函数,返回(弱)布尔类型false/true进行保留元素确定。参数:
-currentValue:当前元素的值
-index:当前元素的索引
-arr:当前元素所在的数组对象
thisArg对象作为该执行回调时使用,传递给函数,用作 "this" 的值。
var a = [1, 2, 3, 4, 5];
var b = a.filter((item,index,arr) => {
console.log(`当前元素索引:${index}`);
console.log(`被处理的数组:${arr}`);
return item > 3;
});
console.log(b);
3、map()
用于处理数组中每一个元素返回一个新数组。返回一个由原来数组中的每一个元素调用一个指定方法后返回值组成的新数组。
array.map(function(currentValue,[index],[arr]), [thisValue])
calback数组中每个元素都会执行这个函数。参数:
-currentValue:当前元素的值
剩余同上。
十三、导入模块
ES6中导入其他模块的一种方式import
。
在项目的main.js中:
import $ from 'jquery' //纯正的JS模块,会暴露成员$,需要接收一下
import './css/index.css' //单纯的样式,不会暴露成员,直接拿过来