javascript - 使用 jQuery 时扩展 object.prototype 的替代方法

标签 javascript jquery defineproperty

前段时间我尝试扩展 Object.prototype... 后来我在控制台中看到来自 jQuery 文件的错误时,我感到很惊讶。我试图找出问题所在,当然我发现扩展 Object.prototype 是一个“邪恶”的信息,“你不应该这样做,因为 JS 是动态语言,你的代码将无法工作soon” 以及 jQuery 现在将 hasOwnProperty 方法添加到它们的 for in 循环中的信息。

因为我不想离开 jQuery,所以我放弃了扩展 Object.prototype 的想法。

到现在为止。我的项目越来越大,我真的很生气,因为我不得不多次重复代码的某些部分。下面是我在我的项目中使用的一些结构:

charts.js:

CHARTS = {
    _init: function () {
        this.monthlyChart();
        /*
         * 
         * more propertys goes here
         * 
         */
        return this;
    },
    monthlyChart: function () {
        //create my chart
        return {
            update: function () {
               // update chart
            }
        };
    }()
    /*
     * 
     * more propertys goes here
     * 
     */
}._init;

dashboard.js

NAVBAR = {
    _init: function () {
        /*
         * 
         * more propertys goes here
         * 
         */
        return this;
    },
    doSomething: function(){            
        $(document).ready(function(){
            $('.myButton').on('click', function(){
                var data = [];
                // calling property from charts.js
                CHARTS.monthlyChart.update(data);
            });
        });
    }
}._init

正如我提到的,项目现在真的很大 - 它有 40 多个 js 文件,其中一些有几千行代码。真的很烦人,我每次都必须重复 _init 部分,还有很多功能我必须重复 $(document).ready && $(窗口).load.

我试图为我的问题找到另一种解决方案。我试图用 init 属性创建类 (more you can find here)但是我这个解决方案迫使我向每个文件添加另一个“不必要的”代码片段,并且访问其他文件对象属性也使它变得复杂(到处返回适当的对象等)。正如评论中所建议的那样,我开始阅读有关 JS 中的 getter 和 setter 的内容。

毕竟我创造了类似的东西:

 //Auto initialization
if (typeof $document === 'undefined') {
    var $document = $(document),
            $window = $(window),
            $body = $('body');
}

Object.defineProperty(Object.prototype, '_init', {
    get: function () {
        // if object has no property named `_init`
        if (!this.hasOwnProperty('_init')) {
            for (var key in this) {
                // checking if name of property does starts from '_' and if it is function
                if (this.hasOwnProperty(key) && key[0] === '_' && typeof this[key] === 'function') {                    
                    if (key.indexOf('_ready_') > -1) {
                        //add function to document ready if property name starts from '_ready_'
                        $document.ready(this[key].bind(this));
                    } else if (key.indexOf('_load_') > -1) {
                        //add function to window load if property name starts from '_load_'
                        $window.load(this[key].bind(this));
                    } else {
                        // else execute function now
                        this[key].bind(this)();
                    }
                }
            }
            return this;
        }
    }
});

和我的对象:

var DASHBOARD = {
    _runMe: function(){

    },
    _ready_runMeOnReady: function(){

    },
    _load_runMeOnLoad: function(){

    },
    iAmAString: ''
}._init

这个解决方案似乎适用于 jQuery。但是使用安全吗?我没有看到代码可能导致的任何问题,也没有看到它可能导致的任何其他问题。 如果有人告诉我为什么不应该使用此解决方案,我将非常高兴

我也在尝试了解它是如何工作的细节。理论上,我通过 definePropertyObject.prototype 定义了属性,但没有为其赋值。不知何故,它不会在 jQuery fore in 循环中导致任何错误,为什么?这是否意味着属性 _init 在某些时候或根本没有定义,因为我只定义了它的 getter?

任何帮助将不胜感激:)

最佳答案

不包括 Object.defineProperty(obj, prop, descriptor) 中的描述符JavaScript 将所有 bool 描述符属性默认为 false。即 writable , enumerable , 和 configurable .您的新属性(property)对 for in 是隐藏的迭代器因为你的 _init属性是 enumerable:false .

我不是 JQuery 的粉丝所以不会评论关于 JQuery 的原因

向 JavaScript 的基本类型添加属性没有绝对的规则,这取决于您的代码运行的环境。添加到基本类型会将其添加到全局命名空间。如果您的应用程序与第三方脚本共享命名空间,您可能会发生冲突,导致您的代码或第三方代码或两者都失败。

如果您是唯一的代码,那么冲突将不是问题,但是添加到 object.prototype 将对所有使用对象的代码产生额外的开销。

我强烈建议您重新检查是否需要全局 _init。当然,您不会在每次需要新对象时都使用它。我是 JavaScript 数据结构的 add hock 方法的粉丝,并尽量远离正式的 OOP 范例

关于javascript - 使用 jQuery 时扩展 object.prototype 的替代方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30274543/

相关文章:

javascript - 在 Handlebars 中包含js文件

javascript - 动态添加 Remove font awesome in to span?

javascript - JQuery 检查用户是否在文本区域内输入了特定的字母或单词

javascript - 如何在不返回 Promise 的情况下从对象的 `get()` 获取异步数据

reactjs - 如何在IE8中转换Object.defineProperty

javascript - 组合 fancyBox 脚本

javascript - 如何在nodejs中将项目添加到数组中

javascript - 在 java 脚本中的 setTimeout 方法内调用 setInterval 函数获取 setInterval(...) 不是函数错误

javascript - Wordpress 中的下拉菜单

javascript - javascript中如何防止对象属性不被扩展