Javascript---字面量创建对象、组合构造函数+原型模式、动态原型模式

本文是有关于创建对象实例的一些常见方法,字面量模式,组合构造函数+原型模式,动态原型模式

一、字面量方式

创建原型对象除了可以用构造函数,还可以使用字面量的方式。

两者的区别是,字面量创建的方式使用constructor属性不会指向实例,而会指向Object,构造函数创建的方式则相反。

function Box() {};

Box.prototype = {                                     //使用字面量的方式

       name:‘ wrx',

       age: 20,

       run: function () {

              returnthis.name + this.age + '运行中...';

       }

var box = new Box();

alert(box.constructor == Box);                           //false

alert(box.constructor == Object);                       //true

如果想让字面量方式的constructor指向实例对象,那么可以这么做:

Box.prototype = {

         constructor: Box,                                                   //直接强制指向即可

};

那么,字面量方式为什么 constructor会指向Object?

因为Box.prototype={};这种写法其实就是创建了一个新对象。而每创建一个对象,就会同时创建它prototype,这个对象也会自动获取constructor属性。所以,新对象的

constructor重写了Box原来的constructor,因此会指向新对象,那个新对象没有指定构造函数,那么就默认为Object。

原型的声明是有先后顺序的,所以,重写的原型会切断之前的原型。

function Box() {};

Box.prototype = {                                                               //原型被重写了

  constructor : Box,

  name : 'Lee',

  age : 100,

  run : function () {

            return this.name + this.age + '运行中...';

  }

};

var box1 = new Box();                                                       //在这里声明

alert(box1.run());                                        //Lee100运行中

             

Box.prototype = {

  name: 'Wang' 

  };                                                          //box只是最初声明的原型

var box2 = new Box();                                                       //在这里声明

alert(box2.name);                                              //Wang

alert(box2.age);                                               //undefined,因为原型被重写了

原型对象不仅仅可以在自定义对象的情况下使用,而ECMAScript内置的引用类型都可以使用这种方式,并且内置的引用类型本身也使用了原型。

alert(Array.prototype.sort);                                         //sort就是Array类型的原型方法

alert(String.prototype.substring);                              //substring就是String类型的原型方法

 

String.prototype.addstring = function () {                 //String类型添加一个方法

         returnthis + ',被添加了!';                                      //this代表调用的字符串

};

 

alert('Lee'.addstring());                                                  //Lee被添加了

注:尽管给原生的内置引用类型添加方法使用起来特别方便,但我们不推荐使用这种方法。因为它可能会导致命名冲突,不利于代码维护。

原型模式创建对象也有自己的缺点,它省略了构造函数传参初始化这一过程,带来的缺点就是初始化的值都是一致的。而原型最大的缺点就是它最大的优点,那就是共享。

function Box() {};

Box.prototype = {

         constructor: Box,

         name: 'Lee',

         age: 100,

         family: ['父亲', '母亲', '妹妹'],                          //添加了一个数组属性

         run: function () {

                   returnthis.name + this.age + this.family;

         }

};

var box1 = new Box();

alert(box1.run());                            //Lee100父亲母亲妹妹

box1.family.push('哥哥');                                              //在实例中添加'哥哥'

alert(box1.run());                           //Lee100父亲母亲妹妹哥哥

 

var box2 = new Box();

alert(box2.run());              // Lee100父亲母亲妹妹哥哥,共享带来的麻烦,也有'哥哥'

二、组合构造函数+原型模式

为了解决构造传参和共享问题,可以组合构造函数+原型模式:

function Box(name, age) {                                             //不共享的使用构造函数

         this.name= name;

         this.age= age;

         this.family = ['父亲', '母亲', '妹妹'];

};

Box.prototype = {                                                             //共享的使用原型模式

         constructor: Box,

         run: function () {

                   returnthis.name + this.age + this.family;

         }

};

这种混合模式很好的解决了传参和引用共享的大难题,是创建对象比较好的方法。

原型模式,不管你是否调用了原型中的共享方法,它都会初始化原型中的方法,并且在声明一个对象时,构造函数+原型部分让人感觉又很怪异,最好就是把构造函数和原型封装到一起。为了解决这个问题,我们可以使用动态原型模式。

三、动态原型模式

function Box(name ,age) {                                             //将所有信息封装到函数体内

         this.name= name;

         this.age= age;

                   if(typeof this.run != 'function') {                        //仅在第一次调用的初始化

                   Box.prototype.run= function () {

                            returnthis.name + this.age + '运行中...';

                   };

         }

}

当第一次调用构造函数时,run()方法发现不存在,然后初始化原型。当第二次调用,就不会初始化了,并且第二次创建新对象,原型也不会再初始化了。这样既得到了封装,又实现了原型方法共享,并且属性都保持独立。

注:使用动态原型模式,要注意一点,不可以再使用字面量的方式重写原型,因为会切断实例和新原型之间的联系。

四、其他方法

1.寄生构造函数:其实就是工厂模式+构造函数模式

function Box(name, age) {

         varobj = new Object();

         obj.name= name;

         obj.age= age;

         obj.run= function () {

                   returnthis.name + this.age + '运行中...';

         };

         returnobj;

}

var box1 = new Box('Lee', 100);

alert(box1.run());

 

var box2 = new Box('Jack', 200);

alert(box2.run());

2.稳妥构造函数:在一些安全的环境中,比如禁止使用this和new,这里的this是构造函数里不使用this,这里的new是在外部实例化构造函数时不使用new。

function Box(name , age) {

         varobj = new Object();

         obj.run= function () {

                   returnname + age + '运行中...';              //直接打印参数即可

         };

         returnobj;

}

var box = Box('Lee', 100);                                              //直接调用函数

alert(box.run());

注:寄生构造函数和稳妥构造函数较为少用,稍微了解即可!










  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值