内容简介:起初接触JS时常见的简单地创建单个对象的方式有下面三种:以上三种方式在需要创建很多对象时会产生大量重复代码。显然需要更高效的方式,下面将介绍7种创建对象的方式工厂模式正是源自设计模式中的工厂模式,其基本思想:
起初接触JS时常见的简单地创建单个对象的方式有下面三种:
- 字面量,即var obj = {}
- new Object()
- Object.create()
以上三种方式在需要创建很多对象时会产生大量重复代码。显然需要更高效的方式,下面将介绍7种创建对象的方式
1. 工厂模式
1.1介绍
工厂模式正是源自 设计模式 中的工厂模式,其基本思想:
- 既然创建对象数量多时产生了大量重复代码
- 那就建一座工厂,通过工厂来创建加工
- 再返回创建好的对象
function createPerson(name, age) { var obj = new Object() obj.name = name obj.age = age obj.getName = function() { console.log(this.name) } return obj } var person1 = createPerson("AAA", 23) person1.getName() //AAA var person2 = createPerson("BBB", 30) person2.getName() //BBB 复制代码
1.2 优劣分析
- 解决了复用性的问题
- 但无法判断对象的类型(只知道是Objcet类型)
2. 构造函数模式
2.1 介绍
构造函数可创建特定类型的对象,类似Object和Array(实际上Object和Array本身就是构造函数)
function Person(name, age) { this.name = name this.age = age this.getName = function() { console.log(this.name) } } var person1 = new Person("AAA", 23) person1.getName() //AAA var person2 = new Person("BBB", 30) person2.getName() //BBB 复制代码
通过上面代码我们可以看到构造函数模式:
- 没有通过new Object()显示创建对象
- 属性和方法赋值给了this
- 无需return
2.2 构造函数也是函数
构造函数其实也是个函数,只是可以通过new调用来创建对象,当然也可作为普通函数使用
//作为普通函数使用 Person("CCC", 24) Person.getName() //CCC //在一个对象内调用 var obj = {} Person.call(obj, "DDD", 25) obj.getName() //DDD 复制代码
2.3 优劣分析
- 构造函数模式可以创建具体类型的对象
console.log(person1 instanceof Object) //true console.log(person1 instanceof Person) //true 复制代码
- 然而,构造函数中的方法是通用的,但每个实例都创建了一份属于自己的副本,造成内存浪费
console.log(person1.getName === person2.getName) //false 复制代码
3. 原型模式
3.1 介绍
原型模式即通过原型对象来实现属性和方法的共享,实例对象不会创建各自的副本
要理解原型模式,建议先理解透彻JS原型的概念——推荐阅读 一张图彻底KO原型链(prototype,__proto__)
function Person() { } Person.prototype.name = "AAA" Person.prototype.age = 23 Person.prototype.getName = function() { console.log(this.name) } var person1 = new Person() person1.getName() //AAA var person2 = new Person() person2.name = "BBB" person2.getName() //BBB console.log(person1.getName === person2.getName) //true 复制代码
然而原型对象也存在缺陷——对于引用类型的属性,各实例对象间指向同一个地址,某个对象修改了属性,所有对象都会受到影响
function Person() { } Person.prototype.arr = [1,2,3] Person.prototype.getArr = function() { console.log(this.arr) } var person1 = new Person() person1.arr.push(4) person1.getArr() //1,2,3,4 var person2 = new Person() person2.getArr() //1,2,3,4 person1.arr.push(5) person1.getArr() //1,2,3,4,5 person2.getArr() //1,2,3,4,5 复制代码
3.2 优劣分析
- 原型模式解决了属性和方法的共享问题
- 但对于引用类型的属性,各实例对象会相互影响
4. 组合模式
4.1介绍
组合模式即组合构造函数模式和原型模式,取二者之长,构造函数模式用于定义实例的属性,原型模式用于定义方法和共享的属性
function Person(name, age) { this.name = name this.age = age this.arr = [1,2,3] } Person.prototype = { getName: function() { console.log(this.name) } } var person1 = new Person("AAA", 23) person1.arr.push(4) console.log(person1.arr) //1,2,3,4 person1.getName() //AAA var person2 = new Person("BBB", 30) console.log(person2.arr) //1,2,3 person2.getName() //BBB 复制代码
4.2 优劣分析
- 组合模式是使用最广泛的一种模式,尤其在需要定义引用类型时
5. 动态原型模式
5.1 介绍
刚说组合模式是认可度最高的一种模式,然而也有些美中不足——每创建一个实例对象,原型方法都被重复定义一次
动态原型模式正是解决这个问题,使用if语句,使得原型方法只初始化一次
function Person(name, age) { this.name = name this.age = age //这里只需要使用任何一个方式或属性,不一定是getName,getAge也可以 //只要保证if里面的代码只执行一次就行 if(typeof this.getName !== 'function') { Person.prototype.getName = function() { console.log(this.name) } Person.prototype.getAge = function() { console.log(this.age) } } } var person = new Person("AAA", 23) person.getName() //AAA 复制代码
5.2 优劣分析
- 动态原型模式在组合模式的基础上做了优化,可谓更加完美
6. 寄生构造函数模式
6.1 介绍
长得和工厂模式一样,但调用方式和构造函数模式一样的模式,通过new调用构造函数,本该返回一个实例对象,但 return语句重写了构造函数的返回值
function Person(name, age) { var obj = new Object() obj.name = name obj.age = age obj.getName = function() { console.log(this.name) } return obj } var person = new Person("AAA", 23) person.getName() //AAA 复制代码
6.2 优劣分析
-
这种方式和工厂模式没什么不同,要说不同的就是通过new来调用,仍然存在工厂模式的无法判别对象类型的问题
-
个人认为这是一种多余的方式,复杂而不好理解,也没有什么应用场景
7. 稳妥构造函数模式
7.1 介绍
先介绍一个概念——稳妥对象:
- 没有公共属性
- 不使用this
- 不使用new调用
稳妥构造函数模式和工厂模式类似,但遵循稳妥对象的原则
function Person(name, age) { var obj = new Object() //getName是唯一读取name的方式 obj.getName = function() { console.log(name) } return obj } var person = Person("AAA", 23) person.name = "BBB" //无效 person.getName() //AAA 复制代码
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 《JavaScript面向对象精要》之三:理解对象
- 面向对象的程序设计之理解对象
- 深入理解Objective-C中实例、类对象、元类对象之间的关系
- Object 对象你真理解了吗?
- 深入理解Python面向对象的三大特性
- 深入理解多线程(三)—— Java的对象头
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。