javascr*pt对象的创建相对java 怎样去创建了"类"*以及实例化对象

  由于javascr*pt没有java那么多基本类型,同时也没有提供class这个东西,那么我们想实现javascr*pt的对象创建应该怎么办呢,我简单地从w3c提供的课件中提取了一下几种方法:

一.工厂模式

  说白了就是类似于c语言中的定义一个函数,然后给一个struct的各个属性复制,再返回这个struct。代码示例:

    fu*ct*o* perso*(*ame,a*e,sex){

      var o=*ew Object();

      o.*ame=*ame;

      o.a*e=a*e;

      o.sex=sex;

      o.sayName=fu*ct*o*(){

        alert(th*s.*ame);

      }

      retur* o;

    }

    var perso*1=*ew perso*("wa**ke",21,"Male");

    var perso*2=*ew perso*("*aoyua*yua*",34,"Female");

    perso*1.sayName();//wa**ke

    perso*2.sayName();//*aoyua*yua*

这种办法的确可以创建多个类似的对象,但是个人觉得类似c++中struct与class的区别,它没有解决对象的识别问题。

二.构造函数模式:

  其实在javascr*pt中,构造函数和普通函数没什么区别,起码从格式上看来都是一样的,所谓的构造函数无非就是在调用的时候前面加了个*ew,比如上节的var perso*1=*ew perso*(...)。在这种模式中,通过使用th*s,将属性和方法赋值给th*s对象,这样就不用retur*了,同时一般构造函数的首字母会大写的(这也算是个认为加上去的区别吧)。示例代码:

  fu*ct*o* *erso*(*ame,a*e,sex){

    th*s.*ame=*ame;

    th*s.a*e=a*e;

    th*s.sex=sex;

    th*s.sayName=fu*ct*o*(){...};

  }

  var perso*1=*ew&*bsp;*erso*("wa**ke",21,"Male");

  var perso*2=*ew&*bsp;*erso*("*aoyua*yua*",34,"Female");

这种模式就可以进行类型检测了,通常用**sta*ceof方法:

  alert(perso*1 **sta*ceof Object);//true

  alert(perso*1 **sta*ceof *erso*);//true

缺陷:每次实例化一个对象,里面的方法都会被重新创建一遍,浪费资源,所以我们可以想着把它放到全局变量中(但是只被个别方法调用,作用域为全局显得名不副实)。修改如下:

  

 fu*ct*o* *erso*(*ame,a*e,sex){

    th*s.*ame=*ame;

    th*s.a*e=a*e;

    th*s.sex=sex;

    th*s.sayName=sayName;

  }

  fu*ct*o* sayName(){

    alert(th*s.*ame);

  }

使用这种方法的话,会出现太多的全局函数了,所以我们会在下一种这种方法中解决这个问题。

三.原型模式:

  了解什么是prototype(原型):w3c给的概念有点绕,我通俗点说:prototype就是“一个给类的对象添加方法的方法”,假如有你把一个对象a赋值为一个对象b,假如对对象a进行拓展的话,那么对象b也能访问a新定义的属性或方法。可能这两句话还是不能理解,那就看代码以及w3c上提供的图(看了图就会恍然大悟了)。

  fu*ct*o* *erso*(){

  }

  *erso*.prototype={

    *ame:"N*cholas",

    a*e:29,

    job:"Soft E****eer",

    sayName:fu*ct*o*(){

      alert(th*s.*ame);

    }

  };

  var perso*1=*ew *erso*();

  var perso*2=*ew *erso*();

  alert(perso*1.sayName==perso*2.sayName();//true

<*m* src="http://*ma*es.c**tblo*.com/blo*/591889/201312/16111049-6499f7d7739f46449e46f5afeb42506f.p**" alt="" />

&*bsp;

备注:1.原型的动态性(开头也提到过,对a的拓展)即可以先创建实例再修改原型也可以:

  var perso*=*ew *erso*();

  *erso*.prototype.saySth(){

    alert("* wa*t to sleep");

  };

  perso*.saySth();//* wa*t to sleep

虽然修改可以立即在所有对象实例中反映过来,但是要重写所有的原型对象就会不一样了。

2.原生对象的原型--不光自定义类型方面原型很重要,所有原生的引用类型都是采用这种模式创建的,所以我们可以自己添加一些方法:

  Str***.prototype.startW*th=fu*ct*o*(text){

    retur* th*s.**dexof(text)==0;

  };

  var ms*="Hello,World";

  alert(ms*.startW*th("Hello");//true

3.原型模式的缺陷:共享的本性,特别是array。

  fu*ct*o* *erso*(){

  }

  *erso*.prototype={

    *ame:"N*cholas",

    a*e:29,

    job:"Soft E****eer",

    fr*e*ds:["wa**ke","yua*yua*"],

    sayName:fu*ct*o*(){

      alert(th*s.*ame);

    }

  }

  var perso*1=*ew *erso*();

  var perso*2=*ew *erso*();

  perso*1.fr*e*ds.push("x*j**p***");

  alert(perso*1.fr*e*ds);//wa**ke,yua*yua*,x*j**p***

  alert(perso*2.fr*e*ds);//wa**ke,yua*yua*,x*j**p***

四.组合

  现在只要解决了原型模式中共享造成的缺陷,那么就比较完美了,我们注意到第二条的构造函数模式了吗?下面就是最常见的创建自定义类型的方式:

  fu*ct*o* *erso*(*ame,a*e,sex){

    th*s.*ame=*ame;

    th*s.a*e=a*e;

    th*s.sex=sex;

    th*s.fr*e*ds=["obama","kobe"];

  }

  *erso*.prototype={

    co*structor:*erso*,

    sayName:fu*ct*o*(){}

  }

实例属性都是在构造函数中定义,而共享的属性和方法都是在原型模式中定义。

五.其他构造方式:

  偶尔会用到,大家可以自己查一下:动态原型模式,寄生构造方式 ,稳妥构造函数模式

以上只是个人的一点总结,欢迎大家阅读并交流!

&*bsp;

&*bsp;

原文地址:https://www.cnblogs.com/wangkeustc/p/3476417.html