简单说:ECMAScript 是一套标准(它不是一种语言),JavaScript 实施的就是这一套标准【 es6 <=> es2015】,ES6强制开启 严格模式 ,变量为未声明不能引用!
【作用域】:一个变量的有效范围,js 之前只有全局作用域,和函数作用域

1.【块级作用域 】

// 定义一个‘块’, 最简单的就是一个 { } ,let 定义的变量作用域只在这个块里
 if(true){
    // var fruit = '苹果';
	let fruit = '苹果';
 }
 
console.log(fruit); // fruit is not defined

2.【恒量 const】: 不能为const定义的 恒量 重新赋值

const fruit = '香蕉';
 console.log(fruit);
 const fruit = '苹果';
 
 console.log(fruit); // Identifier 'fruit' has already been declared
const fruit = [];
 fruit.push("香蕉");
 console.log(fruit); // 可以对 const定义的 恒量进行操作,就是不能够 重新赋值;

3.【解构 ( 分解一个结构 )】 例如:数组

let [dessert,drink,fruit] = ['蛋糕',"茶水","香蕉"];
 
 console.log(dessert); // 蛋糕
 console.log(drink); // 茶水
 console.log(fruit); // 香蕉
 console.log(dessert,drink,fruit); // 蛋糕 茶水 香蕉

4.【解构 对象】

function breakfast(){
   return {dessert:"蛋糕",drink:"茶水",fruit:"苹果" }
};

// 前面这个 dessert是对应的属性名,后面的属性值的名称是我们自定义的,
// 将 dessert 的值 赋给 admin

let {dessert:admin ,drink:zhou ,fruit: yuan} = breakfast();

console.log(admin,zhou,yuan); // 蛋糕 茶水 苹果

5.【解构参数】

function breakfast(dessert,drink,{location,restaurant}={}){
 
     console.log(dessert,drink,location,restaurant); // 蛋糕 啤酒 陕西 油泼面
     
 } 

 breakfast("蛋糕","啤酒",{location:"陕西",restaurant:"油泼面"});

6.【模板字符串 ${}

let dessert = "蛋糕",
    drink = "茶水";
    
//let breakfast = "今天早餐吃了" + dessert + "喝了" + drink;
// console.log(breakfast); // 今天早餐吃了蛋糕喝了茶水
 
let breakfast = `今天早餐吃的是${dessert},喝的是${drink}`;

console.log(breakfast); // 今天早餐吃的是蛋糕,喝的是茶水

7.【带标签的 模板字符串 tagged templates】

// 这里的 标签 其实就是 一个函数

let breakfast = kitchen`今天早餐吃的是${dessert},喝的是${drink}`;

function kitchen(strings,...values){
     // strings 是 模板字符串 里面原有的 部分字符串
     // values 就是 模板字符串里面的 插值
     //  strings & values 都是 数组 类型
     
     // console.log(strings);  // ['今天早餐吃的是' , ',喝的是 ' ] 
   	 // console.log(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); // 今天早餐吃的是蛋糕,喝的是茶水

8.【判断字符串 开头: startsWith() 结尾: endsWith() 包含:includes() 】

console.log(
     breakfast.startsWith("蛋糕"),  // false
     breakfast.endsWith("茶水"), // true
     breakfast.includes("蛋糕") // true
 )

9.【默认参数 】

function breakfast( dessert,drink) {
     return `${dessert} ${drink}`;
 }

 console.log(
      breakfast(), // 默认参数 undefined undefined 
      breakfast("甜甜圈","啤酒") // 甜甜圈 啤酒
 )

10.【... Spread 展开操作符】

let fruit = [ "蛋糕","苹果","香蕉"],
     foods = ["茶水",...fruit]
     
 console.log(fruit); // [ '蛋糕', '苹果', '香蕉' ]
 console.log(...fruit); // 蛋糕 苹果 香蕉 , 直接输出数组的值,相当于 展开数组
 console.log(foods); // [ '茶水', '蛋糕', '苹果', '香蕉' ]

11【 ...Rest 剩余操作符 ,】一般会用在函数的参数里面

function breakfast(dessert,drink,...foods){

    console.log(dessert,drink,foods) // 除了 dessert和drink 参数,剩余的参数存放在 foods里面
    
 }

 breakfast("蛋糕","啤酒","苹果","香蕉"); // 蛋糕 啤酒 [ '苹果', '香蕉' ]

12.【函数的 name 属性】

// 函数声明方式 创建一个函数
 function breakfast(){
     // ...body
 }
 // 匿名函数 方式
 let edit = function(){
     // ... body
 }

 let del = function superdel(){
     //...body
 }
 
 console.log(
     breakfast.name, // breakfast  函数声明的名字
     edit.name, // edit 变量的名字
     del.name // superdel 函数声明的名字,而不是变量的名字,因为函数声明的优先级更高一些
 )

13.【 箭头函数】

// 单个参数 
 let breakfast = dessert => dessert ; 
 console.log(breakfast("蛋糕")) //蛋糕
 
// 多个参数
 let breakfast = (dessert,drink)=>{
    return dessert + drink;
 }
 
console.log(breakfast("蛋糕","啤酒")); // 蛋糕啤酒

14.【对象表达式】

// 当对象的属性名和定义属性值的变量名字相同,直接写属性名就可以了
 let dessert = "蛋糕", drink = "啤酒";
 let food = {
     dessert,
     drink,
     // breakfast:function(){}
     breakfast(){}
 }
 
 console.log(food); // { dessert: '蛋糕', drink: '啤酒', breakfast: [Function: breakfast] }

15.【对象属性名】

let food= {};
 let drink = "code drink";
 
 food.dessert = "蛋糕";
 food['hot drink'] = "咖啡";
 food[drink] = "啤酒"; 
 
 console.log(food); // { dessert: '蛋糕', 'hot drink': '咖啡', 'code drink': '啤酒' }

16.【对比两个值是否相等】 通常 == 或者 === ,号可以使用 Object.is()

// 终端判断结果
// +0 == -0  // true
// +0 === -0 // true
// NaN == NaN // false

Object.is(NaN,NaN) // true
Object.is(-0,+0) // false

17.【Object.assign() 】 把一个对象里面的属性复制到另一个对象

let breakfast = {};
 Object.assign(
     breakfast,
    { drink:"啤酒"}
 )

 console.log(breakfast); // { drink: '啤酒' }

18.【Object.setPrototypeOf() 】 设置对象的 prototype

let breakfast = {
    getDessert(){
        return "蛋糕";
    }
}
let dinner = {
    getDrink(){
        return "啤酒";
    }
}
let sunday = Object.create(breakfast);
 console.log(sunday.getDessert()); // 蛋糕
 console.log(Object.getPrototypeOf(sunday) === breakfast); // true

 Object.setPrototypeOf(sunday,dinner);
 console.log(sunday.getDrink()); // 啤酒
 console.log(Object.getPrototypeOf(sunday) === breakfast); // false
 console.log(Object.getPrototypeOf(sunday) === dinner); // true

19.【__proto__】可以得到 或者 设置 对象的 prototype

let sunday = {
     __proto__:breakfast
 }
 console.log(sunday.getDessert()); // 蛋糕
 console.log(Object.getPrototypeOf(sunday) == breakfast); //true
 
 sunday.__proto__  = dinner;
 console.log(sunday.getDrink()); // 啤酒
 console.log(Object.getPrototypeOf(sunday) == dinner); // true

20.【 super 】继承原有对象的属性

let sunday = {
    __proto__:breakfast,
    // 重写 breafast 里面的 getDessert()方法,覆盖原有的
    getDessert(){
        return super.getDessert() + "苹果派" 
    }
}

console.log(sunday.getDessert()); // 蛋糕苹果派