外部属性定义方式 /* 在js中并不存在类,所以可以直接通过object来创建对象 但是使用如下方式创建,带来最大的问题是,由于没有类的约束 无法实现对象的重复利用,并且没有一个约定,在操作时会带来问题 */ var person = new Object(); person.name = 'leo'; person.age = 33; person.say = function(){ alert(this.name + ',' + this.age); } 使用json格式定义 /* json的意思就是javascript simple object notation json就是js的对象,但是它省去了xml中标签,而是通过{}来完成对象的说明 */ var person = { name :'张三', age :23, say:function(){ alert(this.name + ',' + this.age); }//最后一个属性之后不能有, } person.say(); /* 通过json依然可以创建对象数组,创建的方式和js的数组一样 */ var ps =[ {name : 'leo',age:22}, {name : 'le',age :30} ]; /* 创建一个组用户,用户的属性有 name :string,age:int,friends:array List<person> ps = new ArrayList<person>(); ps.add(new Person('leo',22,['ada','alice'])); */ ps = [ { name :'leo', age :22, friendes :['Ada','Alice'] }, { name : 'le', age :30, friends:['Ada','chris'] } ] 工厂方式 /* 通过工厂的方式来创建person对象 在createPerson中创建一个对象 然后为这个对象设置相应的属性和方法之后返回这个对象 */ function createPerson(name,age){ var o = new Object(); o.name = name; o.age =age; o.say = functon (){ alert(this.name+','+this.age); } return o; } /* 使用工厂的方式,虽然有效的解决了类的问题,但是依然存在另外个问题 我们无法检测对象p1和p2的数据类型 */ var p1 = createPerson('leo',22); var p2 = createPerson('ada',30); // 没有办检测p1和ps的数据类型通过typeof仅仅只能检测出object类型,如果希望使用instanceof来检测的话,无法确定检测类型 p1.say(); p2.say(); 构造函数方式 //通过new person来创建对象 var p1 = new person('leo',22); var p2 = new person('le',30) p1.say(); p2.say(); /* 使用构造函数的方式可以通过以下方式来检测 对象的类型 */ console.log(p1 instanceof Person); /* 使用构造函数创建所带来的第一个问题就是每个对象中 都会存在一个方法的拷贝,如果对象的行为很多的话空间 的占用率就会大大增加 可以将函数放在全局变量中定义,这个可以让类中的行为指向同一个函数 */ console.log(p1.say == p2.say); 如果在person内部来创建方法,这两个不是一样的 使用如下方式可以解决空间利用的问题 this.say = say; /* 将行为设置为全局的行为,如果将所有的方法都设计为全局函数的时候 这个函数就可以被winodw调用,此时就破坏对蠏的封装性 而且如果某个对象有大量的方法,就会导致整个代码中充斥着大量的全局函数 这样将不利于开发 */ function say(){ console.log(this.name+','+this.age); } 基于原型的方式 /* 基于原型的创建虽然可以有效的完成封装,但是依然有一些问题 1、无法通过构造函数来设置属性值 2、当属性中有引用类型变量是,可能存在变量值重复 */ function person(){ } person.prototype = { constructor :person, name : 'leo', age :30, friends:['le','chris'], say:function(){ console.log(this.name +'['+ this.friends+']'); } } var p1 = new person(); p1.name = 'john'; p1.say(); //john[le,chris] //会在原型中找friends,所以mike是在原型中增加的 p1.friends.push('ni'); //为p1增加了一个朋友 var p2 = new Person(); //此时原型中就多了一个Mike,这就是原型所带来的第二个问题 p2.say(); 基于构造函数和原型方式 /* 为了解决原型所带来的问题,此外需要通过组合构造函数和原型来实现对象的创建 将属性在构造函数中定义,将方法在原型中定义 这种有效集合了两者的优点,是目前最为常用的一种方式 */ function person(name,age,friends){ //属性在构造函数中定义 this.name = name; this.age = age; this.friends = friends; } person.prototype = { constructor = person; //方法在原型中定义 say : function(){ console.log(this.name +"["+this.friends+"]") } } //此时所以的属性都是保存在自己的空间中的 var p1 = new Person('leo',23,['Ada','chris']); p1.name = 'john'; p1.friends.push('Mike'); //为p1增加了一个朋友 p1.say(); var p2 = new Person('Ada',33,['leo']); //此时原型中就多了一个mike,这就是原型所带来的第二个问题 p2.sav(); 动态原型的方式 为了让定义的方式更加符合java的需求,就把定义方法的原型代码放置到person这个构造函数中 function Person(name,age,friends){ this.name = name; this.age = age; this.friends = friends; //不能使用重写的方式定义 /* person.prototype = { constructor:person, say:function(){ console.log(this.name + "["+this.friends+"]"); } } */ /* 判断person.prototype.asy是否存在,如果不存在就表示需要创建 当存在之后就不会在创建 */ if(!person.prototype.say){ person.prototype.say = function(){ console.log(this.name +"['+this.friends+']") } } }