JavaScript中的面向对象

1.创建一个对象

 创建一个对象,然后给这个对象新建属性和方法。

 var box = new Object();                         //创建一个Object对象
 box.name = 'lucy';                              //创建一个name属性并赋值
 box.age = 100;                                  //创建一个age属性并赋值
 box.run = function(){                           //创建一个run()方法并返回值
     return this.name + this.age + '运行中...';   //this表示当前作用域下的对象
 };
  
  alert(box.run());                              //输出属性和方法的值
 
  

    上面就创建了一个对象,并且创建了属性和方法,在run()方法里面的this就是代表box对象本身。这种是JavaScript创建对象最基本的方法,但是有个缺点,想要创建一个类似的对象,就会产生大量的代码。

var box1 = new Object();                         
 box1.name = 'lucy';                             
 box1.age = 100;                               
 box1.run = function(){                          
     return this.name + this.age + '运行中...'; 
 };                   

var box2 = new Object();                         
 box2.name = 'tom';                             
 box2.age = 200;                               
 box2.run = function(){                          
     return this.name + this.age + '运行中...'; 
 };
  
  
 alert(box1.run());   
 alert(box2.run());

    为了解决多个类似对象声明的问题,我们可以使用一种叫做工厂模式的方法,这种方法就是为了解决实例化对象产生大量重复的问题。

//工厂模式
function createObject(name,age){
   var obj = new Object();       //创建对象
   obj.name = name;              //添加属性
   obj.age = age;
   obj.run = function(){         //添加方法
        return this.name + this.age + '运行中...';
   }
    return obj;                 //返回对象引用
}

var box1 = createObject('lucy',100);
var box2 = createObject('tom',200);
alert(box1.run());
alert(box2.run());

alert(typeof box1);
alert(typeof box2);
alert(box1 instanceof Object);
alert(box2 instanceof Object);

    工厂模式解决的重复实例化的问题,但还有一个问题,那就是识别问题,因为根本无法搞清楚他们是哪个对象的实例。

    ECMAScript中可以采用构造函数(构造方法)来创建特定的对象。类似Object对象。

//构造函数
function Desk(name,age){  
   this.name = name;
   this.age = age;
   this.run = function(){
         return this.name + this.age +'运行中...';
   }
}

function Box(name,age){  
   this.name = name;
   this.age = age;
   this.run = function(){
         return this.name + this.age +'运行中...';
   }
}

//1.构造函数没有new Object,但是它在后台会自动的var obj = new Object()
//2.this就相当于obj
//3.构造函数不需要返回对象的引用,它是后台自动返回的

//构造函数的一些规范
//1.构造函数也是函数,但函数名第一个字母大写
//2.必须new构造函数名(),new Box(),而这个Box的第一个字母也是大写的

var box1 = new Box('lucy',100); //实例化
var box2 = new Box('tom',200);
var box3 = new Desk('kkkk',200);
alert(box1.run());
alert(box2.run());
alert(box1 instanceof Object);
alert(box1 instanceof Box);
alert(box2 instanceof Box);
alert(box3 instanceof Box); //可以识别了,因为box3是Desk对象的引用


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

    使用构造函数的方法,和使用工厂模式的方法,他们的不同之处如下:
    1.使用构造函数方法并没有显示创建对象(new Object())
    2.直接将属性和方法赋值给this对象
    3.没有return语句

    构造函数的方法有一些规范:
    1.函数名和实例化构造名相同,且大写(PS:非强制,但这么写有助于区别构造函数和普通函数)
    2.通过构造函数创建对象,必须使用new运算符

    既然通过构造函数能够创建对象,那么这个对象是从哪里来的,new Object()在哪里执行了?执行的过程如下:
    1.当使用构造函数,并且new构造函数(),那么就后台执行了new Object()
    2.将构造函数的作用域给新对象,(即new Object()创建出来的对象),而函数体内的this就代表new Object()出来的对象
    3.执行构造函数内的代码
    4.返回新对象(后台直接返回)


    关于this的使用,this其实就表示当前作用域对象的引用。如果在全局范围内this就表示window对象,如果在构造函数体内,就代表当前构造函数的所声明的对象

    构造函数和普通函数唯一的区别就是,就是他们的调用方式不同。只不过,构造函数也是函数,必须使用new运算符来调用,否则就是普通函数。

var box = new Box('tom',100);   //构造模式调用
alert(box.run());

Box('tom',10);   //普通模式调用无效


var o = new Object();
Box.call(o,'tom',200);      //对象冒充调用
alert(o.run());


    探讨构造函数内部内部的方法(或函数)的问题,首先看下面两个实例化之后的属性或方法是否相等。


var box1 = new Box('tom',100);     //传递一致
var box2 = new Box('tom',100);
alert(box1.name == box2.name);     //true 属性的值相等
alert(box1.run == box2.run);       //false 注意此处不是box.run(),方法其实也是一种引用地址
alert(box1.run() == box2.run());   //true  方法的值相等,因为传参一致
 


    可以把构造函数里面的方法(或函数)用new Function()方法来代替,得到一用的效果,更加证明,他们最终判断的是引用地址,唯一性。


function Box(name,age){
    this.name = name;
    this.age = age;
    this.run = new Function("return this.name+this.age+'运行中...'");
}

var box1 = new Box('tom',100);
alert(box1.run());


    我们可以通过构造函数在外面绑定同一个函数的方法来保证引用地址的一致性,但是这种方法没有必要

function Box(name,age){
    this.name = name;
    this.age = age;
    this.run = run;
}

function run(){    //通过外面调用,保证引用地址一致
    return this.name + this.age + '运行中...';
}

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

var box2 = new Box('tom',100);
alert(box1.run == box2.run);
alert(box1.run());//这里run中的this.name的this表示的是Box对象
alert(run());     //这里run中的this.name的this表示的是window


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


你可能感兴趣的:(JavaScript)