1.继承
继承 是类与类之间的关系
子类继承父类子类就拥有父类的属性和方法
1.JS中没有类,但是可以通过构造函数模拟类,然后通过原型来实现继承
父类
//人类-父类
function Person(){
this.name 'jack'
this.age 20
}
Person.prototype ={
constructor:Person,
//手动设置constructor:指向构造函数
say:function(){
console.log('说话')
}
}
子类
//学生-子类
function Student(){
this.num=1081//学生学号
}
Student.prototype={
constructor:Student,
//读书
readBook:function(){
console.log('学生读书)
}
}
构造函数继承
继承父类构造函数属性和方法
//学生-子类
function Student(){
Person.call(this)//构造函数继承,继承父类构造函数属性和方法
this.num=1001字生学号
}
原型拷贝继承
继承父类原型对象上公共的属性和方法
//拷贝继承,继承父类原型对象上公共的属性和方法
for(let key in Person.prototype){
Student.prototype[key]= Person.prototype[key]
}
2.ES6 的类与继承
class类名{
//构造函数
constructor(name){
this.name=name
}
//方法
say(){}
}
·es6的继承很容易,而且是固定语法
//下面表示造一个Student类,继承自Person类
class Student extends Person{
constructor (){
//必须在constructor里面执行一下super()完成继承
super()
}
}
·这样就继承成功了
ES6语法
创建对象>类class
//人类
class Person{
constructor(name,age){
this.name = name
this.age = age
}
say(){
console.log(this.name,"在说话")
}
}
//学生类
class Student extends Person{
constructor(name, age ,num){
super(name,age)// super表示调用父类构造函数
this.num = num
}
readBook(){
console.log("学号是" ,this.num,"的学生在读书")
}
}
let s1 = new Student( "jack ",23,1081)
s1.say()
console.log(s1.name,s1.age,s1.num)
2.闭包
函数的两个阶段
- 定义阶段
- 调用阶段
函数执行空间
当js引擎解析到fn函数定义时,
=>在堆区域开辟一块存储空间,将函数体内代码以字符串形式存储到堆区域
=>在栈区域存储fn函数变量,并将堆区域存储空间地址赋值给fn
function fn(){
let num = 100
console.log ( 'fn函数' , num)
*当执行函数调用语句fn()时,
=>根据fn找到堆区域函数体代码,复制一份到调用栈区域,
=>执行调用栈函数体代码,执行完毕销毁调用栈区域
fn()
不销毁的函数执行空间
当js引擎解析到fn函数定义时,
=>在堆区域开辟一块存储空间,将函数体内代码以字符串形式存储到堆区域
=>在栈区域存储fn函数变量,并将堆区域存储空间地址赋值给fn
function fn(){
let num = 100
console.log( 'fn函数' , num)
return {}
}
当执行函数调用语句fn()时,*
=>根据fn找到堆区域函数体代码,复制一份到调用栈区域,
=>执行调用栈函数体代码,
=>函数体代码返回一个复杂数据类型,赋值给变量f
=>f引用函数体复杂数据类型对象,调用栈空间不会销毁
let f = fn()
了解闭包
闭包条件:
1.有一个A函数,在A函数内部返回一个B函数
2.在B函数内部,访问A函数私有变量
3.在A函数外部,有一个变量引用返回的B函数
function A() {
let num = 106
//1.A函数内部返回一个B函数(显示)
return function B() {
console.log(num)//2.B函数内部,访间A函数私有变量num
}
}
let f = A()// 3变量f引用返回的B函数
闭包形成后:
- 生成一个不会被销毁的函数执行空间,
- 内部函数叫做外部函数的闭包函数
闭包概念
-
有一个A函数,在A函数内部返回一个B函数
-
在B函数内部,访问A函数内部私有变量
-
在A函数外部,有一个变量引用返回的B函数
-
有函数嵌套,内层函数被返回
-
内层函数访问外层函数私有变量
-
返回的内层函数被引用
闭包三种写法
1.显示写法
function A() {
let num = 100
//1.A函数内部返回一个B函数(显示)
return function B() {
console.log(num)//2.B函数内部,访问A函数私有变量num
}
}
let f = A()3.变量f引用返回的B函数
2.隐式写法
let B // 3.在A函数外部,有一个变量引用返回的B函数
function A() {
let num = 280
//1.A函数内部返回一个B函数(隐示)
B= function () {
console.log(num)//2.B函数内部,访间A函数私有变量num
}
}
A()
B()
3.自调用写法
let x= (function (){
let num = 300
return function B(){
console.log(num)
}
})()
闭包的特点
-
作用域空间不销毁
优点: 因为不销毁,变量不会销毁,增加了变量的生命周期
缺点: 因为不销毁,会一直占用内存,多了以后就会导致内存溢出 -
可以利用闭包,在一个函数外部,访问函数内部的变量
优点: 可以在函数外部访问内部数据
缺点: 必须要时刻保持引用,导致函数执行栈不被销毁 -
保护私有变量
优点: 可以把一些变量放在函数里面,不会污染全局
缺点: 要利用闭包函数才能访问,不是很方便