• JavaScript之面向对象与原型笔记整理--------创建对象(1)


    创建对象

    1、通过Object方法

    创建一个box对象,然后给这个对象新建属性和方法,如下:

    另:属性相当于变量,在一个作用域里面就变成了属性;方法其实是函数,在一定作用域下就变成了方法。

    1 var box = new Object();             //创建一个Object对象
    2 box.name = 'Lee';                   //创建一个name属性并赋值
    3 box.age = 20;                       //创建一个age属性并赋值
    4 box.run = function(){               //创建一个run方法并返回值
    5     return "姓名:" + this.name + ",年龄:" + this.age;
    6 }
    7 console.log(box.name);             //Lee
    8 console.log(box.age);              //20
    9 console.log(this.age);             //undefined 因为此时this指代window

    this表示new Object()实例化出来的对象,即当前作用域下的对象。

    this要放在一个作用域下,比如box.run(){},这个是box作用域下的方法,即可用this来表示。

    在run()方法里的this就指代box本身。

    缺点:若想创建一个类似的对象,就会产生大量的代码。如下:

    var box1 = new Object();           
    box1.name = 'Lee';                 
    box1.age = 20;                       
    box1.run = function(){            
         return "姓名:" + this.name + ",年龄:" + this.age;
     }
    
    
    var box2 = new Object();           
    box2.name = 'Lily';                 
    box2.age = 18;                       
    box2.run = function(){            
         return "姓名:" + this.name + ",年龄:" + this.age;
     }
    
    ...

    此时,新添加了对象box2,若继续添加(比如有十个就得写十次),则产生大量类似代码,为了解决多个类似对象声明的问题,可以使用工厂模式的方法,这种方法就是为了解决实例化对象产生大量重复的问题。

    2、工厂模式

     1  function createObject(name,age){
     2     var obj = new Object();              //创建对象
     3     obj.name = name;                     //添加属性
     4     obj.age = age;
     5     obj.run = function(){                //添加方法
     6         return "姓名:" + this.name +  ",年龄:" + this.age;  
     7     };
     8     return obj;                          //需要返回这个对象,返回对象引用
     9  }
    10    
    11  var box1 = createObject('Lee',20);      //创建第一个对象
    12  var box2 = createObject('Lily',18);     //创建第二个对象
    13  console.log(box1.run());                //姓名:Lee,年龄:20
    14  console.log(box2.run());                //姓名:Lily,年龄:18

    工厂模式解决了重复实例化的问题,但是还有一个问题,识别问题。

    缺点:无法搞清楚他们到底是那个对象的实例,都是Object。如下

     1    function createObject(name,age){
     2       var obj = new Object();            
     3       obj.name = name;                
     4       obj.age = age;
     5       obj.run = function(){              
     6           return "姓名:" + this.name +  ",年龄:" + this.age;  
     7       };
     8       return obj;                      
     9    }
    10 
    11   function createObject2(name,age){
    12       var obj = new Object();            
    13       obj.name = name;                
    14       obj.age = age;
    15       obj.run = function(){              
    16           return "姓名:" + this.name +  ",年龄:" + this.age;  
    17       };
    18       return obj;                      
    19    }
    20 
    21     
    22   var box1 = createObject('Lee',20);      //创建第一个对象
    23   var box2 = createObject('Lily',18);     //创建第二个对象
    24   var box3 = createObject2('Lucy',25);     //创建第三个对象
    25   console.log(box1 instanceof Object);    //true,box1属于Object对象
    26   console.log(box2 instanceof Object);    //true,box2属于Object对象
    27   console.log(box3 instanceof Object);    //true,box2属于Object对象

    不管怎样他们都是Object对象,就无法区分谁到底是谁的对象了,其实box1和box2都是第一个工厂的Object,box3是第二个工厂的Object。此时无法区分。

    采用构造函数可用来创建特定的对象。

    3、构造函数

     1 function Box(name,age){                             //创建一个对象
     2      //此处无new,自动var obj = new Object()
     3      this.name = name;                              //添加属性
     4      this.age = age;
     5      this.run = function(){                         //添加方法
     6         return "姓名:" + this.name + ",年龄:" + this.age;
     7      }; 
     8      //此处无return,自动返回
     9 } 
    10 
    11 var box1 = new Box('Lee',20);                       //实例化
    12 var box2 = new Box('Luck',8); 
    13 console.log(box1.run());                            //姓名:Lee,年龄:20
    14 console.log(box2.run());                            //姓名:Luck,年龄:8

    使用构造函数的方法,即解决了重复实例化的问题,又解决了对象识别的问题,但问题是,这里并没有new Object(),为什么可以实例化Box(),这个是哪里来的呢?

    使用了构造函数的方法,和使用工厂模式的方法他们不同之处如下:

    (1)构造函数方法没有显示的创建对象(new Object()),但后台会自动var obj = new Object();

    (2)直接将属性和方法赋值给this对象,此时this相当于obj;

    (3)没有return语句,无需返回对象引用,后台自动返回。

    构造函数的方法有一些规范:

    (1)函数名和实例化构造名相同且第一个字母大写。

    (2)必须new 构造函数名() ,例如 new Box()。

    (3)必须使用new运算符。

    接下来看识别对象问题,如下:、

     1  function Box(name,age){                          
     2        this.name = name;                              
     3        this.age = age;
     4        this.run = function(){                     
     5           return "姓名:" + this.name + ",年龄:" + this.age;
     6        }; 
     7   }
     8 
     9  function Desk(name,age){                          
    10        this.name = name;                              
    11        this.age = age;
    12        this.run = function(){                     
    13           return "姓名:" + this.name + ",年龄:" + this.age;
    14        }; 
    15   }  
    16  
    17  var box1 = new Box('Lee',20);                       
    18  var box2 = new Box('Luck',8); 
    19  var box3 = new Desk('Lily',22);   
    20  console.log(box1 instanceof Box);    //true
    21  console.log(box2 instanceof Box);    //true
    22  console.log(box3 instanceof Box);    //false
    23  console.log(box3 instanceof Desk);    //true

    可以看出,box1,box2属于Box对象,box3属于Desk对象。解决了对象识别问题。

    构造函数用普通函数调用一般是无效的,必须使用new运算符。比如直接console.log(Box('Lee',20));此时控制台输出undefined。

    补充:

    接下来探究一下构造函数内部的方法问题,先看例子:

     function Box(name,age){                          
             this.name = name;                              
             this.age = age;
             this.run = function(){                     
                return "姓名:" + this.name + ",年龄:" + this.age;
             }; 
       }
    
    var box1 = new Box('Lee',20);
    var box2 = new Box('Lee',20);
    //构造函数体内方法值是相等的
    console.log(box1.name == box2.name);           //true
    console.log(box1.age== box2.age);              //true
    console.log(box1.run()== box2.run());          //true
    //比较的是引用地址,所以不相等
    console.log(box1.run== box2.run);              //false

    此时说明box1和box2的引用地址不同。

    改进方法:

     function Box(name,age){                          
             this.name = name;                              
             this.age = age;
             this.run = run;
     } 
     function run(){       //通过外面调用保证引用地址一致              
             return "姓名:" + this.name + ",年龄:" + this.age;
     }
    
     var box1 = new Box('Lee',20);   
     var box2 = new Box('Lee',20);
    
     console.log(box1.run== box2.run);              //true

    虽然使用了全局的函数run()来解决了保证引用地址一致的问题,但这种方式又带来了一个新的问题,全局中的this在对象调用的时候是Box本身,意思为:box1.run()时,此时this代表Box本身,而当做普通函数调用的时候,意思为:run()时,this又代表window。

    此时run()也可以被其他调用。

  • 相关阅读:
    Redis实战(十)Redis常见问题及解决方案
    小团队构建大网站:中小研发团队架构实践
    Asp.net core 3.0
    图解TCP/IP
    TCP/IP协议
    Grid画边框
    WPF常用方法,事件驱动和控件遍历
    WPF中的画图
    WPF中的常用类汇总:
    WPF中的VisualTreeHelper
  • 原文地址:https://www.cnblogs.com/manru75/p/9475345.html
Copyright © 2020-2023  润新知