我们可以利用JavaScript的语法特征,以类的思想来创建对象。
方法一:原始方法
代码如下:
- <script>
- var obj = new Object();
- obj.name = "Kitty";//为对象增加属性
- obj.age = 21;
- obj.showName = function () {//为对象添加方法
- console.log(this.name);
- };
- obj.showAge = function(){
- console.log(this.age);
- };
- obj.showName();
- obj.showAge();
- </script>
这种方法通过new关键字生成一个对象,然后根据JavaScript是动态语言的特性来添加属性和方法,构造一个对象。其中的this表示调用该方法的对象。
这种方法的问题在于:如果我们需要多次创建对象,那么就需要重复代码多次,不利于代码的复用。
方法二:工厂方法
代码如下:
- <script>
- function createObj(){
- var obj = new Object();//创建对象
- obj.name = "Kitty";
- obj.age = "21";
- obj.showName = function () {
- console.log(this.name);
- };
- obj.showAge = function () {
- console.log(this.age);
- };
- return obj;
- }
- var obj1 = createObj();
- var obj2 = createObj();
- obj1.showName();
- obj1.showAge();
- obj2.showName();
- obj2.showAge();
- </script>
改进代码如下:
- <script>
- function createObj(name,age){
- var obj = new Object();
- obj.name = name;
- obj.age = age;
- obj.showName = function () {
- console.log(this.name);
- };
- obj.showAge = function(){
- console.log(this.age);
- };
- return obj;
- }
- var obj1 = new createObj("Kitty","21");
- var obj2 = new createObj("Luo","22");
- obj1.showName();//Kitty
- obj1.showAge();//21
- obj2.showName();//luo
- obj2.showAge();//22
- </script>
改进代码如下:
- <script>
- function createObj(name,age){
- var obj = new Object();
- obj.name = name;
- obj.age = age;
- obj.showName = showName;
- obj.showAge = showAge;
- return obj;
- }
- function showName(){
- console.log(this.name);
- }
- function showAge(){
- console.log(this.age);
- }
- var obj1 = new createObj("Kitty","21");
- var obj2 = new createObj("Luo","22");
- obj1.showName();//Kitty
- obj1.showAge();//21
- obj2.showName();//luo
- obj2.showAge();//22
- </script>
方法三:构造函数方法
代码如下:
- <script>
- function Person(name,age){
- this.name = name;
- this.age = age;
- this.showName = function () {
- console.log(this.name);
- };
- this.showAge = function () {
- console.log(this.age);
- };
- }
- var obj1 = new Person("Kitty","21");
- var obj2 = new Person("Luo","22");
- obj1.showName();//Kitty
- obj1.showAge();//21
- obj2.showName();//luo
- obj2.showAge();//22
- </script>
构造函数的方法和工厂方法一样,会为每个对象创建独享的函数对象。当然也可以将这些函数对象定义在构造函数外面,这样有了对象和方法相互独立的问题。
使用构造函数存在的最大问题就是每个实例都会将所有的属性创建一次。这个对于数值属性来说可以接受,但是如果函数方法每个实例都要创建一遍,则不合理。
要创建Person()的新实例,必须使用new操作符。以这种方式调用构造函数实际上会经历以下四个步骤:
- 创建一个新对象;
- 将构造函数的作用域赋给新对象(因此this就指向了这个新对象);
- 执行构造函数中的代码(为这个新对象添加属性);
- 返回新对象。
方法四:原型方法
代码如下:
- <script>
- function Person(){} //定义一个空构造函数,且不能传递参数
- //将所有的属性的方法都赋予prototype
- Person.prototype.name = "Kitty";
- Person.prototype.age = 21;
- Person.prototype.showName = function (){
- console.log(this.name);
- };
- Person.prototype.showAge = function (){
- console.log(this.age);
- };
- var obj1 = new Person("Kitty","21");
- var obj2 = new Person("Luo","22");
- obj1.showName();//Kitty
- obj1.showAge();//21
- obj2.showName();//luo
- obj2.showAge();//22
- </script>
修改代码如下:
- <script>
- function Person(){} //定义一个空构造函数,且不能传递参数
- //将所有的属性的方法都赋予prototype
- Person.prototype.age = 21;
- Person.prototype.array = new Array("Kitty","luo");
- Person.prototype.showAge = function (){
- console.log(this.age);
- };
- Person.prototype.showArray = function (){
- console.log(this.array);
- };
- var obj1 = new Person();
- var obj2 = new Person();
- obj1.array.push("Wendy");//向obj1的array属性添加一个元素
- obj1.showArray();//Kitty,luo,Wendy
- obj2.showArray();//Kitty,luo,Wendy
- </script>
方法五:混合的构造函数/原型方式
代码如下:
- <script>
- function Person(name,age){
- this.name = name;
- this.age = age;
- this.array = new Array("Kitty","luo");
- }
- Person.prototype.showName = function (){
- console.log(this.name);
- };
- Person.prototype.showArray = function (){
- console.log(this.array);
- };
- var obj1 = new Person("Kitty",21);
- var obj2 = new Person("luo",22);
- obj1.array.push("Wendy");//向obj1的array属性添加一个元素
- obj1.showArray();//Kitty,luo,Wendy
- obj1.showName();//Kitty
- obj2.showArray();//Kitty,luo
- obj2.showName();//luo
- </script>
属性私有后,改变各自的属性不会影响别的对象。同时,方法也是由各个对象共享的。在语义上,这符合了面向对象编程的要求。
方法六:动态原型方法
代码如下:
- <script>
- function Person(name,age){
- this.name = name;
- this.age = age;
- this.array = new Array("Kitty","luo");
- //如果Person对象中_initialized 为undefined,表明还没有为Person的原型添加方法
- if(typeof Person._initialized == "undefined"){
- Person.prototype.showName = function () {
- console.log(this.name);
- };
- Person.prototype.showArray = function () {
- console.log(this.array);
- };
- Person._initialized = true;
- }
- }
- var obj1 = new Person("Kitty",21);
- var obj2 = new Person("luo",22);
- obj1.array.push("Wendy");//向obj1的array属性添加一个元素
- obj1.showArray();//Kitty,luo,Wendy
- obj1.showName();//Kitty
- obj2.showArray();//Kitty,luo
- obj2.showName();//luo
- </script>
这种方法和构造函数/原型方式大同小异。只是将方法的添加放到了构造函数之中,同时在构造函数Person上添加了一个属性用来保证if语句只能成功执行一次,在实际应用中,采用最广泛的构造函数/原型方法。动态原型方法也很流行,它在功能上和构造函数/原型方法是等价的。不要单独使用构造函数和原型方法。