免责声明
- 该线程应该为遇到类似问题的其他人提供帮助,并检查是否有更好的解决方案。我将附上我自己的解决方案,但欢迎提出想法和改进(除了使其更通用)。
- 我知道一般来说,扩展内置对象是个坏主意。所以这个线程的一个假设是有一个很好的理由并且没有办法绕过它。
设想
作为开发人员,我想为someMethod
所有 Javascript 对象添加一个方法,其中Object
,Number
和String
.
我希望解决方案满足以下验收标准:
免责声明
作为开发人员,我想为someMethod
所有 Javascript 对象添加一个方法,其中Object
,Number
和String
.
我希望解决方案满足以下验收标准:
在试图解决这个问题时,我遇到了一些导致一个或另一个验收标准被打破的问题(例如 [1] 中描述的问题)。一段时间后,我想出了以下似乎对我有用的解决方案。当然,这可以用更通用的方式编写。
(function () {
'use strict';
var methodName = 'someMethod',
/** Sample method implementations */
__someMethod = {
'object': function () {
var _this = this.valueOf();
return ['Object'].concat( Array.prototype.slice.call( arguments ) );
},
'number': function () {
var _this = this.valueOf();
return ['Number'].concat( Array.prototype.slice.call( arguments ) );
},
'string': function () {
var _this = this.valueOf();
return ['String'].concat( Array.prototype.slice.call( arguments ) );
},
'boolean': function () {
var _this = this.valueOf();
return ['Boolean', _this];
}
};
if( Object.defineProperty ) {
Object.defineProperty( Number.prototype, methodName, {
value: __someMethod['number'],
writable: true
} );
Object.defineProperty( String.prototype, methodName, {
value: __someMethod['string'],
writable: true
} );
Object.defineProperty( Boolean.prototype, methodName, {
value: __someMethod['boolean'],
writable: true
} );
Object.defineProperty( Object.prototype, methodName, {
value: __someMethod['object'],
writable: true
} );
} else {
Number.prototype[methodName] = __someMethod['number'];
String.prototype[methodName] = __someMethod['string'];
Boolean.prototype[methodName] = __someMethod['boolean'];
Object.prototype[methodName] = __someMethod['object'];
}
})();
编辑:我更新了解决方案以添加 [1] 中提到的问题的解决方案。即它的行 (eg) var _this = this.valueOf();
。如果使用,原因就很清楚了
'number': function (other) {
return this === other;
}
在这种情况下,你会得到
var someNumber = 42;
console.log( someNumber.someMethod( 42 ) ); // false
当然,这不是我们想要的(同样,原因在 [1] 中说明)。所以你应该使用_this
而不是this
:
'number': function (other) {
var _this = this.valueOf();
return _this === other;
}
// ...
var someNumber = 42;
console.log( someNumber.someMethod( 42 ) ); // true
创建一个包装对象(注意这只是一个例子,它不是很健壮):
var $ = (function(){
function $(obj){
if(!(this instanceof $))
return new $(obj);
this.method = function(method){
var objtype = typeof obj;
var methodName = method + objtype[0].toUpperCase() + objtype.substr(1);
typeof _$[methodName] == 'function' && _$[methodName].call(obj);
}
}
var _$ = {};
_$.formatNumber = function(){
console.log('Formatting number: ' + this);
}
_$.formatString = function(){
console.log('Formatting str: "' + this + '"');
}
_$.formatObject = function(){
console.log('Formatting object: ');
console.log(JSON.stringify(this));
}
return $;
})();
用法:
var num = 5;
var str = 'test';
var obj = {num: num, str: str};
var $num = $(num);
$num.method('format');
$(str).method('format');
$(obj).method('format');