本篇主要是简单回顾面向对象的编程。

# 封装

使用工厂模式进行封装

function createCat() {
  var obj = {};
  obj.name = name;
  obj.eat = function() {
    console.log(name + "eat something");
  };
  return obj;
}
var catA = createCat("xiaoA");
var catB = createCat("xiaoB");
var catC = createCat("xiaoC");
1
2
3
4
5
6
7
8
9
10
11

# 1. this 指向问题

详见👉👉👉JavaScript 中 this 到底指向谁

# 2. new 干了什么

详见👉👉👉JavaScript 中 this 到底指向谁

// 区分构造函数和一般函数的区别,一般构造函数首字母大写
function CreateCat(name){
    this.name=name
    this.eat=fucntion(){
        console.log('abc')
    }
}

// 在生命函数的时候,会自动创建一个prototype属性,这个叫原型,一般用来存放实例公用方法
CreateCat.prototype.eat=fucntion(something){
    console.log(this.name+'eat'+something)
}
var catA=new CreateCat=('xiaoA')
catA.eat('finish')
// 在js里规定,访问对象属性的时候,如果对象下面没有这个属性,则去它下面的__proto__去寻找,如果害没有就一直向下寻找知道没有__proto__为止
console.log(catA)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

以上执行结果:

# 继承

# 1.类式继承

问题:

    1. 这种方法不支持父构造函数带参数
    1. 父构造函数里的方法和属性都会编程共有属性
fucntion A(name){
    this.name=name
    this.list=[1,2,3,4]
}
A.prototype.getName=fucntion(){
    console.log(this.name)
}
function SubA(name){
    this.subName='sub'+this.name
}
SubA.prototype=new A()
// var sa1=new SubA('sa1')
// console.log(sa1.list,sal.name) // [1,2,3] undefined
/*
 执行 var sa1=new SubA('sa1'),做了什么?
 SubA.prototype=new A()->{
     name:undefined
     list:[1,2,3], 这里属性共享了
     __proto__:{
         getName:fn
         constructor...
     }
 }
*/
var sal=new SubA('sa1')
var sa2=new SubA('sa2')
A.prototype.getName=fucntion(){
    console.log('fixed getName')
}
A.prototype.newFn=fucntion(){
    console.log('fixed getName')
}
sa1.getName()
sa2.newFn()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

# 2.构造函数继承

问题:不能继承父构造函数的原型方法

fucntion A(name){
    this.name=name
    this.list=[1,2,3,4]
}
A.prototype.getName=fucntion(){
    console.log(this.name)// 这里漏掉了
}
fucntion SubA(name){
    A.call(this,name)
    this.subName='sub'+this.name
}
var sa1=new SubA('xiaoA')
console.log(sa1.list,sal.name)
sa1.getName()//报错,因为不能继承父构造函数的原型方法

/*
分析:漏掉了父构造函数的原型方法
 sa1= new SubA('xiaoA')->{
    __proto__:{constructor...},
    name:'xiaoA',
     list:[1,2,3],
    subName:'sub XiaoA'
 }
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 3.组合式继承

小问题:

    1. _proto里面的属性没有用
    1. 执行两次父构造函数
function A(name) {
  this.name = name;
  this.list = [1, 2, 3];
}
A.prototype.getName=function(){
    console.log(this.name)
}
fucntion SubA(name){
    A.call(this,name)
    this.subName='sub'+this.name
}
SubA.prototype=new A()
var sa1=new SubA('xiaoA')
console.log(sa1.name,sa1.subName)//xiaoA sub xiaoA
sa1.getName()//xiaoA

/*
 SubA.prototype=new A()->{
     name:undefined
     list:[1,2,3],
     __proto__:{
         getName:fn
     }
 }
 var sa1= new SubA('xiaoA')->{
    name:'xiaoA',
    list:[1,2,3],
    subName:'sub XiaoA',
    __proto__:{
    name:'xiaoA',
    list:[1,2,3],
    __proto__:{
        getName:fn
     }
    },
 }
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

# 4.寄生组合式继承

function A(name) {
  this.name = name;
  this.list = [1, 2, 3];
}
A.prototype.getName=function(){
    console.log(this.name)
}
fucntion SubA(name){
    A.call(this,name)
    this.subName='sub'+this.name
}
//问题出现在这: SubA.prototype=new A()
// 所以,改个写法
function inheritPrototype(subClass,superClass){
function F(){}
F.prototypr=superClass.prototype
subClass.prototype=new F()//这里导致constructor没有了,可以写回去
// subClass.prototype.constructor=subClass
}
inheritPrototype(subA,A)
var sa1=new SubA('xiaoA')
console.log(sa1.name,su1.subName)
sa1.getName()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 多态

  1. 定义:表示不同对象调用相同方法会产生不同结果 SubaA,SubB 都是继承 Base,但是调用同样 initial 方法会产生不同结果
fucntion Base(){}
Base.prototype.initial=fucntion(){
    this.init()
}
fucntion SubA(){
    this.init=fucntion(){
        console.log('subA init')
    }
}
fucntion SubB(){
    this.init=fucntion(){
        console.log('subB init')
    }
}
SubA.prototype=new Base()
SubB.prototype=new Base()
var subA=new SubA()
var subB=new SubB()
// SubaA,SubB 都是继承 Base,但是调用同样 initial 方法会产生不同结果
subA.initial() // subA init
subB.initial() // subB init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21