创建对象的方式有5种
- 工厂方法——使用new Object创建对象并添加相关属性
- 构造函数——来定义类(原型对象)
- 原型模式——使用prototype
- 混合模式——构造函数和原型模式的混合方式(推荐)
- 动态原型方式
//1,工厂模式 function createPerson(name,age,job) { var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function () { alert(this.name); }; return o; //需要把o返回 } var person1 = createPerson("wang",22,"Engineer"); alert(person1.name); //可以无数次调用这个函数,虽然解决了创建多个相似对象的问题,却无法知道一个对象的类型 //2,构造函数模式 function Person(name,age,job) { this.name = name; this.age = age; this.job = job; this.sayName = function () { alert(this.name); } } var person2 = new Person("leo",22,"Engineer"); alert(person2.age); //构造函数名首字母大写,表示它可以用来创建对象; //创建Person的新实例,需要new操作符; //创建自定义的构造函数可以把它的实例标识为一种特定的类型(优于工厂模式); //缺点:每个方法都要在每个实例上重新创建一遍 //3、原型模式 function Person() { } //构造函数是一个空函数 Person.prototype.name = "wang"; Person.prototype.age = 22; Person.prototype.friends = ["aaa","bbb"]; Person.prototype.sayName = function () { alert(this.name); }; var person1 = new Person(); person1.sayName(); var person2 = new Person(); person2.sayName(); alert(person1.sayName == person2.sayName);//true //原型模式的好处是可以让所有的对象实例共享它所包含的属性和方法 person1.name = "leo"; //通过对象实例同名的属性,只可以屏蔽原型中的那个属性, //原理是:先找对象实例里的属性值,若找不到,则再找原型里的属性值 alert(person1.name); //leo //使用hasOwnProperty()方法。可以方便的判断什么时候访问的的实例属性(true),什么时候是原型属性 person1.friends.push("ccc"); alert(person1.friends); //aaa,bbb,ccc alert(person2.friends); //aaa,bbb,ccc //缺点:由于原型中的所有属性的被它的很多实例共享的,如果包含引用类型(例如数组)值的属性时, //改变某个实例的该属性,另外的实例的这个属性也会变,因为他们都指向Person.proptotype //4,构造函数和原型模式的混合模式 function Person(name,age,job) { this.name = name; this.age = age; this.job = job; this.friends = ["aaa","bbb"]; } Person.prototype.sayName = function () { alert(this.name); } var person1 = new Person("wang",23,"engineer"); var person2 = new Person("leo",23,"teacher"); person1.friends.push("ccc"); alert(person1.friends); //aaa,bbb,ccc alert(person2.friends); //aaa,bbb alert(person1.friends === person2.friends); //false alert(person1.sayName === person2.sayName); //true //每个实例都会有自己的一份实例属性的副本,但同时有共享对方法的引用,最大限度节省内存; //实例属性都是在构造函数中定义的(改变不会影响到其他的实例),而所有实例共享的属性constructor和方法sayName()则是在原型中定义的 //5,动态原型模式 function Person(name,age,job) { this.name = name; this.age = age; if(typeof this.sayName != "function"){ Person.prototype.sayName = function () { alert(this.name); } } } var friend = new Person("wang",22,"coder"); friend.sayName(); //只有在sayName()方法不存在时才会将它添加到原型中,这段代码只会在初次调用构造函数时才会执行