类型声明
const
常量的标识符 建议通过const声明的常量用大写的字母表示,以便于我们区分代码中的变量
const LIMIT=10
特点:
- 不允许重复的声明和赋值 es5中实现const 则利用的是defineProperty()函数实现
Object.defineProperty(window,'LIMIT',{
value:12,
whiteable:false
})
- 块级作用域
if(true){
console.log(aa)//报错
const aa=12
console.log(aa)//12
}
console.log(aa)//报错
console.log(window.aa)//undefinde const是块级作用域 不会挂在到window下
//es5 变量提升的问题
if(true){
var aa=12
console.log(aa)//12
}
console.log(aa)//12
- 无变量提升
console.log(aa) //not definde
const aa='12'
//es5
console.log(aa)//12
var aa=12
let
let用于声明变量 特点:
- 不能重复声明
let aa=12
let aa=31//报错
- 块级作用域 不会出现变量提升
var aa=12
if(true){
aa=12 //报错 因为通过let 声明的变量在{}的作用域中存在暂时的死区
let aa
}
//es5
if(true){
console.log(aa)//undefinde
var aa=12
}
通常我们在使用的时候用const去声明引用类型的数据(对象,数组),const 声明引用类型的数据的原理在于其声明引用类型的地址指向不能改变,其中内部的结构可以改变
const test={name:'小花',age:12}
test.sex='女'
const arr=[12,23,34,45]
arr[1]=90
通过Object.freeze()可以实现对象个根层级属性不可改变
const test={
name:"小花",
age:12,
sex:'女',
other:{
first:"1",
seconde:"2"
}
}
//
Object.freeze(test)
test.name='小红'//这样修改不成功
test.other.first=13//这个可以修改 如果不让其修改 就用递归让嵌套的引用属性都用//Object.freeze()进行包裹
//递归实现所有属性不可编辑
function deepFreeze(obj){
Object.freeze(obj)
for(let key in obj){
//判断属性是否存在
if(obj.hasOwnproperty(key)&&typeOf obj[key]==='object'){
deepFreeze(obj[key])
}
}
}
箭头函数
箭头函数几种用法
//多个参数
const test=(a,b)=>{
return a+b
}
//多个参数简写
const test=(a,b)=>a+b
//一个参数
const test=(a)=>{}
//没有参数
const test=()=>{}
特点:
- this的指向永远指向定义时候的上层this,而不是调用时候的this
// ES6
const obj2 = {
teacher: '测试',
leader: '测试leader',
getLeader: function() {
console.log('teacher is:', this.teacher); //这个this是动态的 谁调用指向谁
return this.teacher;
},
getLeader: () => {
console.log('leader is:', this.leader); //这里的this指向的就是obj2所处的this环境 很明显此时this指向的是window对象
return this.leader;
}
}
obj2.getLeader()//undefined 因为此时的this指向的是window,应为箭头函数没有自己的this因此也不能使用bind call apply 去进行this的改变
obj2.getLeader()//打印出来的是 //测试leader
- 箭头函数没有constructor 因此也不能进行实例化
- 箭头函数也不能构造原型方法 其本质的原因就是this指向的问题,指向window
- 箭头函数也不能获取argument对象,因为argument不存在
class 类 面向对象
///es5的面向对象
function Person(name,age){
this.name=name
this.age=age
}
//方法 挂载在原型上
Person.prototype.eat=function(){
////其他
}
///es6的面向对象
class Person{
constructor(name,age){
this.name=name
this.age=age
}
eat(){
////其他
}
}
class的类型
class的类型则是function
console.log(typeOf Person) //function
class的prototype
class 的prototype本质是一个function但是constructor 是一个class
属性的定义
class Person{
constructor(name,age){
this.name=name
this.age=age
}
get name(){
return this.name
}
set name(val){
this.name=val
}
eat(){
////其他
}
}
属性定义的作用:
- 控制属性只读(修改不会报错,修改不成功) 对于某些情况下我们不需要其他人或者第三方去改变不能改变我们的属性值 或者只能通过我们的方式逻辑去修改值的话就可以用属性定义的方式(底层core的思想)
class Person{
constructor(name,age){
this._name=name
this.age=age
}
get name(){
return this._name
}
set name(val){
//对于改变name的时候做的一系列操作
this._name=newval
}
}
- 创建私有变量 其实创建私有变量的逻辑很简单就是通过闭包的方式对外抛内部定义的变量,这种变量也无法修改
class Person{
constructor(name,age){
this._name=name
this.age=age
let aa=12
this.getaa=()=>{
return aa
}
}
}
//另一种定义私有变量的
class Course {
#course = 'es6';
constructor(teacher, course) {
this._teacher = teacher;
}
get course() {
return this.#course;
}
set course(val) {
if(val) {
this.#course = val;
}
}
}
静态的属性或者方法
在es6 中我们是通过static的关键字去定义 属性或者方法为静态的属性或者方法,通常解决全局变量的问题
es5中的静态方法
function Person(){
}
//静态方法
Person.eat=function(){
}
//es6
class Person{
static eat(){
}
}
///调用
Person.eat()
继承
es5 的原型链继承
function Person(name,age){
this.name=name
this.age=age
}
Person.prototype.eat=function(){
}
functon Student(name,age){
Course.call(this,name,age)
}
//继承父类
//让子类的原型链指向父类的原型链
Student.prototype=Person.Prototype
//还有一种常见的方式,也是运用了原型链的方式
// new Person().__proto___=Person.Prototype
Student.prototype.lear=function(){}
es6的继承
class Person{
constructor(name,age){
this.name=name
this.age=age
}
eat(){
}
}
class Student extend Person{
constructor(name,age){
super(name,age)
}
}
解构
- 数组解构
//以从数组中提取值,按照对应位置,对变量赋值。
let [a, b, c,d] = [1, 2, 3];
- 对象解构
const zhaowa = {
teacher: {
name: '',
age: 30
},
leader: '',
name: 'es6'
}
// 别名
const {
teacher: {
name,
age
},
leader,
name: className
} = zhaowa;
- 形参解构
const sum = arr => {
let res = 0;
arr.forEach(each => {
res += each;
})
}
const sum = ([a, b, c]) => {
return a + b + c;
};
//结合初始值
const course = ({ teacher, leader, course = 'zhaowa' }) => {
// ……
}
course({
teacher: 'yy',
leader: 'ss'
})
- 返回值解构
const getCourse = () => {
return {
teacher: '',
leader: ''
}
}
const { teacher, leader } = getCourse();
- 变量交换
let a = 1;
let b = 2;
[b, a] = [a, b];
- json处理
const json = '{"teacher": "yy", "leader": "xk"}';
const obj = JSON.parse(json);
const {
teacher,
leader
} = JSON.parse(json);
7.字符串解构
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"
//字符串length属性解构
const {length:len}='test'
len//4
8.数值或者boolean解耦 无论是数值还是boolean解构的时候都会转成对象
let {toString: s} = 123;
s === Number.prototype.toString // true
let {toString: s} = true;
s === Boolean.prototype.toString // true
因为数值或者boolean的包装对象都有一个toString的属性 因此s可以取到值