一、闭包
1.概念:
- 定义在一个函数内部的函数(函数嵌套函数),闭包就是将函数内部和函数外部连接起来的一座桥梁。
- 在一个自执行函数中套用另外一个函数。
2.特点:
- 里面的小空间不销毁,延长了变量的生命周期
- 变量声明在函数内部,保护了私有的变量不被全局污染,让数据更安全
- 让全局可以访问到局部的数据了
3.缺点:
- 常驻内存,增加内存使用量。
- 内存不销毁,容易造成内存的溢出/内存泄漏。
闭包实现tab切换
//获取元素
const aBtn = document.querySelectorAll('button');
const aItem = document.querySelectorAll('.item');
let timer = null;
for (var i = 0; i < aBtn.length; i++) {
//i:0 - aBtn.length
(function(i) {
//i:0 - aBtn.length
aBtn[i].onmouseover = function() {
timer = setTimeout(() => {
for (var j = 0; j < aBtn.length; j++) {
aBtn[j].className = '';
aItem[j].style.display = 'none';
}
aBtn[i].className = 'active';
aItem[i].style.display = 'block';
}, 400);
};
aBtn[i].onmouseout = function() {
clearTimeout(timer);
}
})(i);
}
二、原型链
概念:
实例对象与原型(prototype)的连接,依靠__proto__内置属性实现的。
// 每一个对象都有一个__proto__。
// JS在创建对象的时候,都有一个叫做__proto__的内置属性,用于指向创建它的函数对象的原型prototype。
三、继承
子类继承父类,但不影响父类。
方法继承(原型继承)
方法继承1 - 浅拷贝:将prototype下面的方法一一赋值给子类。
for(var i in Person.prototype){
Student.prototype[i] = Person.prototype[i]
}
Object.assign(Student.prototype, Person.prototype)
方法继承2 - 原型继承:将父类的实例给子类的原型。
Student.prototype = new Person(); //不但继承了Person.prototype的方法,同时修改了子类的构造函数体。
Student.prototype.constructor = Student; //重新设置子类的构造函数体。
ES6中的继承:
extends关键字:
Class 可以通过extends关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多。
super关键字:
子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用super方法,子类就得不到this对象。
class Animal{
constructor(name){
this.name = name;
}
dong(){
console.log("能动");
}
}
class Dog extends Animal{
constructor(name){
super(name);
this.jiao = "汪汪";
}
}
var ergou = new Dog("狗");
console.log(ergou); // Dog {name: "狗", jiao: "汪汪"}
ergou.dong(); // 能动