var obj = new Object();
obj.name = 'xxx'
obj...
问题:需要写大量的重复代码
var obj = {};
obj.name = 'xxx';
问题:需要写大量的重复代码
function createObj(name, age) {
var obj = new Object();
obj.name = name;
obj.age = age;
obj.running = function () {
console.log('我会跑...');
}
return obj;
}
var person1 = createObj('黑黑', 18);
好处:通过在工厂中加工出一个对象,来解决重复代码的问题。
坏处: 我们通过工厂加工出来的对象,我们不知道具体是个什么对象。所有的实例都指向一个原型。
function Person(name) {
this.name = name;
this.age = 18;
this.running = function () {
console.log('我会跑...');
}
}
var person1 = new Person('黑黑', 18);
好处:可以自定义对象, 可以识别对象.
坏处: 每一个方法都会在实例中创建一次,意味着共同拥有的行为将创建多次,大量重复的代码。同样的工作,造成内存的浪费(每创建一个对象都会申请内存空间)。
function Person() {
}
Person.prototype.name = '黑黑';
Person.prototype.age = 18;
Person.prototype.running = function () {
console.log('我会跑...');
}
var person1 = new Person('黑黑', 18);
好处:解决了上面的对同一个行为创建多次,实例只需要去原型上取那个唯一的行为。节约了内存。
坏处:1. 将所有的属性都放置原型上,失去了对象独有的属性,造成了不方便,所有的属性和方法都会共享。 2. 如果属性是一个引用类型的对象,那么代表共有一块内存区域,那么只要有一个实例修改,就会全部修改, 不能初始化参数.
function Person() {
}
Person.prototype.name = {
constructor: Person,
name: '黑黑',
age: 18,
running: function () {
console.log('我会跑...');
}
}
var person1 = new Person('黑黑', 18);
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype = {
constructor: Person,
running: function () {
console.log('我会跑...');
}
}
var person1 = new Person('黑黑', 18);
好处:混用两种模式可以解决上面的问题,可以自定义对象独有的属性,并且还能够共用行为。
坏处:使用了两种模式,不利于封装。
function Person(name, age) {
this.name = name;
this.age = age;
if (typeof this.running !== 'function') {
Person.prototype.running = function () {
console.log('我会跑...');
}
}
}
var person1 = new Person('黑黑', 18);
通过判断我们来决定 running 行为是否是需要挂到原型上的。这样灵活度更高,创建对象初始化一次就.
这样写主要就是为了解决 原型 + 构造函数环境中的不利于封装问题。
缺点:我们不能够使用对象字面量来重写原型。
function Person(name, age) {
this.name = name;
this.age = age;
if (typeof this.running !== 'function') {
Person.prototype = {
constructor: Person,
running: function () {
console.log('我会跑...');
}
}
}
}
var person1 = new Person('黑黑', 18);
person1.running(); // 会报错
var person2 = new Person('哈哈', 19);
person.running(); // 我会跑...
我们结合 new 的原理,new 第二部会先使 对象的原型绑定到了 Person.prototype 。然后才调用的 Person.apply(对象); 这时候再去重写原型。所以第一次访问 running 方法的时候是不存在于原型上的。
但是如果经过第一次 new ,进行了一次性的初始化,再去调用 running ,就可以正常运行了。
可以这样修改
function Person(name, age) {
this.name = name;
this.age = age;
if (typeof this.running !== 'function') {
Person.prototype = {
constructor: Person,
running: function () {
console.log('我会跑...');
}
}
return new Person(name);
}
}
重新 new 一次,代表已经初始化过了。就可以正常执行。
function createObj(name, age) {
var obj = new Object();
obj.name = name;
obj.age = age;
obj.running = function () {
console.log('我会跑...');
}
return obj;
}
var person1 = new createObj('黑黑', 18);
我们可以看到跟工厂模式比较起来,只是多了一个 new。 我们从 new 实现原理过程来看。二者的区别在与最终的对象是由 new 操作符给返回的,而不是 createObj 函数返回的。
使用 new 的函数才能被看作是真正意义上的构造函数。 所以说其实意义上这两个模式是差不多的。
我觉得这个模式是基于一个已经存在的对象,进行一个扩展。(具体还是要研究一下设计模式).