向对象/数字/字符串原型添加方法

Ing*_*ürk 5 javascript

免责声明

  • 该帖子旨在为遇到类似问题的其他人提供帮助,并检查是否有更好的解决方案。我将附上我自己的解决方案,但欢迎提出想法和改进(除了使其更通用)。
  • 我知道,一般来说,扩展内置对象是一个坏主意。因此,该线程的假设是有充分的理由并且没有办法解决它。

设想

作为一名开发人员,我想向所有 Javascript 对象添加一个方法,其中、和someMethod的实现不同。ObjectNumberString

我希望该解决方案满足以下验收标准:

  • A) 该解决方案在浏览器中运行
    • A1) 该解决方案在严格模式下工作,以防脚本在严格上下文中使用
    • A2) 该解决方案在非严格模式下工作,因为'use strict';在压缩过程中将被删除,例如YUI 压缩机[1]
  • B) 该解决方案适用于Node.js
    • B1) 该解决方案在严格模式下工作(原因参见 A1)
    • B2) 该解决方案在非严格模式下工作,原因与 B2 相同,而且 Node.js 中的严格模式无法在函数级别激活[2]
  • C) 我希望允许其他对象覆盖此方法
  • D)如果可能的话,我想控制该方法是否出现在循环中for .. in以避免与其他库发生冲突
  • E) 解决方案应实际修改原型。

[1] Minfication 删除了严格指令
[2]有什么方法可以在节点中强制使用严格模式?

Ing*_*ürk 3

我自己的解决方案

在试图解决这个问题时,我遇到了一些导致一个或另一个验收标准被破坏的问题(例如[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'];
    }
})(); 
Run Code Online (Sandbox Code Playgroud)

编辑:我更新了解决方案以添加[1]中提到的问题的解决方案。即它是行 (eg) var _this = this.valueOf();。如果使用的话,原因就很清楚了

'number': function (other) {
    return this === other;
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您将得到

var someNumber = 42;
console.log( someNumber.someMethod( 42 ) ); // false
Run Code Online (Sandbox Code Playgroud)

当然,这不是我们想要的(同样,原因在[1]中说明)。所以你应该使用_this而不是this

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

// ...

var someNumber = 42;
console.log( someNumber.someMethod( 42 ) ); // true
Run Code Online (Sandbox Code Playgroud)

[1]为什么 `typeof this` 返回“object”?