创建对象的模式除了工厂模式。 构造函数模式。 原型模式还有其他几种模式。
一。 构造函数模式加原型模式
这种模式可以简单的理解为。构造函数模式用来创建实例属性。而原型模式用于创建共享的属性和方法。这样的好处在每个实例属性都有属于自己的属性。又有共享的属性和方法。 很大程度上节约了内存。而且这种模式还支持构造函数传参。这种模式也是目前为止用的最广泛认可度最高的一种模式。
function Person(name, age, city) {
this.name = name;
this.age = age;
this.city = city;
this.like = ["java", 'python']
}
Person.prototype = {
constructor:Person,
tall:179,
getName:function () {
return this.name
}
}
let a = new Person("小张" , 24, "成都");
let b = new Person("小王",27,'兰州');
console.log(a)
console.log(b)
console.log(a.tall)
console.log(b.tall)
console.log(a.tall === b.tall)
console.log(a.getName())
console.log(b.getName())
console.log(a.getName === b.getName)
a.like.push("css")
console.log(a.like)
-----------------------------
console.log(b.like)Person { name: '小张', age: 24, city: '成都', like: [ 'java', 'python' ] }
Person { name: '小王', age: 27, city: '兰州', like: [ 'java', 'python' ] }
-----------------------------
179
179
true
-----------------------------
小张
小王
true
-----------------------------
[ 'java', 'python', 'css' ]
[ 'java', 'python' ]
二。动态原型模式
用单独的构造函数和原型来创建对象对于某些开发者来说难免有点奇怪。为了解决这一问题动态原型模式将有所得信息全部封装在构造函数中。在构造函数中初始化原型。 简单的说就是通过检查某个应该存在的方法是否有效来决定是否初始化原型。
function Person(name, age, city) {
this.name = name;
this.age = age;
this.city = city;
this.like = ["java", 'python']
if (typeof this.getName !=“function”){
Person.prototype.getName = function(){
return this.name
}
}
}
let a = new Person("小王",25,"成都")
console.log(a)
console.log(a.getName())
Person { name: '小王', age: 25, city: '成都', like: [ 'java', 'python' ] }
小王
注意:
- 只有getName()不存在的情况下才会添加原型。 而且这段代码只会在初始化函数的时候才会执行
function Person(name, age, city) {
this.name = name;
this.age = age;
this.city = city;
this.like = ["java", 'python']
if (typeof this.getName != "function"){
console.log("执行")
Person.prototype.getName = function(){
return this.name
}
}
}
let a = new Person("小王",25,"成都")
let b = new Person("小刘",24,"兰州")
执行
- 如果对原型做了修改会立即反应在所有实例属性上
function Person(name, age, city) {
this.name = name;
this.age = age;
this.city = city;
this.like = ["java", 'python']
if (typeof this.getName != "function"){
Person.prototype.getName = function(){
return this.name
}
}
}
let a = new Person("小王",25,"成都")
let b = new Person("小刘",24,"兰州")
Person.prototype.tall = 100
console.log(a.tall)
console.log(b.tall)
100
100
三。寄生构造模式
这种模式的思想就是创建一个函数,该函数的作用是封装创建该函数的代码。然后返回新的对象。 从表面上看其就是一个构造函数
function Person(name,age,tall) {
let obj = new Object();
obj.name = name;
obj.age = age;
obj.tall = tall;
obj.getName = function () {
return this.name
}
return obj
}
let a = new Person("小王" , 23, 178)
console.log(a)
{ name: '小王', age: 23, tall: 178, getName: [Function] }
这种方法除了使用new操作符把函数当成构造函数以外, 其他创建对象的方法是与工厂模式是一样的。 构造函数在不返回值的情况下默认返回新的对象实例。
function Person(name,age,tall) {
let obj = new Object();
obj.name = name;
obj.age = age;
obj.tall = tall;
obj.getName = function () {
return this.name
}
}
let a = new Person("小王" , 23, 178)
console.log(a)
Person {}
由此我们发现在构造函数末尾添加一个return语句后。回重写调用构造函数的返回值。可以简单的理解为从一个新的空实例对象变成了我们想要创建的对象。
function Person(name,age,tall) {
let obj = new Object();
obj.name = name;
obj.age = age;
obj.tall = tall;
obj.getName = function () {
return this.name
}
return obj
}
let a = new Person("小王" , 23, 178)
console.log(a)
{ name: '小王', age: 23, tall: 178, getName: [Function] }
这种模式可以在特殊的情况下为对象创建特殊的构造函数。 假如要创建一个具有特殊方法的数组。 由于不能修改Array构造函数。 所以可以使用这种模式。
function Person() {
let arr = new Array()
arr.push(...arguments)
arr.getName = function(){
return this.join("@")
}
return arr
}
let a = new Person("小王" , 23, 178)
console.log(a)
console.log(a.getName())
[ '小王', 23, 178, getName: [Function] ]
小王@23@178
这样以来也就意味着只有通过Person实例化的对象才会有getName这个方法。 而通过原生的构造函数创建的对象是不具有这个方法的,要明确指出的是。 返回的对象与构造函数或者与构造函数的原型是没有关系的。
四。稳妥构造函数模式
所谓稳妥对象。就是没有公共属性。而且其方法不能使用this中的对象。稳妥构造函数模式遵循寄生构造函数的模式。 不同之处在于 新建实例对象的方式不能使用this对象。 不使用new操作符调用构造函数。
function Person(name,age,tall) {
let obj = new Object()
obj.getName = function () {
return name
}
return obj
}
let a = Person("小王" , 23 , 178)
console.log(a)
{ getName: [Function] }
这种方式只能通过方法访问属性。无法通过其他方式访问属性。 即上面的访问name属性必须使用getName访问。否则是没法访问的。
function Person(name,age,tall) {
let obj = new Object()
obj.getName = function () {
return name
}
return obj
}
let a = Person("小王" , 23 , 178)
console.log(a)
console.log(a.getName())
console.log(a.name)
{ getName: [Function] }
小王
undefined