JS对象创建的几种方式整理

js创建对象几种方式

第一种:Object构造函数创建

var Person = new Object();
Person.name = 'Nike';
Person.age = 29;

这行代码创建了Object引用类型的一个新实例,然后把实例保存在变量Person中。

第二种:使用对象字面量表示法

var Person = {};//相当于var Person = new Object();
var Person = {
 name:'Nike';
 age:29;  
}

对象字面量是对象定义的一种简写形式,目的在于简化创建包含大量属性的对象的过程。也就是说,第一种和第二种方式创建对象的方法其实都是一样的,只是写法上的区别不同

在介绍第三种的创建方法之前,我们应该要明白为什么还要用别的方法来创建对象,也就是第一种,第二种方法的缺点所在:**它们都是用了同一个接口创建很多对象,会产生大量的重复代码,就是如果你有100个对象,那你要输入100次很多相同的代码。**那我们有什么方法来避免过多的重复代码呢,就是把创建对象的过程封装在函数体内,通过函数的调用直接生成对象。

第三种:使用工厂模式创建对象

function createPerson(name,age,job){
 var o = new Object();
 o.name = name;
 o.age = age;
 o.job = job;
 o.sayName = function(){
  alert(this.name); 
 };
 return o; 
}
var person1 = createPerson('Nike',29,'teacher');
var person2 = createPerson('Arvin',20,'student');

在使用工厂模式创建对象的时候,我们都可以注意到,在createPerson函数中,返回的是一个对象。那么我们就无法判断返回的对象究竟是一个什么样的类型。于是就出现了第四种创建对象的模式。

第四种:使用构造函数创建对象

function Person(name,age,job){
 this.name = name;
 this.age = age;
 this.job = job;
 this.sayName = function(){
 alert(this.name);
 }; 
}
var person1 = new Person('Nike',29,'teacher');
var person2 = new Person('Arvin',20,'student');

对比工厂模式,我们可以发现以下区别:

1.没有显示地创建对象

2.直接将属性和方法赋给了this对象

3.没有return语句

4.终于可以识别的对象的类型。对于检测对象类型,我们应该使用instanceof操作符,我们来进行自主检测:

alert(person1 instanceof Object);//ture
alert(person1 instanceof Person);//ture
alert(person2 instanceof Object);//ture
alert(person2 instanceof Person);//ture

同时我们也应该明白,按照惯例,构造函数始终要应该以一个大写字母开头,而非构造函数则应该以一个小写字母开头。

那么构造函数确实挺好用的,但是它也有它的缺点:

就是每个方法都要在每个实例上重新创建一遍,方法指的就是我们在对象里面定义的函数。如果方法的数量很多,就会占用很多不必要的内存。于是出现了第五种创建对象的方法

第五种:原型创建对象模式

function Person(){}
Person.prototype.name = 'Nike';
Person.prototype.age = 20;
Person.prototype.jbo = 'teacher';
Person.prototype.sayName = function(){
 alert(this.name);
};
var person1 = new Person();
person1.sayName();

使用原型创建对象的方式,可以让所有对象实例共享它所包含的属性和方法。

如果是使用原型创建对象模式,请看下面代码:

function Person(){}
Person.prototype.name = 'Nike';
Person.prototype.age = 20;
Person.prototype.jbo = 'teacher';
Person.prototype.sayName = function(){
 alert(this.name);
};
var person1 = new Person();
var person2 = new Person();
person1.name ='Greg';
alert(person1.name); //'Greg' --来自实例
alert(person2.name); //'Nike' --来自原型

当为对象实例添加一个属性时,这个属性就会屏蔽原型对象中保存的同名属性。

这时候我们就可以使用构造函数模式与原型模式结合的方式,构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性

第六种:组合使用构造函数模式和原型模式

function Person(name,age,job){
 this.name =name;
 this.age = age;
 this.job = job;
}
Person.prototype = {
 constructor:Person,
 sayName: function(){
 alert(this.name);
 };
}
var person1 = new Person('Nike',20,'teacher');

第七种:动态原型模式
这种模式主要是将所有信息都封装在了构造函数里,因为在组合构造函数模式和原型模式中,构造函数和原型模式是独立的,有些开发人员会感到很困惑,因此,这种模式也是为了解决这个问题,通过在构造函数中初始化初始化原型,又保持了同时使用构造函数和原型的优点,换句话说,就是可以通过在构造函数中,检查某个应该存在的方法是否有效,来决定是否需要初始化原型

function Person(name, age) {
    this.name = name;
    this.age = age;
    if(typeof this.sayName != "function") {
        Person.prototype.sayName = function() {
            console.log(this.name);
        }
    }
}

var person1 = new Person("Nicholas", 29);
person1.sayName();  // Nicholas

第八种:寄生构造函数模式
这种模式其实和工厂模式很像,除了使用new操作符并把使用的包装函数叫做构造函数之外,和工厂模式可以说是一模一样的,这种模式的基本思想是创建一个函数,该函数的作用仅仅是封装创建对象的代码,然后再返回新创建的对象

function Person(name, age) {
  var o = new Object();
  o.name = name;
  o.age = age;
  o.sayName = function() {
      console.log(this.name);
  }
  return o;
}

var person1 = new Person("Nicholas", 29);
person1.sayName();  //  Nicholas

寄生构造函数模式和工厂模式真的是很像,那么既然有了工厂模式,为什么还要有寄生构造函数模式呢?其实这个模式主要是用来给js原生的构造函数定义一些新的方法,我们可以看下面这个例子

function SpecialArray() {
    var values = new Array();
    values.push.apply(values, argumens);
    values.toPipedString = function() {
        return this.join("|");
    }
    return values;
}

var colors = new SpecialArray("red","blue");
console.log(colors.toPipedString());  //  red|blue

从上面这个例子我们可以看到,我们在构造函数里面创建了一个新的数组,然后通过push方法初始化这个数组,并且又给数组的实例添加了一个toPipedString方法,并且将所创建的数组返回,因此呢,当我们通过new创建了SpecialArray实例时,其实就得到增加了新方法的数组实例啦,就可以在这个实例上使用我们添加的新的方法toPipedString

第九种:稳妥构造函数模式
在说这种模式之前,要先说一下稳妥对象,稳妥对象就是指没有公共属性,而且其方法也不引用this的对象,稳妥对象最适合在一些安全的环境中,或者防止数据被其他应用程序改动时使用,稳妥构造函数模式遵循与寄生构造函数类似的模式,但是还是有下面的不同,第一个是新创建的对象实例方法不引用this,第二个是不使用new操作符调用构造函数

function Person(name, age) {
    var o = new Object();
    _name = name;
    _age = age;
    o.sayName = function() {
        return _name;
    }
    return o;
}

var person1 = Person("Nicholas", 29);
person1.sayName();  //  Nicholas

在上面这个例子中,我们在构造函数中创建了一个对象后,可以继续添加一些私有的变量和函数,要修改这些私有的变量和函数,只能通过创建的对象的方法进行访问,这里在对象上创建的方法其实可以看作就是公有方法,比如说这里的_name和_age就是私有变量,而对象o的sayName方法就是访问私有变量的公有方法了,这里除了调用sayName()方法外,没有其它方法可以访问其数据成员

第十种:es6中创建对象的方法

class Person {
   constructor(name, age) {
       this.name = name;
       this.age = age;
   }
   sayName() {
       console.log(this.name);
   }
}

var person1 = new Person("Nicholas", 29);
person1.sayName();  //  Nicholas

上面这个例子其实就是组合构造函数模式和原型模式的改写,其中,constructor属性直接指向类本身,该方法会默认返回实例对象,在里面定义的属性和方法都是实例本身具有的方法,不是其它实例共享的,而像sayName方法就是定义在原型上的方法了,是所有实例一起共享的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值