现在在我眼里如果js代码中使用了面向对象,那就高了一个档次,使用面向对象编程可以增加你的代码的灵活性以及可维护性,在后期开发中也可以减少大量的工作,但前提是要正确使用它。
对象是无序属性的集合,其属性可以包括基本值、函数、对象。每个属性都会有一个名字,每个名字映射到一个值上。
那么,如何创建一个对象呢?方法有很多。
1.工厂模式
function createPerson(name, age, job) {
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayname = function() {
console.log("name = " + this.name);
};
return o;
}
var person = createPerson("nana", 17); //注意创建方法
person.sayname();
这种方法无法知道一个对象的类型。
2.构造函数模式
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayname = function() {
console.log("name = " + this.name);
}
}
var person1 = new Person("nana", 17, 'hihi');
person1.sayname();
注意:一般将Person称为构造函数,并且构造函数的名字首字母大写,这是编码规范。
此方法解决了问题,可是不同实例的sayname()函数是不相同的,试一下
alert(person1.sayname == person2.sayname) //false
这远远不是我们所需要的,那么就想办法解决吧~ 就有了下面方法:
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = sayName;
}
function sayName() {
return console.log(this.name);
}
var person1 = new createPerson("nana", 17, 'hihi');
person1.sayName();
将sayName定义成一个全局方法,这样每个实例共享的都是全局方法sayName()。问题是解决了,可是如果构造函数里有大量的方法,这就造成代码中有大量的全局变量,后果是不堪设想的。因此,又有了其他办法。
3.原型模式
function Person() {
}
Person.prototype.name = 'nana';
Person.prototype.age = '29';
Person.prototype.sayname = function() {
console.log("name = " + this.name);
}
var person1 = new Person();
person1.sayname();
此方法将属性定义在原型上,是解决了上述问题,可是新的问题就又出来了,原型自身存在的问题是当一个实例改变属性值时,所有实例对应的属性值也都跟着改变,还有一个问题是无法初始化属性值。因此,这种方法也是不可以的,那么,综合一下,重头戏来了!!!
4.组合使用构造函数模式和原型模式
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
}
Person.prototype.sayname = function() {
console.log("name = " + this.name);
}
var person1 = new Person("nana", 17, 'hihi');
person1.sayname();
用构造函数的模式定义属性,用原型模式定义方法和共享属性,结合了两种方法的优点,这种方法是最常用的~~
5.动态原型模式
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
//方法
if(typeof this.sayName != 'function') {
Person.prototype.sayname = function() {
console.log("name = " + this.name);
};
}
}
var person1 = new Person("nana", 17, 'hihi');
person1.sayname();
动态原型方法可以通过检查方法是否有效,决定初始化的原型。这种方法堪称为完美,但是不能使用面向字面量重写原型,这样会切断现有实例与新原型之间的联系。
6.寄生构造函数模式
function createPerson(name, age, job) {
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayname = function() {
console.log("name = " + this.name);
};
return o;
}
var person = new createPerson("nana", 17); //注意创建方法
person.sayname();
此方法可以和工厂模式对比一下,创建实例方法与构造函数相同,其余与工厂模式相同。如果前面方法都不适用可以考虑一下这种方法,但是这种方法构造函数返回的对象与实例没有关系,也不能依赖instanceof判断对象类型,因此,如果可以使用其他模式这种方法建议还是不要使用。
7.稳妥构造函数模式
function Person(name, age, job) {
var o = new Object();
//定义一些私有变量和函数
o.sayname = function() {
console.log("name = " + name); //定义的私有变量等只能通过sayname访问
};
return o;
}
var person1 = Person("nana", 17, "lili");
person1.sayname();
这种方法适合用于在安全的环境下,因为它不使用new调用构造函数,也不使用this引用实例方法。若想访问其属性,只能通过sayname方法来访问其内部私有属性。
其实大二的时候上过面向对象编程的课,但是看了js创建对象的模式还是有点蒙,今天又整理了一遍突然发现思路比较清晰了~如果你还是不懂的话,那就去写代码吧~~~~~写完代码后就会发现也不过如此嘛~~
嘿嘿~如果有什么不对的地方求指教~~~