1. 对象字面量方式
var person = {
name: "XiaoMing",
age: 29,
job: "Software Engineer",
sayName: function () {
alert(this.name)
}
2.object构造函数:
使用object构造函数和对象字面量方式创建对象有一个缺点:如果我们想创建与该对象同类型的对象,就会产生大量重复的代码。
var person = new Object();
person.name = "XiaoMing";
person.age = 18;
person.job = "software Engineer";
person.sayName = function () {
alert(this.name);
}
3、工厂模式:
用函数来封装以特定接口创建对象的细节,instanceof无法判断它是谁的实例,只能判断他是对象,构造函数都可以判断出。
function Person(name,age,family) {
var o = new Object();
o.name = name;
o.age = age;
o.family = family;
o.say = function(){
alert(this.name);
}
return o;
}
var person1 = createPerson('jill',18,'software');
var person2 = createPerson('vane',23,'student');
console.log( person1 instanceof Object);
4、构造函数:
创建自定义构造函数可以将它的实例标识为一种特定的类型,但是其中的每个方法都要在每个实例上重新创建一遍。
即会导致不同的作用域链和标识符解析,但是创建Function新实例的机制是相同的。
所以person1.sayName == person2.sayName //false
function Person(name,age,family) {
this.name = name;
this.age = age;
this.family = family;
this.say =function(){
alert(this.name);
}
}
var person1 = newPerson("lisi",21,["lida","lier","wangwu"]);
varperson2 = newPerson("lisi",21,["lida","lier","lisi"]);
console.log(person1instanceofObject);
console.log(person1instanceofPerson);
console.log(person2instanceofObject);
console.log(person2instanceofPerson);
5、原型模式:
关于原型模式,每个函数在创建时,都有一个prototype属性,指向该函数的原型对象。使用原型对象的好处是可以让所有对向实例共享它所包含的属性和方法。通过 hasOwnPrototype()方法可以判断属性是实例属性还是原型属性。若为实例属性,返回true,否则返回false。
实例中的指针([[ Prototype ]])指向原型。
原型对象的问题:原型中的所有属性是被很多实例共享的,这种共享对于函数非常合适,然而对于包含引用类型值的属性来说,问题就比较突出。
function Person() {
}
Person.prototype.name = "lisi";
Person.prototype.age = 21;
Person.prototype.family = ["lida","lier","wangwu"];
Person.prototype.say = function(){
alert(this.name);
};
console.log(Person.prototype); //Object{name: 'lisi', age: 21, family: Array[3]}
var person1 = new Person(); //创建一个实例person1
console.log(person1.name); //lisi
var person2 = new Person(); //创建实例person2
person2.name = "wangwu";
person2.family = ["lida","lier","lisi"];
console.log(person2); //Person {name: "wangwu", family: Array[3]}
console.log(person2.prototype.name); //报错
console.log(person2.age); //21
6、混合模式(构造函数模式+原型模式)
function Person(name,age,family){
this.name = name;
this.age = age;
this.family = family;
}
Person.prototype = {
constructor: Person, //每个函数都有prototype属性,指向该函数原型对象,原型对象都有constructor属性,这是一个指向prototype属性所在函数的指针
say: function(){
alert(this.name);
}
}
var person1 = new Person("lisi",21,["lida","lier","wangwu"]);
console.log(person1);
var person2 = new Person("wangwu",21,["lida","lier","lisi"]);
console.log(person2);
7.动态原型模式:
大多数开发人员看到独立的构造函数和原型时,会感到困惑。我们使用动态原型模式解决这一问题。即通过检查某个应该存在的方法是否有效,来决定是否需要初始化原型。
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.friends = ["vane", "ming"];
// 方法
if (typeof this.sayName != "function") {
//使用动态原型模式时,不能使用对象字面量重写原型。如果在已经创建了实例的情况下重写原型,那么就会切断现有实例与新原型之间的联系
Person.prototype.sayName = function () {
alert(this.name);
}
}
}
8、寄生构造函数模式
基本思想:创建一个函数,其作用是封装创建对象的代码,然后返回新创建的对象。
function Person(name,age,job) {
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function () {
alert(this.name);
}
return o;
}
var person = new Person("ming",18,"software");
person.sayName();//ming
9、稳妥构造函数模式:
稳妥对象,指的是没有公共属性,而且其方法也不引用this的对象。稳妥对象最适合在一些安全的环境中(这些环境会禁止使用this和new),或者在防止数据被其他应用程序改动时使用。
其与寄生构造函数不同之处:1、新创建对象的实例方法不引用this;2、不使用new操作符调用构造函数。
function Person(name, age, job) {
var o = new Object();
//可以在这里定义私有变量和函数
o.sayName = function () {
alert(name);
}
return o;
}
var person12 = Person("ming",29,"student");
person12.sayName();//ming