写出几种创建对象的方式,并说说他们的区别是什么? 【前端每日一题-26】

383 阅读2分钟

写出几种创建对象的方式,并说说他们的区别是什么?

初见此题,没啥好说的,脑海中闪现如下两种方式:

//字面量
var obj={};

//new实例化
var obj=new Object();

难度就这么点?百度查了查,发现自己理解得有些片面了。如下正解:

工厂方式创建对象

function createPerson(name) {
  var obj = {};
  obj.name = name;
  obj.sayMyname = function() {
    console.log(this.name);
  };
  return obj;
}

var p1 = createPerson('Mike');
p1.sayMyname(); //Mike

var p2 = createPerson('Lily');
p2.sayMyname(); //Lily

console.log(p1 instanceof createPerson); //false
console.log(p1 instanceof Object); //true
console.log(p2 instanceof createPerson); //false
console.log(p2 instanceof Object); //true

可以明显的感觉到,用此方法创建的对象无法识别创造者(这里的创造者全是Object)。

构造函数创建对象

当new去调用一个函数,这个时候函数中的this就是创建出来的对象,而且函数的返回值就是this(隐式返回)。

function createPerson(name) {
  this.name = name;
  this.sayMyname = function() {
    console.log(this.name);
  };
}

var p1 = new createPerson('Mike');
p1.sayMyname(); //Mike

var p2 = new createPerson('Lily');
p2.sayMyname(); //Lily

console.log(p1 instanceof createPerson); //true
console.log(p1 instanceof Object); //true
console.log(p2 instanceof createPerson); //true
console.log(p2 instanceof Object); //true

  • 优点:创建自定义函数意味着将来可以将它的实例标识为一种特定的类型,这是构造函数胜过工厂模式的地方
  • 缺点:每个方法都要在每个实例上重新创建一遍,如(sayMyname)

原型方式

function Person() {}

Person.prototype.name = 'Mike';

Person.prototype.sayMyname = function() {
  console.log(this.name);
};

var p1 = new Person();

p1.sayMyname();

  • 优点:可以让所有的对象实例共享它所包含的属性和方法
  • 缺点:原型中是所有属性都是共享的,但是实例一般都是要有自己的单独属性的。所以一般很少单独使用原型模式。

混合模型

  • 构造函数模式定义实例属性
  • 原型模式用于定义方法和共享的属性

function CreatePerson(name) {  this.name = name;}CreatePerson.prototype.sayMyname = function() {  console.log(this.name);};var p1 = new CreatePerson('Mike');p1.sayMyname();var p2 = new CreatePerson('Lily');p2.sayMyname();console.log(p1.sayMyname == p2.sayMyname); //true;原因:都是在原型下面,在内存中只存在一份,地址相同

属性是否要放在原型下面,就要看该属性是否是可变的,如果不是可变的,就可以放在原型下面,用来公用属性,可变的话放在构造函数下面。

参考:

js创建对象的5种方式