扩展现有Object以添加其他JavaScript Prototype方法

时间:2015-07-09 22:22:00

标签: javascript prototype extend

让我们说我有一个类似下面的函数创建一个非常简单的微库:

var microLib = function(selector) {
    var el;
    var selectorEngine = function(selector)
    {
        var selector_value = selector.slice(1);
        return document.getElementById(selector_value);
    };

    el = selectorEngine(selector);

    Element.prototype.func_1 = function(){
        return 'first';
    };

    Element.prototype.func_2 = function(){
        return 'second';
    };

    return el;
};
window._$ = microLib;

这个脚本允许我编写如下代码:

var elem = _$("#div_with_id");   //some element on my web page
console.log(elem.func_2());      //outputs 'second' in the console 

现在,我正在寻找一种方法,在补充代码中扩展_$以添加额外的Element.prototype方法,这将允许我写:

console.log(elem.func_3());    //to output 'third' in the console

我需要这样做的原因是因为这个扩展需要在另一个JavaScript文件中进行,否则我会添加另一个方法并完成它。

我该怎么做?

2 个答案:

答案 0 :(得分:2)

以下是我建议的方法示例:http://jsfiddle.net/rbxssmx8/

JS:

var toArray = Function.prototype.call.bind(Array.prototype.slice);
var qAll = document.querySelectorAll.bind(document);

var _$ = (function() {
    function dom(selector) {
        if(!(this instanceof dom)) {
            return new dom(selector);
        }

        this.elements = toArray(qAll(selector));
    }    

    dom.prototype.iterate = function(func) {
        this.elements.forEach(func);
        return this;
    };

    dom.prototype.addClass = function() {
        var klasses = arguments;
        return this.iterate(function(element) {
            element.classList.add.apply(element.classList, klasses);
        });
    };

    dom.extend = function(name, func) {
        this.prototype[name] = func;    
    };

    dom.ready = function(func) {
        document.addEventListener("DOMContentLoaded", func);    
    };

    return dom;
})();

_$.extend("removeClass", function() {
    var klasses = arguments;
    return this.iterate(function(element) {
        element.classList.remove.apply(element.classList, klasses);    
    });
});

_$("div").addClass("gray");
var $el = _$("div:last-of-type");
$el.removeClass("gray");

答案 1 :(得分:1)

所以我在What's wrong with extending the DOM上阅读了这篇文章,作者建议的另一种方法是使用Object Wrappers。通过快速搜索,我就可以看到这篇文章:Using object wrappers to extend the JavaScripts DOM?

再加上来自@ DRD答案的一些见解,我更新了我的代码:

(function() {

    var microLib = function (selector){
        return new Dom(selector);
    };

    function Dom(selector)
    {
        var selector_value = selector.slice(1);
        this.element = document.getElementById(selector_value);
    }

    Dom.prototype.func_1 = function(){
        return 'first';
    };

    Dom.prototype.func_2 = function(){
        return 'second';
    };

    microLib.extend = function(name, func){
        Dom.prototype[name] = func;
    };

    window._$ = microLib;

})();

然后,只要您想扩展并添加其他功能,请在此之后执行此操作:

_$.extend('func_3', function(){ //this is inline with my earlier question
     return 'third';
});

像魅力一样!与扩展Element.prototype相比,更安全选项肯定是。