Reputation: 2665
I made an object like this:
var MyObj = function(arg)
{
var PublicMethods = {
SomeMethod: function(someArg)
{
if(SomeCheck(arg)
{
PublicMethods.SomeFunc2 = somethingElse;
}
}
};
return PublicMethods;
};
However MyObj
doesn't seem to be persistent and between calls, PublicMethods
doesnt preserve the new methods added to it, so I tried moving it to global scope, however then it doesn't recognize the 'args
' passed from MyObj
anymore.
If I make MyObj
like this:
var MyObj = (function()
{
//..
}());
Then it becomes a persistent object, but I'm not sure - can I call it like a function again?
jQuery
seems to have a persistent object and at the same time it can be called like a function, how do they achieve that?
I want to be able to do this:
MyObj("Something Here").SomeMethod("Something Else");
and thus to be able to create a SomeFunc2 method that I can later call too:
MyObj("Something Here").SomeFunc2("Something Else");
Upvotes: 2
Views: 366
Reputation: 1
You can create a jQuery method which extends jQuery
or jQuery.fn
and can also set this
context within the method.
(function($) {
jQuery.addMethod = function addMethod({methodName, method, type}) {
let bool = {
[type]: false
};
let _jQuery_jQueryFn_ = Object.keys(bool).pop();
if (type === "jQuery") {
for (let prop in jQuery) {
if (prop === methodName
|| prop.toUpperCase() === methodName.toUpperCase()) {
bool[type] = true;
break;
}
}
}
if (type === "fn") {
for (let prop in jQuery.fn) {
if (prop === methodName
|| prop.toUpperCase() === methodName.toUpperCase()) {
bool[type] = true;
break;
}
}
}
if (type === "jQuery" && bool[_jQuery_jQueryFn_] === false) {
jQuery[methodName] = method;
}
if (type === "fn" && bool[_jQuery_jQueryFn_] === false) {
jQuery[type][methodName] = method;
}
if (bool[_jQuery_jQueryFn_] === true) {
return Promise.reject(
new ReferenceError(
methodName
+ " previously defined at "
+ _jQuery_jQueryFn_
));
} else {
console.log(methodName + " defined at " + _jQuery_jQueryFn_);
}
return {methodName:methodName, type};
}
})(jQuery);
$(function() {
Promise.resolve($.addMethod({
methodName: "add",
method: function add(a, b, context) {
console.log(a + b);
return (context || this)
},
type: "jQuery"
}))
.then(function({methodName, type}) {
if (type === "jQuery" && methodName in window[type]) {
jQuery[methodName](10, 10)
} else {
if (methodName in window["jQuery"][type]) {
jQuery[type][methodName](10, 10);
}
}
})
.catch(function(err) {
console.error(err)
});
});
$(function() {
Promise.resolve($.addMethod({
methodName: "add",
method: function add(a, b, context) {
console.log(a + b);
return (context || this)
},
type: "fn"
}))
.then(function({methodName, type}) {
if (methodName === "jQuery" && methodName in window[type]) {
jQuery[methodName](10, 10)
} else {
if (methodName in window["jQuery"][type]) {
jQuery("span")[methodName](10, 10);
}
}
})
.catch(function(err) {
console.error(err)
});
});
$(function() {
Promise.resolve(
$.addMethod({
methodName: "reverseText",
method: function reverseText(_text, context) {
let text = [...(_text || this.text())].reverse().join("");
(context || this).text(text);
return (context || this)
},
type: "fn"
}))
.then(function({methodName, type}) {
if (type === "jQuery" && methodName in window[type]) {
jQuery[methodName]()
} else {
if (methodName in window["jQuery"][type]) {
// set context `this` to `span`
let span = jQuery("section")[methodName]("321", $("span"))
.css("color", "sienna");
console.log(
span.is(document.querySelector("span"))
);
jQuery("section")[methodName]()
.css("color", "green");
}
}
})
.catch(function(err) {
console.error(err)
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js">
</script>
<section>section</section>
<span>span</span>
Upvotes: 0
Reputation: 1053
Simply store the result of the initial MyObj
call in a local variable:
var obj = MyObj("Something Here");
obj.SomeMethod("Something Else");
obj.SomeFunc2("Something else");
The PublicMethods
variable is specific to each call of MyObj
, so when you call MyObj
for the second time, you get a different instance of PublicMethods
. By using a variable to store the result of the first MyObj
call, you can use the same instance of PublicMethods
for both the SomeMethod
and SomeFunc2
functions.
As a side note, you may want to look into constructor functions which would allow you to define functions more simply, instead of returning an object. For example:
function Example() {
this.a = function() {
return "a";
};
this.b = function() {
this.a = function() {
return "b";
}
}
}
var example = new Example();
example.a(); // => "a"
example.b();
example.a(); // => "b"
Upvotes: 1