是否存在变量提升
var声明的变量存在变量提升,可以在声明之前调用,值为undefined
let和const不存在变量提升,所声明的变量一定要在声明后使用,否则报ReferenceError错
是否存在暂时性死区
let和const存在暂时性死区,只要块级作用域存在let命令,所声明的变量就‘绑定’(binding)这个区域,不再受 外部影响
是否允许重复声明变量
var允许重复声明变量。
let和const在同一作用域不允许重复声明变量。
是否存在块级作用域
var不存在块级作用域
let和const存在块级作用域
是否修改声明过的变量
var和let可以
const声明一个只读的常量,一旦声明,常量的值不能改变
箭头函数里没有自己的this,这改变了以往JS函数中最让人难以理解的this运行机制。
箭头函数内的this指向的是函数定义时所在的对象,而不是函数执行时所在的对象。
箭头函数是匿名函数,不能作为构造函数,不能使用new
箭头函数相当于匿名函数,并且简化了函数定义。箭头函数有两种格式:一种只包含一个表达式,{…}和return都省略掉。还有一种可以包含多条语句,这个时候就不能省略{…}和return。
箭头函数内没有arguments,可以用展开运算符…解决
箭头函数的this,始终指向父级上下文(箭头函数的this取决于定义位置父级的上下文,跟使用位置没关系,普通函数this指向调用的那个对象)
箭头函数不能通过call() 、 apply() 、bind()方法直接修改它的this指向。(call、aaply、bind会默认忽略第一个参数,但是可以正常传参)
箭头函数没有原型属性
变量作用域就是一个变量可以使用的范围
一段代码起作用的范围 分为全局作用域和局部作用域
函数内部使用变量,先从当前函数查找,如果找不到,则继续向父级查找,如果还找不到继续往上一级查找,最后找到window对象,如果还找不到,则报错提示变量不存在,这种链条关系就是作用域链
js中首先有一个最外层的作用域,全局作用域
js中可以通过函数来创建一个独立作用域称为函数作用域,函数可以嵌套,所以作用域也可以嵌套;
es6新增了块级作用域{} 比如if{} for{}
es6作用域,只适用于const,let
一个变量在当前作用域没有定义,但被使用了
向上级作用域,一层一层依次寻找,直达找到为止
如果全局作用域都没找到,则报错 xx is not defined
变量提升(预解析)
var声明的变量,function声明的函数存在变量提升 let const 不会变量提升
javascript中声明并定义一个变量时,会把声明提前
函数声明也会把整个函数提升到作用域的最上面
函数表达式不能变量提升,只会把声明的 var fn 提升到作用域的最顶端
函数嵌套函数 当内部函数访问外部函数变量时 就产生了闭包
函数嵌套函数
内部函数可以直接访问外部函数的内部变量或参数
变量或参数不会被垃圾回收机制回收
函数作为参数被传递
函数作为返回值被返回
实际应用(隐藏数据):普通用户只能通过get、set等api对数据进行查看和更改等操作,没法对data直接更改,达到所谓隐藏数据的效果;jquery就利用了这一特性,必须调用$.ajax()才能访问内部属性方法。
封装功能时(需要使用私有的属性和方法),函数防抖、函数节流、单例模式
避免全局变量污染
私有成员的存在
变量长期驻扎在内存中
常驻内存
增大内存的使用量
使用不当 会造成内存泄漏
浏览器的 Javascript 具有自动垃圾回收机制(GC:Garbage Collecation),也就是说,执行环境会负责管理代码执行过程中使用的内存
原理:垃圾收集器会定期(周期性)找出那些不在继续使用的变量,然后释放其内存
程序的运行需要内存。只要程序提出要求,操作系统或者运行时(runtime)就必须供给内存
对于持续运行的服务进程(daemon),必须及时释放不再用到的内存。否则,内存占用越来越高,轻则影响系统性能,重则导致进程崩溃。
不再用到的内存,没有及时释放,就叫做内存泄漏(memory leak)
全局变量引起的内存泄露
闭包引起的内存泄露:慎用闭包
dom清空或删除时,事件未清除导致的内存泄漏
循环引用带来的内存泄露
解构赋值就是从目标对象或数组中提取自己想要的变量。最常用的场景是:element-ui,vant-ui按需引入,请求接口返回数据,提取想要数据。
减少代码量,减少代码冗余
可以属性和方法的共用
减少了内存使用
原型继承:父类的实例作为子类的原型
借用构造函数继承:在子类中使用call方法调用父类的方法并将父类的this改成子类的this
组合继承:既能调用父类的实例属性又能调用父类的原型属性
使用class构造一个父类
使用class构造一个子类,并使用extends实现继承,super指向父类的原型对象
实例化对象
class相当于es5中的构造函数
class中定义方法是前后不能加function,全部都定义在class的prototype属性中
class中只能定义方法不能定义对象变量等
class默认是严格模式
在子类中调用extends方法可以调用父类的属性,用eat调用父类的方法
原型链继承
原型链继承的基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法
借用构造函数
在子类型的构造函数中调用超类型构造函数
组合继承
原型式继承
寄生式继承
寄生组合继承
父类的实例作为子类的原型
可以使用父类原型上的方法,不可以传递参数
在子类内使用call()调用父类方法,将父类this的指向修改为子类的this,相当于把实列属性复制一份给子类
可以父类实例中的方法,可以传递参数。不能使用父类原型的方法
即在子类中使用call()方法,再把父类的实例作为子类的原型
既能调用父类实例的方法,又能调用父类原型的方法,还可以传递参数