1.闭包
1.1为什么需要闭包?
局部变量无法共享和长久保存,全局变量会造成变量污染,创建了一个既可以长久保存变量又不会造成变量污染的机制就是闭包。
1.2闭包的定义和使用
定义:从函数内部访问函数外部的作用域。
理解:返回值是一个函数,并且这个函数对局部变量存在引用关系,那我们就称它存在闭包。
// 使用:
function fn1() {
let a = 10
function fn2() {
a ++
console.log(a)
}
return fn2
}
fn1() //fn1的执行结果就是一个闭包
1.3 闭包的缺点
1.闭包的变量都被保存在内存中,内存消耗很大,滥用闭包,可能导致内存泄露
2.闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
2.JS的构造函数、原型、原型链是什么? 有什么作用?
2.1 构造函数
声明一个函数就可以是构造函数(但不能是箭头函数)
function Cat (name,color){
this.name = name
this.color = color
}
let mimi = new Cat ('wang',white) // new Cat() 就是一个构造函数
注意:
1.构造函数必须使用new 来调用
2.构造函数中无需使用return 默认将创建的对象返回
3.**构造函数中的this 就是新创建的对象**
2.2 new 实例化过程
1.创建新空对象
2.构造函数this指向新对象
3.执行构造函数代码
4.返回新对象
实例化:使用new调用构造函数创建 对象的过程
实例对象:调用构造函数创建出来的新对象
实例成员:实例对象上的属性 和方法
静态成员:构造函数的属性和方法 如:Math.PI Date.now()
2.3 原型
原型:js规定 每个构造函数都会有的prototype属性,它是一个对象
结论:
1.添加在 原型对象 上的属性和方法 ,所有当前构造函数创建的实例对象都可以访问
2.添加在 原型对象 上的this ,就是调用它方法的实例对象
例:给数组 添加 max方法
Array.prototype.max = function(){
//this 就是调用方法的 实例对象
return Math.max(...this)
}
let arr = [1,2,3,4]
arr.max() //在Array的原型上添加的方法,所有实例对象都可使用
2.4 constructor 属性
constructor 属性:是原型对象的一个属性,可以 快速找到 构造函数
语法:原型对象.constructor
使用场景:创建一个新的原型对象时,需要设置constructor属性
function Person(name){
this.name = name
}
// new 一个构造函数
let a = new Person('a')
console.log(a.constructor); // construction : Person
2.5 __proto__属性
__proto__属性:实例对象都有的属性,可以快速找到的原型对象
***等价于prototype
语法:实例对象.__proto__
***可以通过__proto__来添加共享的方法
function A(name){
this.name =name
}
A.prototype.aa = function(){
console.log('aaa');
}
let b = new A('b')
console.log(A.prototype === b.__proto__); // true
// 构造函数的原型对象 === 实例对象的 _proto_
b.__proto__.bbb = function(){
console.log('bbb');
}
b.bbb() // 可以调用
2.6原型链:
实例对象和原型对象,以及原型对象的原型对象组成的链式结构
使用场景:访问属性和方法改怎么查找
查找顺序:先在实例对象中找,再到原型对象中找,再到原型对象的原型对象中找, 一直到Object的原型对象中,再没有就是null
构造函数与原型对象的关系
2.7 原型继承
原型继承:通过原型来实现继承别人方法的效果
语法结构:子构造函数.prototype = new 父构造函数()
function Man() {}
function Women() {}
//使用字面量对象
let person = {
eyes: 2,
eat() {
console.log("我在吃饭");
},
};
//将person中的属性和方法赋值给构造函数
Man.prototype = person;
Women.prototype = person;
let jack = new Man();
let rose = new Women();
// 构造函数自己没有方法和属性 继承了原型对象上的方法和属性
jack.eat();
rose.eat();
console.log(jack.eyes,rose.eyes);
缺点:使用同一个对象 ,修改任何一个都会影响其他
2. 使用构造函数的实例对象来继承
function Car(name,id,price){
this.name = name
this.id = id
this.price = price
}
Car.prototype.run = function(){
console.log(`${this.name}在跑`);
// console.log(this);
}
Car.prototype.scrapped = function(){
console.log(`${this.name}报废了`);
}
function Robot (name,dian,price){
this.name =name
this.dian =dian
this.price = price
}
Robot.prototype.attack = function(){
console.log(`${this.name}在战斗`);
}
// 希望机器人继承汽车的方法
//机器人的原型对象 等于 汽车构造函数创建的实例对象
//机器人原型对象 继承 汽车的原型对象
Robot.prototype = new Car()
let wzt = new Robot('威震天',1,"???")
wzt.run()