JavaScript 对象系列:
第三篇
对象创建的方式,一般有两种:
- 字面量(常用)
- 构造函数
针对定义一个对象,随你采用哪种方式都是可以的。但是如果是下面这种情况呢?
var p1 = {
name: "james",
age: 35,
playing: function (team) {
console.log(`${this.name}效力于${team}`);
},
};
var p2 = {
name: "curry",
age: 30,
playing: function (team) {
console.log(`${this.name}效力于${team}`);
},
};
var p3 = {
name: "kobe",
age: 40,
playing: function (team) {
console.log(`${this.name}效力于${team}`);
},
};
从上面,可以发现定义了三个对象,并且对象的结构一模一样,那么对于程序员来说,不进行抽离,天理难容。
工厂模式
- 工厂模式其实是一种常见的设计模式;
- 工厂模式有一个工厂方法,用于创建新的对象
// 工厂方法
function createPerson(name, age) {
var p = new Object();
p.name = name;
p.age = age;
p.playing = function (team) {
console.log(`${this.name}效力于${team}`);
};
return p;
}
var p1 = createPerson("james", 35);
var p2 = createPerson("curry", 30);
var p3 = createPerson("kobe", 40);
优点:主要定义一个工厂方法,进行调用,就能创建多个对象;代码量少;
缺点:获取不到函数的真实类型(都是Object类型)
console.log(p1) // { name: 'james', age: 35, playing: [Function (anonymous)] }
构造函数
- 一个函数直接通过
()
调用,被称为普通函数; - 一个函数通过
new
调用,则被称为构造函数; - 约定俗成的规定,构造函数的首字母要大写,为了其他人便于区分;
function Person(name, age) {
this.name = name;
this.age = age;
this.playing = function (team) {
console.log(`${this.name}效力于${team}`);
};
}
var p1 = new Person("james", 35);
var p2 = new Person("curry", 30);
var p3 = new Person("kobe", 40);
优点:可以清楚的知道对象的类型
console.log(p1)
// Person { name: 'james', age: 35, playing: [Function (anonymous)] }
// Person 类型
缺点:就是浪费内存空间(针对于函数)
每调用一次构造函数,就会在堆内存空间里面开辟一个新的地址来保存 playing
函数。如果创建对象,创建了100个,那么就会在内存空间中,创建出100个内存地址。但是呢?100个内存地址里面保存的信息基本上又是一样的,所以有点浪费性能。
构造函数 + 原型
上面,我们知道了构造函数,创建多个对象的缺点,就是浪费内存空间。所以可以利用原型,来优化一下,共享一个函数,只需要开辟一个空间。
函数都是具有函数的原型(prototype)
function Person(name, age) {
this.name = name;
this.age = age;
}
// 共享方法绑定在原型上
Person.prototype.playing = function (team) {
console.log(`${this.name}效力于${team}`);
};
var p1 = new Person("james", 35);
var p2 = new Person("curry", 30);
var p3 = new Person("kobe", 40);
console.log(p1);
这样就保存了构造函数的优点,又解决了构造函数的缺点。