简体   繁体   English

向Object / Number / String原型添加方法

[英]Adding methods to Object / Number / String prototype

Disclaimer 放弃

  • This thread is supposed to serve as a help for other people encountering similar problems as well as checking whether there are better solutions. 该线程应该作为其他人遇到类似问题的帮助,以及检查是否有更好的解决方案。 I will attach my own solution, but ideas and improvements (besides making it more generic) are welcome. 我将附上我自己的解决方案,但欢迎提出想法和改进(除了使其更通用)。
  • I know that generally, extending the built-in objects is a bad idea. 我知道,通常,扩展内置对象是个坏主意。 So an assumption for this thread is that there is a good reason and no way around it. 所以这个线程的假设是有一个很好的理由而且无法绕过它。

Scenario 脚本

As a developer, I want to add a method someMethod to all Javascript objects, wherein the implementation is different for Object , Number and String . 作为开发人员,我想向所有Javascript对象添加一个方法someMethod ,其中ObjectNumberString的实现是不同的。

I want the solution to meet the following acceptance criteria: 我希望该解决方案符合以下验收标准:

  • A) The solution works in a browser A)解决方案适用于浏览器
    • A1) The solution works in strict mode in case the script is used within a strict context A1)如果在严格的上下文中使用脚本,解决方案将以严格模式运行
    • A2) The solution works in non-strict mode because 'use strict'; A2)解决方案在非严格模式下工作,因为'use strict'; will be removed during compression in, eg, the YUI Compressor [1] 将在压缩期间删除,例如YUI Compressor [1]
  • B) The solution works in node.js B)解决方案在node.js中工作
    • B1) The solution works in strict mode (reason see A1) B1)解决方案在严格模式下工作(原因见A1)
    • B2) The solution works in non-strict mode for the same reason as in B2, plus strict mode in node.js cannot be activated on function level[2] B2)解决方案在非严格模式下工作的原因与B2相同,加上node.js中的严格模式不能在功能级别激活[2]
  • C) I want other objects to be allowed to override this method C)我希望允许其他对象覆盖此方法
  • D) If possible, I want to have control over whether or not the method shows up in a for .. in loop to avoid conflicts with other libraries D)如果可能的话,我想控制方法是否出现在for .. in循环中以避免与其他库冲突
  • E) The solution shall actually modify the prototypes. E)解决方案实际上应修改原型。

[1] Minfication removes strict directives [1] Minfication删除了严格的指令
[2] Any way to force strict mode in node? [2] 任何强制节点严格模式的方法?

My own solution 我自己的解决方案

While trying to figure this out, I have encountered a few problems causing one or another acceptance criterium to break (eg a problem described in [1]). 在试图解决这个问题时,我遇到了一些导致一个或另一个接受标准破裂的问题(例如[1]中描述的问题)。 After some time I came up with the following solution which seems to work for me. 过了一段时间,我想出了以下解决方案,这似乎对我有用。 This can be written in a more generic way, of course. 当然,这可以用更通用的方式编写。

(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'];
    }
})(); 

Edit: I updated the solution to add the solution for the problem mentioned in [1]. 编辑:我更新了解决方案,为[1]中提到的问题添加解决方案。 Namely it's the line (eg) var _this = this.valueOf(); 即它是行(例如) var _this = this.valueOf(); . The reason for this becomes clear if using 如果使用,原因就变得清晰了

'number': function (other) {
    return this === other;
}

In this case, you will get 在这种情况下,你会得到

var someNumber = 42;
console.log( someNumber.someMethod( 42 ) ); // false

This, of course, isn't what we'd want (again, the reason is stated in [1]). 当然,这不是我们想要的(同样,原因在[1]中说明)。 So you should use _this instead of this : 所以你应该使用_this而不是this

'number': function (other) {
    var _this = this.valueOf();
    return _this === other;
}

// ...

var someNumber = 42;
console.log( someNumber.someMethod( 42 ) ); // true

[1] Why does `typeof this` return "object"? [1] 为什么`typeof this`返回“对象”?

Creating a wrapper object (note this is just an example, it is not very robust): 创建一个包装器对象(注意这只是一个例子,它不是很健壮):

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 $;
})();

Usage: 用法:

var num = 5;
var str = 'test';
var obj = {num: num, str: str};

var $num = $(num);
$num.method('format');

$(str).method('format');
$(obj).method('format');

Demo 演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM