如何在javascript中编写具有扩展功能的函数?

如何在javascript中编写具有扩展功能的函数?,javascript,html,Javascript,Html,我尝试实现一个函数,例如MyFn(),具有以下一些特性: 1.MyFn('Id')>它必须是document.getElementById('Id')的结果值 2.MyFn('Id').MyMethode();>它必须是执行功能的结果。 以下是通过“Object.prototype”实现的: Object.prototype.MyFn =function(param1){ return document.getElementById(param1); }; alert( MyFn('mydiv1

我尝试实现一个函数,例如
MyFn()
,具有以下一些特性:
1.MyFn('Id')>它必须是document.getElementById('Id')的结果值
2.MyFn('Id').MyMethode();>它必须是执行功能的结果。
以下是通过“Object.prototype”实现的:

Object.prototype.MyFn =function(param1){ return document.getElementById(param1); };
alert( MyFn('mydiv1') );
MyFn('mydiv1').posi = function() { alert("Hello, I'm the function posi!"); };
MyFn('mydiv1').posi();
alert( MyFn('mydiv1') );
上面的例子就是我想要实现的。但我不想使用Object.prototype或jQuery。
下面是我的错误方法(这可能是我想说或想做的有益的):

var MyObj={
方法:函数(参数、回调){
if(回调类型==“函数”){
回调();
}
返回123;
}
}
MyFn=函数(sId){
返回MyObj;
};
警报(MyFn(“mydiv1”).method());//这是可以的,因为它按预期调用了方法:MyObj.method()。

警报(MyFn(“mydiv1”);// 丑陋,几乎所有设计人员都不推荐,但应该有效:

MyFn = function(sId) {
    var obj = document.getElementById(param1);

    obj.method = function(args, callback) {
        if(typeof callback == "function") {
            callback();
        }
        return 123;
    }
    return MyObj;
};
基本上,您可以手动将功能添加到对象


这不是一个好的设计模式,因为外部的人不会事先知道对象有一个额外的方法。

这是一个有点老套的解决方案:

var MyObj = function (id) {
    var obj = document.getElementById(id);
    // attach functions here
    obj.myFun = function () {
        // ...
    }
    // ...
    return obj;
}

获取对象后,将自己的函数附加到对象上(最好不要重新定义现有函数),然后返回它。

您可以尝试以下操作:

var MyObj = {
    method: function(args, callback) {
        if(typeof callback == "function") {
            callback();
        }
        return 123;
    }
}

var MyFn = function(sId) { 
    this.elem = document.getElementById(sId);
    this.MyObj = MyObj;
    return this;
};

alert( MyFn("mydiv1").MyObj.method() ); 
alert( MyFn("mydiv1").elem ); 

这将在函数执行后返回对函数的引用,因此提供了与C#扩展方法类似的语法

应该非常直截了当,因为函数也是对象。
通常的做法,以及jQuery的做法,是返回函数的新实例,这是通过简单的检查完成的

function MyFn(selector, context) {

    if ( !(this instanceof MyFn) ) { // not an instance

        return new MyFn(arguments);  // calls itself with the "new" keyword

    } else { // now it is an instance

        context = context || document;
        this[0] = context.getElementById(id);
    }

    return this;
}
在此基础上,我们可以添加方法,但这需要对它们进行原型化,这是正确的方法

MyFn.prototype.width = function() {
    return this[0].style.width;
}
甚至使这些方法可以链接

MyFn.prototype.width = function(width) {

    if ( width ) {
        this[0].style.width = width + 'px';
        return this;
    } else {
        return this[0].style.width;
    }

}

同一输入不能从单个函数返回两个不同的结果。您可以返回HtmleElement对象,也可以返回自己的对象
MyFn(id)
将始终返回相同的结果-不管您以后想对它做什么(例如
.method()
),这是正确的!但正如我上面解释的,我想以某种方式取得一些成就。例如,jQuery可以执行类似的操作。例如$('#Id')和$('#Id').position().left.jQuery不返回HtmleElement。它返回一个具有许多功能的jQuery包装器对象(例如
position()
)。当需要actuall元素时,可以调用
.get()
。这几乎就是我想要实现的。我认为通过一些小技巧和一些函数,如.apply()、.call()或.bind()就可以完成。但是我不知道如何:)是的,您可以使用MyFunc.call(MyObj)将对象添加到函数对象中。JavaScript是关于技巧的,这就是为什么我喜欢它:)1。我可以调用alert(element.width())之类的函数;2.我可以获取id警报(元素[0].id);3.我可以得到如下参考:alert(MyFn('mydiv1')[0]);很不错的。但如果“[0]”可以被删除,那就更好了。也许通过一些小技巧和一些函数,比如.apply(),.call()it.bind()就可以完成:是的,您可以在某些实例中消除
[0]
,例如jQuery对许多方法都这样做,它自动使用集合中的第一个元素,并且它还提供类似
eq
的方法来选择集合中的某个元素。当然,您可以用
this.elem
或其他东西替换
[0]
,如果您只有一个元素,但该元素必须存储在某个地方,并且不能直接返回,否则方法将无法链接,必须返回对象实例才能执行此操作。
MyFn.prototype.width = function(width) {

    if ( width ) {
        this[0].style.width = width + 'px';
        return this;
    } else {
        return this[0].style.width;
    }

}