# 五.建造者模式

前言

建造者模式(Builder Pattern)将⼀个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创 建它们,最后构建成该复杂对象

# 1.代码

function CreateJsPerson(name: string, age: string) {
  //浏览器默认创建的对象囧事我们的实列p1 -->this
  this.name = name
  this.age = age
  this.writeJs = function () {
    console.log("my name is " + this.name)
  }
}
var p1 = new CreateJsPerson("sdaf", "12")
p1.writeJs()

//构造函数模式的目的就是为了创造一个自定义类,并创建这个类的实列
//构造函数模式和工厂模式的区别
//1、执行的时候
//普通函数执行 -->createJsPerson()
//构造函数模式 -->new CreateJsPerson()  通过new执行后我们的CreateJsPerson就是一个类了
//而函数执行的返回值(p1)就是CreateJsPerson这个类的一个实列

//创建一个数组:
var ary = [] //字面量方式
var ary = new Array() //实列创建方式
//不管哪一种方式ary都是Array这个类的一个实列

//js中所有的类都是函数数据类型的,它通过new执行变成了一个类,但是它本身也是一个普通的函数
//js中所有的实列都是对象数据类型的

//2、在函数代码执行的时候
//相同:都是形成一个私有的作用域,然后形参赋值-->预解释-->代码从上到下执行(类和普通函数一样,也有普通函数的一面)
//不同:在代码执行之前,不用自己再手动的创建对象了,浏览器会默认创建一个对象,数据类型的值(这个对象其实就是我们当前类的一个实列)
//接下来代码从上到下执行,以当前的实列为执行主体(this代表当前实列),然后分别把属性名和属性值赋值给当前的实列
//最后浏览器会默认的把创建的实列返回

//this的指向
//1、只执行函数的this是window
//2、在构造函数中this是当前类的实列

//创建出的实列是不同的方法

/*
 *构造函数模式(扩展)
 *
 *
 */
function Fn() {
  this.x = 100
  this.getX = function () {
    //this-->需要看getX执行的时候才知道
    console.log(this.x)
  }
}
var f1 = new Fn()
f1.getX() //this是x=100
var ss = f1.getX
ss() //方法中的this是window
//1、在构造函数模式中new Fn()执行,如果不需要传递参数的话,后面的小括号可以省略
//2、this的问题:在类中出现的this.xxx=xxx中的this都是当前类的实列,而某一个属性值(方法),方法中的this需要看方法执行的时候,前面是否有""."才能知道this是谁

function Fn() {
  var num = 10
  this.x = 100
  this.getX = function () {
    //this-->需要看getX执行的时候才知道
    console.log(this.x)
  }
}
var f1 = new Fn()
console.log(f1.num) //undefined
//3、类有普通函数的一面,当函数执行的时候,var num其实只是当前形成的私有作用域中的私有变量而已,他和我们的fn这个实例没有任何关系,只有this。xxx=xx才相当于给f1z这个实例增加私有属性和方法,才和我们的f1有关系

function Fn() {
  this.x = 100
  this.getX = function () {
    console.log(this.x)
  }
  return { name: "sfa" }
}
var f1 = new Fn()
console.log(f1)
//4、在构造函数模式中,浏览器会默认的把我们的实列返回(返回的是一个对象数据类型的值);如果我们自己动手写了return返回
//返回的是一个基本数据类型值,当前的实列是不变的,例如return 10
//返回的是一个引用数据类型的值,当前的实列会被自己返回的值给替换掉,例如return {name:"asdf"},我们的f1就不在是fn的实例了,而是对象{name:"asd"}

function Fn() {
  this.x = 100
  this.getX = function () {
    console.log(this.x)
  }
}
var f1 = new Fn()
//5、检测某一个实例是否属于这个类-->instanceof
console.log(f1 instanceof Fn) //-->true
console.log(f1 instanceof Array) //-->false
console.log(f1 instanceof Object) //-->true 因为所有的实列都是对象数据类型的,而每一个对象数据类型都是Object这个内置类的一个实列,所以f1也是他的一个实列
//对于检测数据类型来说,typeof有自己的局限性,不能细分Object下的对象、数组、正则
var a = []
console.log(a instanceof Array)

function Fn() {
  this.x = 100
  this.getX = function () {
    console.log(this.x)
  }
}
var f1 = new Fn()
var f2 = new Fn()
//6、f1和f2都是Fn这个类的一个实列,都拥有x和getX两个属性,但是这两个属性是各自的私有属性,所以:
//console.log(f1.getX === f2.getX)//false

//in:检测某一个属性是否属于这个对象 arrt in object 不管是私有属性还是公有属性,只要存在,用in来检测都是true
console.log("getX" in f1)
//hasOwnProperty:用来检测某一个属性是否为这个对象的“私有属性”,这个方法只能检测私有属性
console.log(f1.hasOwnProperty("getX")) //--true

//思考:检测某一个属性是否为该对象的“公有属性”hasPubProperty
function hasPubProperty(obj, attr) {
  return attr in obj && !obj.hasOwnProperty(attr)
}
console.log(hasPubProperty(f1, "getX"))

//7、isPrototypeOf  一个对象是否存在另一个对象的原型上
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120

# 2.应⽤场景及案例

  • 需要⽣成的产品对象有复杂的内部结构,这些产品对象通常包含多个成员属性。
  • 需要⽣成的产品对象的属性相互依赖,需要指定其⽣成顺序。
  • 隔离复杂对象的创建和使⽤,并使得相同的创建过程可以创建不同的产品