【JS系列】一起理解对象的7种创建方式(全)

栏目: 后端 · 发布时间: 5年前

内容简介:起初接触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
复制代码

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

操作系统基础教程

操作系统基础教程

戴维斯 / 第1版 (2006年7月1日) / 2006-7 / 34.0

这是一本关于操作系统基本原理的教科书,其最大特点就是从操作系统的分层概念出发,深入浅出地介绍了操作系统的基本概念和基本框架。本书可以作为高等院校非计算机专业相关课程的教材或参考书,也适合具有高中以上数学基础的计算机用户自学,还可以作为社会上计算机培训机构的教材。对所有想了解计算机操作系统,但又不需要或不打算深入学习其理论和实现细节的读者来说,本书是一本极具价值的入门指导书。一起来看看 《操作系统基础教程》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具