首先,闭包是js作用域嵌套所形成的产物。闭包的形成,就是一个函数中返回一个子函数,在子函数中使用父函数的变量,在全局中调用子函数。
闭包的特点:1、变量的声明在函数内部,这个变量不会被函数外部覆盖,使变量私有化。2、函数内部的子函数的作用域不会被收 回,延长变量生命周期。但也容易造成内存的溢出。
闭包主要应用在设计模式中的单例模式,以及在循环中进行异步操作。
单例模式的主要作用就是让每一次实例出来的对象都是同一个,利用闭包每次使用的变量都是上一次的变量而不是最初的状态,可以通过判断返回目标对象。
循环中的异步操作,如果在异步操作中使用循环的变量,很容易造成所有变量都执行完了,然后所有异步使用的变量都是变量最后的结果。如果将异步操作放到一个单独的作用域中,就形成了闭包。
使用闭包,最主要是利用闭包中的作用域空间不被销毁,从而是变量不被销毁的特性,完成一些让变量持久化的操作。
闭包的作用: 正常函数执行完毕后,里面声明的变量被垃圾回收处理掉,但是闭包可以让作用域里的 变量,在函数执行完之后依旧保持没有被垃圾回收处理掉
继承:即通过一定的方式实现让某个类型A获取另外一个类型B的属性或方法。其中类型A称之为子类型,类型B称之为父类型或超类型。
1、原型继承
function Animal(){
this.name = "动物";
this.attribute = "宠物类";
}
var animal = new Animal(); // 实例化
function Dog(){
this.aaa= "wang";
}
Dog.prototype = animal; // 将Dog的原型赋值为Animal实例后的对象animal
var dog = new Dog();
console.log(dog.name); // 访问Dog对象的name属性
console.log(dog.attribute); // 访问Dog对象的attribute属性 继承到原型上的属性
缺点:原型上的属性是共享的,一个实例修改了原型属性,另一个实例的原型属性也会被修改!
2、通过构造函数继承
function Parent(name) {
this.name = name;
}
Parent.prototype.saiHi = function () {
console.log("hello")
}
//利用构造函数实现继承(利用上下文call)
function Child(name, age, gender) {
Parent.call(this, name) //重点
this.age = age;
this.gender = gender;
}
let child = new Child("张三", 20, "男")
console.log(child.name);// 张三
child.sayHi(); // Uncaught TypeError:child.sayHi is not a function
缺点:只能解决属性的继承,使用属性的值不重复,但是父级类别的方法不能继承
3、混合继承 (就是把原型和构造函数继承方式组合起来)
function Animal(){
this.name = "动物";
}
Animal.prototype.dong=function(){ // 将父类方法绑定到子类上
console.log("能动");
}
function Dog(){
Animal.call(this); // 将父类借用一下,并将函数的this原来是父类改变成子类
this.jiao = '汪汪';
}
Dog.prototype=new Animal();
var ergou = new Dog();
console.log(ergou.name); // 访问子类的name属性- 动物、
ergou.dong(); // 调用dong方法,也能访问了
4、es6 类的继承
class Animal{
constructor(name){
this.name = name;
}
dong(){
console.log("能动");
}
}
class Dog extends Animal{
constructor(name){
super(name);
this.eat = "eat";
}
}
var dog = new Dog("狗");
console.log(dog ); // Dog {name: "狗", eat : "eat"}
dog.dong(); // 能动
总结:继承就是让一个类拥有了一个类的属性和方法。