1、创建Object实例
let mlt = new Object();
mlt.meat = ['鱼','毛肚','午餐肉','鸭肠'];
mlt.vegetable = ['冬瓜','豆腐','小白菜','黄瓜'];
mlt.ingredient = ['辣椒','菜油','盐','鲜汤'];
mlt.effect = function(){
console.log(this.ingredient[0] + '有助于美容养颜');
};
console.log(mlt);
mlt.effect();
缺点:
1、比较麻烦,创建实例后还要一个个添加属性和方法
2、容易与其他代码混合在一起,不便于代码的阅读和管理
2、对象字面量
let mlt = {
meat: ['鱼', '毛肚', '午餐肉', '鸭肠'],
vegetable: ['冬瓜', '豆腐', '小白菜', '黄瓜'],
ingredient: ['辣椒', '菜油', '盐', '鲜汤'],
effect() {
console.log(this.ingredient[0] + '有助于美容养颜');
}
}
console.log(mlt);
mlt.effect();
优点:比直接用Object创建实例更加直观,也符合对象的基本概念;
缺点:不好复用
3、工厂模式
function createObj(name, age) {
let obj = new Object();
obj.name = name;
obj.age = age;
obj.sayHi = function () {
console.log(obj.name)
}
return obj;
}
let per = createObj('司藤', 200)
console.log(per.age); //200
per.sayHi(); //司藤
工厂模式,主要工作原理是用函数来封装创建对象的细节,从而调用函数来达到复用的目的。
优点:解决了创建多个相似对象时,代码的复用问题;
缺点:使用工厂模式创建的对象,没有建立起对象和类型间的关联
4、构造函数
function Person(name, age, sex) {
console.log('this', this) // this Person {}
this.name = name;
this.age = age;
this.sex = sex;
this.say = function () {
console.log("我叫", name)
}
}
let per1 = new Person('柯南', 19, '男');
per1.say(); // 我叫 柯南
console.log(per1 instanceof Person);//true
优点:解决了工厂模式中对象类型无法识别的问题;
缺点:我们知道ECMAScript中的函数时对象,在使用构造函数创建对象时,每个方法都会在实例对象中重新创建一遍。拿上面的例子举例,这意味着每创建一个对象,我们都会创建一个say函数的实例,但它们都是做同样的工作,因此这样便会造成内存的浪费。
5、原型模式
我们知道,我们创建的每一个函数都有一个prototype属性,这个属性指向函数的原型对象,这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。我们通过使用原型对象可以让所有的对象实例共享它所包含的属性和方法,因此这样也解决了代码复用问题。
function Person() {
}
Person.prototype.name = "james";
Person.prototype.age = 9;
Person.prototype.job = "student";
Person.prototype.sayName = function () {
alert(this.name);
}
var person1 = new Person();
person1.sayName(); // "james"
var person2 = new Person();
person2.sayName(); // "james"
console.log(person1.sayName === person2.sayName) // true
优点:解决了构造函数模式中多次创建相同函数对象的问题,所有的实例可以共享同一组属性和函数。
缺点:
- 原型模式省略了构造函数模式传递初始化参数的过程,所有的实例在默认情况下都会取得默认的属性值,会在一定程度上造成不方便;
- 所有的实例都是共享一组属性,对于引用类型进行操作,那么属性的操作就不是独立的,最后导致读写的混乱。
6、Class
class Cat {
constructor(name, age) {
this.name = name;
this.age = age;
}
Say() {
return '我的名字是' + this.name;
}
}
var cat1 = new Cat('有鱼', 2);
console.log(cat1.Say());//我的名字是有鱼
这是创建自定义类型的最常见方式。通过构造函数来初始化对象的属性,通过new关键字来创建实例对象实现函数方法的复用。
7、动态原型模式
动态原型模式解决封装性问题,这个方法把所有信息都封装到了构造函数中,而在构造函数中通过判断只初始化一次原型。
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
if (typeof this.sayName !== "function") {
Person.prototype.sayName = function() {
alert(this.name);
}
}
}
var person1 = new Person("james",9,"student");
person1.sayName(); // "james"
优点:解决了混成模式中的封装性的问题
8、寄生构造函数模式
如果在前面几种模式不适用的情况下,可以使用寄生构造函数模式。这种模式的基本思想是创建一个函数,该函数的作用仅仅是封装创建对象的代码,然后返回新创建的对象。
function Person(name, age, job) {
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function () {
console.log(this.name);
};
return o;
}
var person1 = new Person("james", 9, "student");
person1.sayName(); // james
console.log(person1 instanceof Person); // false
通过上面的例子我们可以发现,其实这个模式和工厂模式基本上是一模一样的,只不过我们采用new操作符来创建对象。
优点:不需要修改原来的构造函数,达到了扩展对象的目的;
缺点:和工厂模式一样,不能依赖instanceof操作符来确定对象的类型
相关资料
http://cavszhouyou.top/JavaScript%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3%E4%B9%8B%E5%AF%B9%E8%B1%A1%E5%88%9B%E5%BB%BA.html