慎用prototype={...}
>
这样做看起来使创建类的代码更加简洁明了,但是内部隐藏着不少可能出现的问题。如你所见到,Obj.prototype = {...}这
条语句是用上下文(即{}匿名对象)把对象的prototype属性完完全全地覆盖掉,这意味着以前prototype生来具有的一些内部方
法现在都不存在了。而这也就是出现问题的地方。举一个例子,假如你想利用上述方法创建对象,但是你还想很集中地定义类
的静态属性和方法,进而考虑利用对象的constructor函数属性来向创建对象的类追加方法(注意,这个例子的思路可能会产生
问题,比如我们想不创建实例的情况下直接使用静态方法或属性等,但是请记住,这只是一个为了说明上述代码创建对象可能会
产生的潜在问题,与本例的易用性无关。),那么你的代码可能会是这样:
但是你会发现这段代码根本就不起作用,类Obj并没有获得任何的静态属性或方法。这是怎么回事呢?其实原因就是obj=prototype
{...}这段代码覆盖了原有对象obj的prototype属性。
首先我们来回顾一下一个对象实例是如何创建的:构造函数把它的prototype原型对象中的所有属性及方法拷贝一份给新的实例。
在这里我的构造函数就是function Obj(){},而constructor也是创建实例的构造函数(即Obj)的引用。但是我们是通过this方式来
调用的,那么我们应该调用的是由构造函数Obj的prototype所拷贝而来的所有的属性和方法,但是我们发现通过Obj.prototype{...},
构造函数的prototype除了_init, method1, method2之外无任何其他方法(of course,constructor方法也没有,所以this.constructor失效了~~~)。改进的方法很简单,就是不要去覆盖prototype,而是要向prototype对象追加属性和方法。所以改进后的方法可能是这样的:
虽然我也不是很赞成去修改原始对象,但有时真的会起到事半功倍的效果。在这里我再向大家推荐一种方法,就是向Funtion对象的prototype属性中追加方法(这样以后所有的function函数对象就都具备了这个方法。其实用function定义的函数都是Function类的实例化),代码如下:
利用我刚才定义的extend方法,就可以轻松而又简洁地向Obj类中添加静态和实例属性或方法,而且已经解决上面所提到的所有问题。
在网上见过很多人创建JavaScript类时喜欢将所有的实例方法都以上下文(Context)的方式赋值给对象的prototype属性:
function Obj() {
this.prop1 = 'prop1'; // instance property
this.prop2 = 'prop2';
}
Obj.staticProp = 'Static Prop';
Obj.staticMethod = function () {
// do some static behavior
};
Obj.prototype = {
method1: function() {
// do somthing
},
method2: function() {
// do somthing
}
};
this.prop1 = 'prop1'; // instance property
this.prop2 = 'prop2';
}
Obj.staticProp = 'Static Prop';
Obj.staticMethod = function () {
// do some static behavior
};
Obj.prototype = {
method1: function() {
// do somthing
},
method2: function() {
// do somthing
}
};
这样做看起来使创建类的代码更加简洁明了,但是内部隐藏着不少可能出现的问题。如你所见到,Obj.prototype = {...}这
条语句是用上下文(即{}匿名对象)把对象的prototype属性完完全全地覆盖掉,这意味着以前prototype生来具有的一些内部方
法现在都不存在了。而这也就是出现问题的地方。举一个例子,假如你想利用上述方法创建对象,但是你还想很集中地定义类
的静态属性和方法,进而考虑利用对象的constructor函数属性来向创建对象的类追加方法(注意,这个例子的思路可能会产生
问题,比如我们想不创建实例的情况下直接使用静态方法或属性等,但是请记住,这只是一个为了说明上述代码创建对象可能会
产生的潜在问题,与本例的易用性无关。),那么你的代码可能会是这样:
function Obj() {
this.prop1 = 'prop1'; // instance property
this.prop2 = 'prop2';
this._init();
}
Obj.prototype = {
_init: function () {
_init: function () {
this.constructor.staticProp = 'Static Prop';
this.constructor.staticMethod = function () {
// do some static behavior
};
},
method1: function() {
// do somthing
},
method2: function() {
// do somthing
}
};
this.prop1 = 'prop1'; // instance property
this.prop2 = 'prop2';
this._init();
}
Obj.prototype = {
_init: function () {
_init: function () {
this.constructor.staticProp = 'Static Prop';
this.constructor.staticMethod = function () {
// do some static behavior
};
},
method1: function() {
// do somthing
},
method2: function() {
// do somthing
}
};
但是你会发现这段代码根本就不起作用,类Obj并没有获得任何的静态属性或方法。这是怎么回事呢?其实原因就是obj=prototype
{...}这段代码覆盖了原有对象obj的prototype属性。
首先我们来回顾一下一个对象实例是如何创建的:构造函数把它的prototype原型对象中的所有属性及方法拷贝一份给新的实例。
在这里我的构造函数就是function Obj(){},而constructor也是创建实例的构造函数(即Obj)的引用。但是我们是通过this方式来
调用的,那么我们应该调用的是由构造函数Obj的prototype所拷贝而来的所有的属性和方法,但是我们发现通过Obj.prototype{...},
构造函数的prototype除了_init, method1, method2之外无任何其他方法(of course,constructor方法也没有,所以this.constructor失效了~~~)。改进的方法很简单,就是不要去覆盖prototype,而是要向prototype对象追加属性和方法。所以改进后的方法可能是这样的:
function Obj() {
this.prop1 = 'prop1'; // instance property
this.prop2 = 'prop2';
this._init();
}
Obj.prototype._init = function () {
this.constructor.staticProp = 'Static Prop';
this.constructor.staticMethod = function () {
// do some static behavior
};
};
Obj.prototype.method1 = function() {
// do somthing
};
Obj.prototype.method2 = function() {
// do somthing
};
this.prop1 = 'prop1'; // instance property
this.prop2 = 'prop2';
this._init();
}
Obj.prototype._init = function () {
this.constructor.staticProp = 'Static Prop';
this.constructor.staticMethod = function () {
// do some static behavior
};
};
Obj.prototype.method1 = function() {
// do somthing
};
Obj.prototype.method2 = function() {
// do somthing
};
虽然我也不是很赞成去修改原始对象,但有时真的会起到事半功倍的效果。在这里我再向大家推荐一种方法,就是向Funtion对象的prototype属性中追加方法(这样以后所有的function函数对象就都具备了这个方法。其实用function定义的函数都是Function类的实例化),代码如下:
Function.prototype.extend = function (oContext, bIsStatic) {
var oThis = (typeof bIsStatic != 'undefined' && bIsStatic)? this: this.prototype;
for ( var prop in oContext) {
oThis[prop] = oContext[prop];
}
};
function Obj() {
this.prop1 = 'prop1'; // instance property
this.prop2 = 'prop2';
}
// Append Static Methods or Properties
Obj.extend({
staticProp: 'staticProp',
staticMethod: function () {
// do some static behavior
}
}, true);
// Append Instance Methods or Properties
Obj.extend({
method1: function() {
// do somthing
},
method2: function() {
// do somthing
}
});
var oThis = (typeof bIsStatic != 'undefined' && bIsStatic)? this: this.prototype;
for ( var prop in oContext) {
oThis[prop] = oContext[prop];
}
};
function Obj() {
this.prop1 = 'prop1'; // instance property
this.prop2 = 'prop2';
}
// Append Static Methods or Properties
Obj.extend({
staticProp: 'staticProp',
staticMethod: function () {
// do some static behavior
}
}, true);
// Append Instance Methods or Properties
Obj.extend({
method1: function() {
// do somthing
},
method2: function() {
// do somthing
}
});
利用我刚才定义的extend方法,就可以轻松而又简洁地向Obj类中添加静态和实例属性或方法,而且已经解决上面所提到的所有问题。