1,let、var
1.1 var
ES5中创建变量使用var,var关键字定义的变量有两个作用域,全局作用域和局部作用域
-  
全局变量:在全局范围内定义的变量
 -  
局部变量:在函数内部定义的变量 比如循环,判断语法块
 
1.2let
ES6中创建变量用let,let关键字定义的变量有三个作用域,全局作用域、局部作用域、块级作用域
-  
块级作用域:在语法块中定义的变量
 
1.3let和var两点主要区别的总结:
-  
var在统一作用域可以重复定义同一个变量,let不行
 -  
var 没有块级作用域,在循环中定义的变量都是全局的,会相互覆盖,let在循环中定义的变量都是独立的,互不影响
 
举例1:let在同一作用域不能重复定义同一个变量,var可以
let在语法块中定义的变量,只能在语法块中使用
if (true) {
    var d = 4;
    let e = 5;
}
console.log(d); //4
console.log(e); //undefined 
举例2:let在循环中定义的变量都是独立的,不会相互覆盖,var没有块级作用域,在循环中定义的变量都是全局的,会被相互覆盖
for (var i = 0; i < 5; i++) {
    var count = i;
    console.log(count); //0,1,2,3,4
    setTimeout(function() {
        console.log(count); //444444
    }, 100);
    let number = i;
    setTimeout(() => {
        console.log(number); //0,1,2,3,4
    }, 200);
}
console.log(i); //undefined 循环变量i建议使用let定义,在循环之外无法调用,也就避免了全局作用域污染 
-  
在循环中使用var定义变量,这个变量是全局变量,每次循环的count共享一个作用域,所以下次循环的count把上次循环的count替换掉,循环之后,全局只有一个count,值为4
 -  
在循环中使用let定义变量,这个变量是块级变量,每次循环都会在一个新的块级作用域中定义一个独立的块级变量number,循环结束后,就有5各块级变量number,他们的值给不相同,互不影响
 
举例3:var定义变量可以重复定义,但是let不能再同一个作用域里边重复定义变量
var count1 = 100; var count1 = 200; console.log(count1);  let number1 = 100; let number1 = 200; console.log(number1);//编辑器直接爆红线
1.4在循环中添加计时器或事件绑定,需要保留每次循环的变量值的方案
有以下两种解决方案:
-  
1.使用let定义块级变量
 
for (let i = 0; i < 5; i++) {
    setTimeout(() => {
        console.log(i);
    }, 300);
} 
-  
2.使用闭包,保持count局部变量
 
function outter(count) {
    return function inner() {
        console.log(count);
    }
}
for (var i = 0; i < 5; i++) {
    setTimeout(outter(i), 300);
} 
2,const定义常量
使用const定义的是常量,它只能/必须初始化一次,所谓初始化就是用const定义的常量必须有初始值。初始化之后不可修改,不能重新赋值。
2.1const定义值类型数据,绝对不能改
const c = 3; c = 4; //TypeError: Assignment to constant variable.报错
2.2 const定义引用类型数据,数据内容(对象/数组 中的数据)可以修改,引用类型本身(内存地址)不能改
const student = {
    name: "zhangsan",
    age: 20
}
student.name = "lisi"
student.sex = "男" 
3,模板字符串
字符串模板用于字符串拼接,由于模板字符串支持换行,所以可以用来渲染字符串
var year = 2020,
    month = 4,
    day = 20;
var htmlStr = `
    <ul>
        <li>${year}年</li>
        <li>${month}月</li>
        <li>${day}日</li>
    </ul>
`
console.log(htmlStr);
console.log((`${year}年${month}月${day}日`)); 
4,箭头函数
-  
普通的函数不能转化为箭头函数,只有匿名函数可以转化为箭头函数
 -  
var add = function() {} var add = () => {} 
4.2 箭头函数的this指向
在事件函数、计时器、异步回调函数中可以保留this上下文(全局作用域)指向
举例1:箭头函数的this指向
// 在node环境下,this默认指向空对象
console.log(1, this); //{}
// 可以修改这个对象
this.name = "全局zhangsan"
console.log(2, this); //{ name: '全局zhangsan' }
// setTimeout会把this指向修改为 Timeout对象
setTimeout(function() {
    console.log(3, this); //Timeout对象
}, 1000)
// 箭头函数会保留this的上下文指向,使this指向和setTimeout外部的this值相同
setTimeout(() => {
    console.log(4, this); //{ name: '全局zhangsan' }
}, 1000); 
4.3 箭头函数的简化
-  
如果箭头函数只有一个参数,可以省略小括号
 -  
如果箭头函数的函数体只有一句return返回,return和{}可同时省略
 -  
在对象中箭头函数可以直接省略箭头和冒号
 
var add = count => { return ++count };
var add = count => ++count;
// 箭头函数在对象中的写法,对象中的函数有以下三种写法
var student = {
    name: "张三",
    age: 20,
    // ES5函数的写法,其中的this使当前对象
    eat: function() {
        console.log(this.name + "吃饭");
    },
    // ES6箭头函数写法,其中的this是对象上下文(全局作用域)指向
    drink: () => {
        console.log(this.name + "喝水");
    },
    // 简化写法,其中this的指向还是当前对象
    sleep() {
        console.log(this.name + "睡觉");
    }
};
student.eat()
student.drink()
student.sleep() 
5,数组、对象的解构
5.1数组的解构
一般,使用数组中的数据要使用索引取值。
5.1.1数组解构使用变量读取数组中的数据
注意:由于数据有顺序,在解构时,一般前边变量个数和数组中的数据个数要一一对应
var array = [1, 2, 3, 4]; let [count1, count2, count3, count4] = array console.log(count3);//3
5.1.2 使用 ...语法解构数组中的一部分数据
let [num1, ...num2] = array; console.log(num2);//[2,3,4]
5.2数组的赋值
使用 ...数组赋值
var array = [1, 2, 3, 4]; var array2 = ["a", "b", "c"]; console.log(...array2);//a b c array.push(...array2); console.log(array);//[1,2,3,4,'a','b','c']
5.3 对象的解构
如果要获取一个对象中的某个字段,直接用对象打点调用即可,也可以使用对象解构写法获取某个字段值
var student = {
    name: "张三",
    age: 12,
    sex: "男",
    phone: "110"
};
console.log(student.phone);//110
var { age, sex } = student;
console.log(age, sex); //12 男 
注意:由于对象中的数据没有顺序,所以对象解构无需把所有字段都写上,可以按需求定义变量读取对象中的某一个或几个字段即可,但必须保证变量名和字段名相同
5.4 对象的赋值
var obj1 = {
    age: 20
}
var obj2 = {
    sex: true
}
console.log({...obj1, ...obj2 });//{ age: 20, sex: true } 
6,函数参数的默认值
6.1ES5
-  
ES5中js函数定义时有两个参数,调用时就必须传入至少两个参数
 -  
如果传入的实参少于形参的个数,为防止错误,可以给形参设置默认值
 -  
设置默认值使用 || 设置
 
function add2(a, b) {
    a = a || 0;
    b = b || 0;
    console.log(a + b);
}
add2() //0
add2(3) //3
add2(3, 4) //7
add2(3, 4, 5) //7 
-  
如果参数个数不确定,通过arguments字段获取所有参数数组
 
function add4() {
    // arguments是一个类数组,里边放了所有参数
    console.log(arguments, Array.from(arguments));
}
add4() //{} []
add4(3) //{ '0': 3}   [ 3]
add4(3, 4) //{ '0': 3, '1': 4}   [ 3, 4]
add4(3, 4, 5) //{ '0': 3, '1': 4, '2': 5 }  [ 3, 4, 5 ] 
6.2 ES6
ES6通过形参 ...array获取参数数组,形参array是所有参数所在的数组
function add5(...array) {
    // 形参array是所有参数所在的数组
    console.log(array);
}
add5() // []
add5(3) // [ 3]
add5(3, 4) // [ 3, 4]
add5(3, 4, 5) // [ 3, 4, 5 ] 
7,对象的自变量创建
js中有两种创建对象的方法:1,使用new关键字创建对象 2,使用字面量创建对象 3,在ES6中字面量创建对象,如果属性名和属性值一样就可省略不写属性名
let date = new Date();
let obj = { name: "张三" }; 
let name = "zhangsan";
let age = 20
let obj1 = {
    name: "张三",
    age: 20,
    sex: "男"
};
// 此时字段name和age已经提前好了变量,所以在对象中可直接引用变量值
let obj2 = {
    name: name,
    age: age,
    sex: "男"
};
// 此时发现,对象中字段名 和 值得变量名一样,ES6中规定可简化 name:name ----> name
let obj3 = {
    name,
    age,
    sex: "男"
};
console.log(obj3);//{ name: 'zhangsan', age: 20, sex: '男' } 
8,类的创建与继承
8.1 类的创建
类需要用到class关键字创建,格式为 class 类名 {},类中含有构造函数和属性,在类中创建属性用到this。
function People(name) {
    // this是构造函数创建的对象,name是对象的属性
    this.name = name
}
var zhangsan = new People("张三")
console.log(zhangsan);//People { name: '张三' } 
class Student {
    // constructor是类的构造器,相当于构造函数
    constructor(name) {
        this.name = name;
        this.study = function() {
            console.log(this.name + "在学习");
        }
    }
}
var xiaoming = new Student("小明");
console.log(xiaoming);
xiaoming.study(); //小明在学习 
8.2 类的继承
继承::把一个类(父类)的属性和方法传递给另一个类(子类),可以让另一个类(子类)的对象调用
class Pupil extends Student {
    constructor(name) {
        // super指父类的构造器,通过父类的构造器创建子类对象
        super(name)
    }
}
var a = new Pupil("李四")
console.log(a);//Pupil { name: '李四', study: [Function (anonymous)] }
a.study()//李四在学习









