(1)闭包:
闭包说的通俗一点就是打通了一条在函数外部访问函数内部作用域的通道。正常情况下函数外部是访问不到函数内部作用域变量的,
表象判断是不是闭包:函数嵌套函数,内部函数被return 内部函数调用外层函数的局部变量
优点:可以隔离作用域,不造成全局污染
缺点:由于闭包长期驻留内存,则长期这样会导致内存泄露,如何解决内存泄露:将暴露全外部的闭包变量置为null
适用场景:封装组件,for循环和定时器结合使用,for循环和dom事件结合.可以在性能优化的过程中,节流防抖函数的使用,导航栏获取下标的使用
(2) JS中的原型链的理解:
原型:
js中,万物皆对象,每一一个对象都拥有自己的属性,
js中怎么才能让多个对象共享一一个或多个方法呢?原型的出现就是为了解决这个问题。
在js中每个对象都有一 一个与它关联的对象,叫做原型对象
每次获取对象属性都是一次查询过程,在对象的自有属性中找不到就会去查找它的原型对象。
原型链:
原型连成一条链,js在查找属性过程中,如果在自有属性中找不到就会去原型对象中查找,
如果原型对象中还查不到,就回去原型对象的原型中查找,也就是按照原型链查找,
直到查找到原型链的顶端object
上面的代码看似没有问题,虽然父类的方法和属性都能够访问,但其实有一个潜在的问题,我再举个例子来说明这个问题
明明我只改变了 s1 的 play 属性,为什么 s2 也跟着变了呢?原因很简单,因为两个实例使用的是同一个原型对象。它们的内存空间是共享的,当一个发生变化的时候,另外一个也随之进行了变化,这就是使用原型链继承方式的一个缺点。
(3)继承
什么是继承: 通过【某种方式】让一个对象可以访问到另一个对象中的属性和方法
原型继承:让新实例的原型等于父类的实例
- 特点:1、实例可继承的属住有:实例的构造函数的属性,父类构造函数属性,父类原型的属性。(新实例不会继承父类实例的属性!)
缺点:1、新实例无法向父类构造函数传参。
2、继承单一。
3、所有新实例都会共享类实例的属性。( 原型上的属性是共享的,一个实例修改了原型属性,另一个实例的原型属性也会被修改!)
组合继承(前两种组合)
这种方式结合了前两种继承方式的优缺点,结合起来的继承,代码如下。
原型式继承
这里不得不提到的就是 ES5 里面的 Object.create 方法,这个方法接收两个参数:一是用作新对象原型的对象、二是为新对象定义额外属性的对象(可选参数)。
从上面的代码中可以看到,通过 Object.create 这个方法可以实现普通对象的继承,不仅仅能继承属性,同样也可以继承 getName 的方法
寄生组合式继承
结合第四种中提及的继承方式,解决普通对象的继承问题的 Object.create 方法,我们在前面这几种继承方式的优缺点基础上进行改造,得出了寄生组合式的继承方式,这也是所有继承方式里面相对最优的继承方式,代码如下。
通过这段代码可以看出来,这种寄生组合式继承方式,基本可以解决前几种继承方式的缺点,较好地实现了继承想要的结果,同时也减少了构造次数,减少了性能的开销
ES6 的 extends 关键字实现逻辑
我们可以利用 ES6 里的 extends 的语法糖,使用关键词很容易直接实现 JavaScript 的继承,但是如果想深入了解 extends 语法糖是怎么实现的,就得深入研究 extends 的底层逻辑。