JavaScript Method within Method - javascript

I would need to declare Methods within Methods and call them outside as a Object, Method connotation...
To make it more clear:
I need to call:
Object.Method().nestedMethod();
how can I do it so? This failed so far:
function Object(){
this.Method = function(){
this.Method.nestedMethod = function(){
};
};
}
As I work on a DSL it is necessary to call a Method within a Method. In this case the last Method is some kind of recursion Method of the previous one, like this:
Object.execute(param).recursion();
How would I have to declare the nested Method to access this so?

You can return an object that contains nestedMethod:
Object.Method = function () {
return {
nestedMethod: function () {}
};
}

Related

Is it possible to append a method to a constructor/function without prototype property?

function DoIHavePrototype()
{
var a = 10;
}
CheckIt = new DoIHavePrototype();
DoIHavePrototype.prototype.GetFnName = function()
{
return "DoIHavePrototype"
}
alert(CheckIt.GetFnName())
In the above code,I observe that prototype is an in-built property for the function using which we can append property/method to a function.
But if I remove the prototype keyword in the above code like the following:
DoIHavePrototype.GetFnName = function()
{
return "DoIHavePrototype"
}
I don't get error in function definition but instead I get error while calling the method
alert(CheckIt.GetFnName()) as "CheckIt.GetFnName is not a function"
What does the JS interpreter assume this to be??
In order to be able to invoke some function a method on an object, there are 4 ways to introduce it to the object.
The first way is what you've done in your original code, which is to assign the function to the object prototype:
Foo.prototype.myFunc = function () { .... }
Another way is to assign it to this within the constructor.
function Foo() {
this.myFunc = function () { .... }
}
We can also assign it directly to the instance:
var foo = new Foo();
var myFunc = function () { .... }
foo.myFunc = myFunc
Finally, we can bind a function to the instance:
var foo = new Foo();
var myFunc = function () { .... }
var myFuncFoo = myFunc.bind(foo)
The last case is a bit special since we have a function that's not a property of the instance, but behaves like an instance method because it's invocation context is affixed to the instance.
The most common way of defining instance methods is assignment to the prototype. The prototype property on the constructor is what the instances inherit from, so that's where we put stuff. It's important to keep in mind that the instances inherit from the prototype property, not the constructor function. Assigning anything to a constructor property does not make it available as an instance property.
Assignment to this can sometimes be used if we want to have a method that's bound. For instance:
function Foo() {
this.boundMeth = this.meth.bind(this)
this.val = "foo"
}
Foo.prototype.meth = function () {
console.log(this.val)
}
This is useful if we want to pass instance.boundMeth() as a value to another function (e.g., event handler). In JavaScript, unlike many OO languages, methods are unbound:
// Using Foo from the previous example
function runner(fn) {
fn()
}
var obj = new Foo()
runner(obj.meth) // Logs `undefined`
runner(obj.boundMeth) // Logs `foo`
When assigning to the constructor prototype, you can assign in bulk:
Foo.prototype = {
meth1: function () { .... },
meth2: function () { .... },
}
If you use ES6, you can also use the class keyword:
class Foo {
myFunc() { .... }
}
This is the same as Foo.prototype.myFunc = function () { .... }.
If you append your function straight to the class it will generate so called static method which you can only call from you class like in Array.from.
So in your case you should call it using you class (not its instances) like so DoIHavePrototype.GetFnName();
you can read about this on MDN
This can also be done, in case if you still want to use it as instance method.
function DoIHavePrototype()
{
var a = 10;
this.GetFnName = function() {
return "DoIHavePrototype";
}
}
CheckIt = new DoIHavePrototype();
alert(CheckIt.GetFnName())

Use a variable both as function and object instance

I was wondering how does JQuery use "$" both as a function to return a new instance and an instance itself.
I guess that it's not exactly the case but I mean, we can use $(element).method and for exemple $.ajax without brackets (.ajax will still be a method).
EDIT :
I think that I misspoke. I know how objects work in JavaScript and my question was not about that.
JQuery allows us to use $ without the key word new. It has a function that returns a new instance automatically. So my question was about how it can use $ both as a function to instanciate a new object and an object itself.
Let's say we have
(function() {
var jQ = function (arg){
this.own = arg;
};
jQ.prototype = {
foo : function (){
alert("Foo");
},
bar : function (){
alert("Bar");
}
};
window.jQ = window.$ = jQ;
return jQ;
}());
In this exemple, i have to go througth the key word new if I want to use my object.
So how does JQuery do to avoid us this step ?
Function is an object in javascript: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function You can check this code:
var f = function () { alert(1); };
f.func1 = function () { alert(2); };
f.func2 = function () { alert(3); };
and you can call f(), f.func1() and so on...
It's not jQuery. In JavaScript functions are objects.
In the case of $(element).method you are passing a parameter element into the jQuery function, where with the $.ajaxcall you are calling the ajax function inside of the $ jQuery object. In both cases we are talking about the same piece of code, but we are using it two different ways.
Have a look at the raw source code for jQuery and that should help to visualize this a little: https://code.jquery.com/jquery-2.1.1.js
Note: the jQuery function that is used repeatedly is aliased at the bottom of the page.
Remember that in JavaScript, functions are objects. So, using the specific functions you called out in your question, you could create them like this:
var $ = function(selector) {
...
};
$.ajax = function(url) {
...
};
EDIT: To respond to your edited/clarified question, you don't have to use prototyping to make constructor functions in javascript. Remember, all a constructor is doing is returning an object - here's the equivalent of your prototyping code, but without having to use the new operator to instantiate the object:
(function() {
var jQ = function (arg){
return {
own: arg,
foo: function (){
alert("Foo");
},
bar: function (){
alert("Bar");
}
}
};
window.jQ = window.$ = jQ;
return jQ;
}());
I believe this style is actually preferred by Douglas Crockford because forgetting to use the new keyword won't throw an error but you'll get some very unexpected behavior.
JQuery allows us to use $ without the key word new. It has a function that returns a new instance automatically.
Nothing magical here. The jQuery function simply returns an instance of another constructor (source):
// Define a local copy of jQuery
jQuery = function( selector, context ) {
// The jQuery object is actually just the init constructor 'enhanced'
// Need init if jQuery is called (just allow error to be thrown if not included)
return new jQuery.fn.init( selector, context );
},
The only magic going on in the code (not shown in the example) is that jQuery.fn.init.prototype = jQuery.prototype. But jQuery.fn.init is a different function than jQuery.
Applied to your example:
var jQ = function (arg){
return new jQ.prototype.init(arg);
};
jQ.prototype = {
init: function(arg) {
this.own = arg;
},
// ...
};
jQ.prototype.init.prototype = jQ.prototype;

Why this returned function being called without any action to its value?

Look at the following code:
function doNotCallMe(){
alert("Otherwise the world will be destroyed!");
}
function getNotCallable(){
return new function() {
alert("Attention!");
doNotCallMe();
};
}
var not_callable = getNotCallable();
The browser shows the alerts, which it shouldn't be. Why? How to fix?
return function() { ... }
is what you want instead.
All functions in JavaScript will act as object constructors when used with operator new; so you're defining an anonymous function, and then invoking it through new.

Calling nested function when function name is passed as a string

I'm trying to access a nested function by passing the function name in as a string and then calling it. Eg, see this post
function outer(action){
window["outer"][action]();
function inner(){
alert("hello");
}
}
outer("inner");
However it doesn't work. Error:
window.outer[action] is not a function
How to make this work, or an alternative way of calling a nested function.
The reason for this is that I am trying to hide a bunch of functions that are called by an iframe inside a functions scope.
function outer(action){
var inner = {
func1: function() {},
func2: function() {},
func3: function() {},
// ...
}
inner[action]();
}
outer("func1");
In that way you are trying to access the "inner" property of the "outer" function (outer.inner) that is not defined. The only way to do that is by using eval:
function outer(action){
eval(action+"()");
function inner(){
alert("hello");
}
}
outer("inner");
But remember eval is evil is some situations so be careful.

How can I pass methods in javascript?

I often need to pass methods from objects into other objects. However I usually want the method to be attached to the original object (by attached I mean 'this' should refer to the original object). I know a few ways to do this:
a) In the object constructor: ObjectA = function() { var that = this; var method = function(a,b,c) { that.abc = a+b+c }}
b) In objectA which has been passed objectB: objectB.assign(function(a,b,c) { that.method(a,b,c) })
c) Outside both objects: objectB.assign(function(a,b,c) { objectA.method(a,b,c) })
I want to know if there is a simpler way to pass methods attached to their original objects.
You can define a "createDelegate" method for all functions:
Function.prototype.createDelegate = function(scope) {
var method = this;
return function() {
return method.apply(scope, arguments);
}
}
And then use like:
var myDelegate = myFunction.createDelegate(myScope);
calling "myDelegate" will execute "myFunction" with "this" pointing to "myScope" and the same arguments as passed to myDelegate
As long as you call the other method with its appropriate owner object, this will always refer to the correct owner.
You can delegate if you like, or just call the object that lacks the method from the defined method scope-
instance.method.call(Other-Object/*,argument,...*/)
For example, if Array has a filter method, you can call it as if it were a method of a node list object.
var list=document.getElementsByTagName('p'), a=[],
list= a.filter.call(list,function(itm){return itm.className=='sidebar'});

Categories