优秀的编程知识分享平台

网站首页 > 技术文章 正文

面试中你有被问到-javascript中有几种创建对象的方式吗?

nanyue 2024-08-25 10:34:40 技术文章 5 ℃

Javascript中,所有事物皆为对象!布尔型,数字型,字符串,日期,数学和正则表达式,数组,函数统统都是对象。所以,学好对象,走遍天下都不怕了!

对象是一种特殊的数据,有属性和方法。通过创建对象,可以代码共享构建出形形色色的实例,从而节省我们开发的时间。那如何创建一个对象呢?有以下四种:

  • 对象字面量(又称为直接量,原始方式)
  • 工厂模式(利用函数创建对象)
  • 构造函数模式(利用类创建对象)
  • 原型模式(利用函数的prototype创建对象)
  • 通过原型+构造函数的方式创建对象
  • 使用 Object.create() 方法
  • 使用 ES6 类

但不管是哪种方式,都万变不离其宗。用句大实话就是,对象就是一个大括号包裹着一些属性和一些方法的集合,无非就是是不是以函数的形式展示。



01

对象字面量


通过对象字面量创建对象有三种形式:

  • 第一种:{}

举例:

var person = {}
person.name = '前端晨话'
person.sex = '不详'
person.age = '无可奉告'
person.dreams = function() {
  console.log('只有远方!')
}


  • 第二种:new Object()

举例:

var person = new Object()
person.name = '前端晨话'
person.sex = '不详'
person.age = '无可奉告'
person.dreams = function() {
  console.log('只有远方!')
}


  • 第三种:直接定义

举例:

var person = {
   name: '前端晨话',
   sex: '不详',
   age: '无可奉告',
   dreams: function() {
     console.log('只有远方!')
   }
}

这三种方式大同小异,我一般习惯用第三种方式,因为简单。


小结:

这三种方式,对象中的方法都是独立的,不能共享。如果创建多个对象,代码冗余现象非常严重。



02

工厂模式


工厂模式是以函数的形式创建对象。

举例:

function person(name, sex, age) {
   var obj = new Object()
   obj.name = name
   obj.sex = sex
   obj.age = age
   obj.dreams = function() {
       console.log('只有远方!')
   }
   return obj
}
var per1 = person('前端晨话', '不详', '无可奉告')
var per2 = person('前端晨话1', '不详1', '无可奉告1')
console.log(per1.dreams === per2.dreams) //false

这种方式其实就是第一种方式加了一层函数的外壳,外加了一些参数,使其可以批量创建对象。无疑,这种方式可以减少代码的冗余。但是这不是完美的,还有一个问题:age这个变量,其实应该是Number类型,如果我不看源码,我是不知道的,在传参的时可能会因随心所欲而出问题。

有没有发现,per1.dreams和per2.dreams,是不相等的,意味着什么?意味着这个方法是不共享的,相同的方法会开辟不同的空间,会浪费空间。


小结:

  • 代码冗余现象有所缓解;
  • 对象属性类型未知,需要看源码;
  • 对象的方法是独立的,不能共享。

  • TIPS:
  • 工厂模式一定不要忘记最后要把对象return出去!



03

构造函数模式


构造函数一种特殊的函数,其名称的首字母是大写的,而普通函数名称的首字母小写。与第2种方式的区别就是,不用首先创建一个空对象,往空对象中添加属性和方法,最后再return出去。构造函数里的属性的前缀全部用this代替。this指向的是创建出来的实例。创建对象用new...。

举例:

function Person(name, sex, age) {
   this.name = name
   this.sex = sex
   this.age = age
   this.dreams = function() {
      console.log('只有远方!')
   }
}
var per1 = new Person('前端晨话', '不详', '无可奉告')
var per2 = new Person('前端晨话1', '不详1', '无可奉告1')
console.log(per1.constructor === per2.constructor) //true
console.log(per1.constructor === Person) //true
console.log(per1.dreams === per2.dreams) //false

new在执行时会完成以下四件事:

  1. 开辟新的空间存储当时对象;
  2. 构造函数中的this指向当前对象;
  3. 执行构造函数中的代码,为当前对象添加属性和方法;
  4. 返回新对象(所以构造函数中不需要return对象)


小结:

  • per1和per2同属于同一个constructor;
  • 构造函数里的方法是独立于每个对象的,所以构造函数里的方法不能共享。

相同的方法开辟不同的空间,会造成资源的浪费。



04

原型模式


在讲这种模式前需回顾一下原型链的知识。

  • 每个函数都有一个prototype属性,这个属性指向函数的原型对象;
  • 每个原型都有一个constructor属性,指向关联的构造函数;
  • _Proto _是每一个子对象(除null外)都会有的一个属性,指向该对象的原型

从上图可以看出来,Person.prototype相当于一个全局对象,只不过这个对象有些特殊,它是与构造函数相关联的。per1以及所有Person的实例都可以继承实例原型的属性或者说,都可以顺着_Proto _这个属性找到实例原型的属性和方法。


举例:

function Person() {}
Person.prototype.name = '前端晨话小号'
Person.prototype.sex = '不详'
Person.prototype.age = '无可奉告'
Person.prototype.dream = function() {
  console.log('只有远方!')
}
var per1 = new Person()
per1.dream()

小结:


一眼就看出来的缺点嘛!虽然方法可以共享,但是属性没有灵活性。一旦任何一个实例改变一个属性,所有实例的值都会改变,不符合预期。



05

原型+构造函数模式


顾名思义,这种模式结合了原型和构造函数。构造函数里添加属性,利用原型的原理,在原型里添加方法,使其能共享方法。

举例:

function Person(name, sex, age) {
   this.name = name
   this.sex = sex
   this.age = age
   
}
Person.prototype.dream = function() {
      console.log('只有远方!')
   }
var per1 = new Person('前端晨话小号', '不详', '无可奉告')
var per2 = new Person('前端晨话小号1', '不详1', '无可奉告1')
console.log(per1)
console.log(per1.dreams === per2.dreams) //true

小结:

确实是一个完美的解决方案,既解决了代码的冗余现象可以批量创建对象,又可以共享方法!赞!




06

Object.create()方法


Object.create()方法,是JavaScript内置 Object 对象的标准方法。通过Object.create()创建的对象是全局对象Object的实例。这个是对第1种方式的一个拓展。

比如想创建的对象2与之前创建过的对象1的结构等很相似,只是某些属性有些不同,那么对象2就可以以对象1为原型创建对象。

举例:

var person = {
   name: '前端晨话',
   sex: '不详',
   age: '无可奉告',
   dreams: function() {
      console.log('只有远方!')
   }
}
var per1 = Object.create(person)
var per2 = Object.create(person)
per1.name = '前端晨话小号'
per2.name = '前端晨话小号1'
console.log(per1)
console.log(per1.dreams === per2.dreams) //true


在控制台,我们可以看到:

为什么console.logg(per1)时,只能看到name的值?因为per1是基于person为原型创建的,其它没有变化的属性必然在其原型链上:

所以能输出per1.sex的属性。:)

小结:

方法是可以共享的噢!



07

ES6类


ES6引入了一种创建JavaScript对象的新语法-class语法。class主法没有给JavaScript添加新的逻辑,本质上是一种语法糖。但体感很好。

举例:

class Person {
  constructor(name, sex, age) {
     this.name = name
     this.sex = sex
     this.age = age


     this.dreams = function() {
      console.log('只有远方!')
     }
  }
}
var per1 = new Person('前端晨话', '不详', '无可奉告')
var per2 = new Person('前端晨话2', '不详2', '无可奉告2')




console.log(per1.constructor === per2.constructor) //true
console.log(per1.dreams === per2.dreams) //false

小结:

与传统的构造函数创建的对象一样,per1和per2就是Person的实例,方法并不是共享的。



最近发表
标签列表