Javascript是一门解释型的语言,是基于对象的,严格来说并不怎么符合的面向对象的标准,显著的特点就是函数就是“一等对象”,与传统的面向对象语言不同的时,Javascript有“一千种”方法来创建对象,(尽管猿们找个对象的方法基本为零)。《Js高程》为我们讲解了多种创建对象的方法,这些方法之间并没有优劣,只要在具体的环境下选择合适的方法即可。
1.对象字面量
1 var mygirl={ 2 name:"js", 3 age:"24", 4 shopping:function(){ 5 console.log("give me money!") 6 } 7 }
小结:大括号里的键值对,只能创建一个特定的单例对象
2. Object构造函数
1 var mygirl=new Object(); 2 mygirl.name="js"; 3 mygirl.age=24; 4 mygirl.shopping=function(){ 5 console.log("give me money!") 6 }
小结:ES5新方法构建对象,再添加属性,还有一种常用的更简洁的方法
var mygirl={}; mygirl.name="js"; mygirl.age=24; mygirl.shopping=function(){ console.log("give me money!") }
3.工厂模式创建对象
function createMygirl(name, age) { var o =new Object(); o.name=name; o.age=24; o.shopping=function() { console.log("give me money!") }; return o; } var mygirl=createMygirl("JS",24);
小结:函数 createMygirl() 能够根据接受的参数来构建一个包含所有必要信息的对象。可以无
数次地调用这个函数,而每次它都会返回一个包含两个属性一个方法的对象。特点:可以创建多个相似对象的问题,但却没有解决对象识别的问题(即怎样知道一个对象的类型)。
4.自定义构造函数模式创建对象
function Girl(name, age) { this.name=name; this.age=24; this.shopping=function() { console.log("give me money!") }; } var mygirl=new Girl("JS",24); var yourgirl=new Girl("HTML",23);
要创建 Girl 的新实例,必须使用 new 操作符。以这种方式调用构造函数实际上会经历以下 4个步骤:
- (1) 创建一个新对象;
- (2) 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象);
- (3) 执行构造函数中的代码(为这个新对象添加属性);
- (4) 返回新对象。
1 alert(mygirl.shopping == yourgirl.shopping);//false
5. 使用原型模式创建对象
1 function Girl(){ 2 } 3 Girl.prototype.name="JS"; 4 Girl.prototype.age=24; 5 Girl.prototype.friends=["girl1","girl2"]; 6 Girl.prototype.shopping=function() 7 { 8 console.log("走起,闺蜜们"+this.friends); 9 //叫上闺蜜一起败家 10 }; 11 var mygirl=new Girl(); 12 mygirl.friends.push("girl3"); 13 mygirl.shopping();//走起,闺蜜们girl1,girl2,girl3 14 var yourgirl=new Girl(); 15 yourgirl.shopping();//走起,闺蜜们girl1,girl2,girl3
特点:原型中所有属性是被所有实例共享的,这种共享对于函数非常合适,但是对于基本属性就显得不是很合适,尤其是对于包含引用类型值的属性来说,问题就比较突出了。所有实例共享属性,如firends,这样mygirl添加的闺蜜,也会变成yourgirl的闺蜜。
6. 组合使用原型模式和构造函数创建对象(my beauty)
1 function Girl(name, age) 2 { 3 this.name=name; 4 this.age=24; 5 this.friends=["girl1","girl2"]; 6 } 7 Girl.prototype.shopping=function() 8 { 9 console.log("走起,闺蜜们"+this.friends); 10 //叫上闺蜜一起败家 11 }; 12 var mygirl=new Girl("JS",24); 13 var yourgirl=new Girl("HTML",25); 14 mygirl.friends.push("girl3"); 15 console.log(mygirl.friends);//[ 'girl1', 'girl2', 'girl3' ] 16 console.log(yourgirl.friends);//[ 'girl1', 'girl2' ] 17 console.log(mygirl.friends===yourgirl.friends);//false 18 console.log(mygirl.shopping===yourgirl.shopping);//true
特点:创建自定义类型的最常见方式,就是组合使用构造函数模式与原型模式。构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性。结果,每个实例都会有自己的一份实例属性的副本,但同时又共享着对方法的引用,最大限度地节省了内存。另外,这种混成模式还支持向构造函数传递参数;可谓是集两种模式之长。
7.动态原型模式
function Girl(name, age) { this.name=name; this.age=24; if(typeof this.sayName!="function"){ Girl.prototype.shopping =function(){ console.log("give me money!") }; } } var mygirl=new Girl("JS",24); mygirl.shopping();
特点:动态原型模式把所有信息都封装在了构造函数中,而通过在构造函数中初始化原型(仅在必要的情况下),又保持了同时使用构造函数和原型的优点。换句话说,可以通过检查某个应该存在的方法是否有效,来决定是否需要初始化原型。
8.寄生构造函数模式
function Girl(name, age) { var o =new Object(); o.name=name; o.age=age; o.shopping=function() { console.log("give me money!") }; return o; } var mygirl=new Girl("kevin",24);
这个模式可以在特殊的情况下用来为对象创建构造函数。假设我们想创建一个具有额外方法的特殊数组。由于不能直接修改 Array 构造函数,因此可以使用这个模式。
functionSpecialArray(){ //创建数组 var values =newArray(); //添加值 values.push.apply(values, arguments); //添加方法 values.toPipedString =function(){ returnthis.join("|"); }; //返回数组 return values; } var colors =newSpecialArray("red","blue","green") alert(colors.toPipedString());//"red|blue|green"
9.稳妥构造函数模式
1 function Girl(name, age,bestfriend) 2 { 3 //可以在这里定义私有变量和函数 4 var heigth=1.75; 5 var o =new Object(); 6 o.shopping=function() 7 { 8 console.log("走起,闺蜜们"+bestfriend); 9 //叫上闺蜜一起败家 10 }; 11 return o; 12 } 13 var mygirl=Girl("kevin",24);