【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
复制代码

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

查看所有标签

猜你喜欢:

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

入侵的艺术

入侵的艺术

Kevin D.Mitnick、William L.Simon / 袁月杨、谢衡 / 清华大学 / 2007-1 / 39.00元

《入侵的艺术》中四个志同道合的伙伴使用口袋大小的计算机在拉斯维加斯大把挣钱。一个无聊的加拿大小伙子居然能够非法访问南部的一家银行。几个年轻人被拉登的恐怖分子征召去攻击Lockheed Martin公司和防御信息系统网络。   [精彩试读一]   [精彩试读二]一起来看看 《入侵的艺术》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

URL 编码/解码
URL 编码/解码

URL 编码/解码

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具