一、最初的对象创建
var obj=new Object()
obj.name="测试";
obj.sayName = function() {
alert(this.name);
}
缺点 : 完全无法复用,无法复用造成代码重复并且每个对象的方法就算完全相同也要重新写一遍,麻烦并且占内存
二、引用工厂模式
为了解决第一种对象创建的问题 引入了工厂模式创建对象
function Person(text){
var obj=new Object();
obj.name="测试";
obj.text=text;
obj.sayName=function(){
alert(this.name);
}
return obj;
}
var obj=Person("测试"); //已经在函数内部new
缺点 : 解决了第一种方式的写法上的复用问题,但是由这个方法创建出来的根本不知道是什么对象
也就是说外部代码不能确定 obj 是 new 的 Object
并且该方法每创建一个实例就会创建一份函数在内存中 存在函数复用的问题
三、构造函数创建对象
为了解决第二种方式的对象识别问题 又创造出构造函数创建对象
function Person(name,age){
this.name=name;
this.age=age;
this.sayAge=function(){
alert(this.age);
}
}
var obj=new Person("测试",20);
缺点 : 只解决了工厂模式的对象识别问题 函数复用问题没有解决
四、原型创建对象
其实在原型之前还有一种将函数创建在执行环境中然后赋值给对象函数的方法
function Person(name,age){
this.name=name;
this.age=age;
this.sayAge=say;
}
function say(){
alert(this.age);
}
var obj=new Person("测试",20);
这样虽然解决了函数复用问题
但是这个say()就被暴露在当前执行环境中 这时整个执行环境都可以访问say()
将需要复用的函数放在原型中
function Person(){
}
Person.prototype.name="测试";
Person.prototype.sayName=function(){
alert(this.name);
}
var child=new Person();
成功解决了函数复用 对象识别 但原型存在一个更大的问题
即原型的共享引用类型变量
function Person(){
}
Person.prototype.name="测试";
Person.prototype.arr=[123,"测试"];
Person.prototype.sayName=function(){
alert(this.name);
}
var child01=new Person();
var child02=new Person();
alert(child01.arr); //123,测试
alert(child02.arr); //123,测试
现在其中一个实例改变对象原型的引用类型
child01.arr[child01.arr]="我被添加了";
输出child02的arr也被改变了
alert(child02.arr); //123,测试,我被添加了
这是一个大问题
五、构造函数+原型
既然原型存在共享引用函数的问题 那么把引用类型移到构造函数里嘛
于是就有了最终创建对象的方法
function Person(name,age){
this.name=name;
this.age=age;
this.arr=[123,测试]; //构造函数内创建引用类型
}
Person.prototype.sayName=function(){ //原型创建函数
alert(this.name);
};
var child01=new Person("张三",123)
var child02=new Person("少爷",789);
这时child01改变arr就不会改变child02的arr
因为arr被声明在了构造函数里面 在new Person 时 每个实例都有了自己的arr