May I ask how can I call function c on below situation?? Thank you very much for your advice.
var Foo = function(el){}
Foo.prototype.d = function(){
// I want to call function c here, how can I do??
};
$.fn.a = function(){
return {
b: new Foo(this)
};
};
$.fn.a.prototype.c = function(){ alert(1); }; //function c
$(el).a().b.d() <-reach c...
You don't have an instance of a that was constructed with the new keyword. So you will have to use call or apply.
Foo.prototype.d = function(){
$.fn.a.prototype.c.apply(this, arguments);
};
This will run c on the Foo instance - is that what you want? If you just want to call the function without an specific execution context you can use $.fn.a.prototype.c().
This probably isn't the best way to architect this - if you want to call it as a member function of Foo don't add it as a member function of $.fn.a.
Related
I'm kind of new to javascript. I'm so confused that javascript Objects!!
My code skeleton is bellow...
var jCanvas = new function(){
this.init = function(canvasID){
...
};
var DrawingManager = new function(){
drawInfos = []; // DrawInfo objects will be pushed into this
this.mouseState = MouseState.released;
...
};
function DrawInfo(bm, cl, id, x, y){
...
}
function Point(x, y){
...
}
var MouseState = new function(){
...
};
var Color = new function(){
...
};
var BrushMode = new function(){
...
};
};
I want jCanvas to be singleton class Object.
in jCanvas object, there are many singleton classes such as DrawingManager, MouseState, Color, BrushMode. And 2 more classes which are not singleton classes(Point, DrawInfo)
What I want is that, in DrawingManager, I want to access other classes and singleton class objects.
Problem is browser gives error that "MouseState is undefined".
I think I'm too familiar with Java, C# etc... I want my program to have good structure but this javascript make me so confused and don't know how to make good design pattern..
Please help me out..
To declare functions, don't use the new keyword. Only use it when creating instances of objects.
In JavaScript, you can declare a "class" like this (the body of the function is the constructor):
function MyClass (arg1) {
this.myClassProperty = arg1;
}
And then instantiate it:
var myObj = new MyClass();
If you want to create a singleton, the best method is to use an immediately invoked function:
var MySingleton = (function() {
var myPrivateFunction = function() { ... };
var myExportedFunction = function() { ... };
var myPrivateVar = 5;
return {
myExportedFunction: myExportedFunction
};
})();
Here, you create an anonymous function and immediately run it. It is kind of a more advanced concept though.
Or you can simply create an object:
var MySingleton = {
myProperty: 1,
myFunction: function() { ... },
...
};
Singleton classes in JavaScript make no sense. Either make a constructor ("class" for Java people) to instantiate multiple objects, or make an object. There is no point in making a constructor that you will only ever use once, then have the code to sanity-check whether or not you actually do use it only once. Just make an object.
The reason for the error is probably (but I might be wrong, I'm guessing about the rest of your code) the misunderstanding between var x = function ... and function name() ... forms. To whit:
var a = function() { console.log("a"); }
function b() { console.log("b"); }
a(); // a
b(); // b
c(); // c
d(); // TypeError: d is not a function
function c() { console.log("c"); }
var d = function() { console.log("d"); }
They are identical in effect, but they differ in whether they are hoisted to the top of the scope or not. var d is hoisted, just like function c() { ... } - so the variable d will exist, but will be undefined, since the assignment is not hoisted. Having both styles of function declarations is inconsistent unless you have a good reason for it; pick one of them and stick to it, is what I'd recommend.
Ok, I can't find a better and clearer title, but basically I've got this:
var obj = function () {
return {
hi: function (name) {
console.log("HI! " + name);
},
fun1: (function (cllb, name) {
//WRONG!! I'm binding the callback not the hi function
var f = cllb.call(this, name)
}).bind(this)
}
}
I call fun1 like this:
var q = new obj()
q.fun1(function () {
hi("paco")
})
Notice how I use hi("paco") and not this.hi("paco"). I need to avoid the this inside the callback. I know that it's not the most pragmatic and logic way, but in my real code the reasons are more obvious. Is it possible to do it in Javascript?
Maybe the closest your gonna get.
function thing(){
this.fun1 = function(cb){
var b = 'this.'+cb();
var c = new Function(b);
c.call(this);
};
}
var t = new thing();
thing.fun1(function(){
return 'hi("paco");';
});
Unless you pass hi as argument to the callback, there is no way to just call hi(..). JavaScript has a lexical scope, and hi is not in the scope of the callback.
Is it possible to do it in Javascript?"
The answer is simply no.
Basically I want to do this:
someFunction() // do something
someFunction.somePropertyFunction()
someFunction() // Now someFunction is modified; it should now exhibit a different behaviour
Is this possible?
EDIT:
I'm not looking for what #Kolink was suggesting. Basically I want to augment a function's functionality by calling one of it's property function.
Specifically, I need to: 1. have access to the original function inside my property function (which is entirely doable using this), and 2. bind a new function to the original function's name (which I'm not sure if it's possible).
Just to be clear, I don't have access to the internal definition of the function that I want to augment. I want to attach a function to Function.prototype (so that it will be available as a property of the function that I want to augment), and then I will call func.augmentThis(), and then func should be augmented. But I'm not sure how, hence the question :P
Easily. Here's an example:
var derp = 123;
someFunction = function() {alert(derp);};
someFunction.somePropertyFunction = function() {derp = 456;};
someFunction(); // alerts 123
someFunction.somePropertyFunction();
someFunction(); // alerts 456
Okay, that's an oversimplified example, but yeah, it's entirely possible.
If your question is whether a function attached as a property to another function has a way to access the function to which it is attached, the answer is no. After all, the same function could be attached to any number of functions of objects.
So one alternative is to explicitly refer to the "mother" function within the function that is attached to it and intended to change its behavior:
function f (n) { alert (n + f.offset); }
f.offset = 0;
f.change_offset = function (i) { f.offset = i; };
f (1); //1
f.change_offset (100);
f (1); //101
Here, f is hard-wired into the definition of change_offset. If this bothers you, or you want something slightly more general, write a little routine to set a function as a property on another function, while binding its this to the function being attached to:
function set_func_as_func_prop ( propname, func_to_set, func_to_set_on ) {
func_to_set_on[propname] = func_to_set.bind(func_to_set_on);
}
Now you can write the function more generally
function change_offset (i) {
this.offset = i;
}
and set it on f or any other function.
set_func_as_func_prop ("change_offset", change_offset, f);
set_func_as_func_prop ("change_offset", change_offset, g);
Sort of:
function someFunction() {
return realFunction.apply(this, arguments);
}
function someFunctionA(name) {
return 'Hello, ' + name + '!';
}
function someFunctionB(name) {
return 'Goodbye, ' + name + '...';
}
var realFunction = someFunctionA;
someFunction.somePropertyFunction = function () {
realFunction = someFunctionB;
};
Sure it's possible. It's not recommended, but it's possible. For example:
function a() {
alert("a");
}
function b() {
alert("b");
}
function c() {
return c.f.apply(this, arguments);
}
c.f = a;
c.toggle = function () {
c.f = c.f === a ? b : a;
};
Now let's test it:
c(); // alerts "a"
c.toggle();
c(); // alerts "b"
See the demo: http://jsfiddle.net/LwKM3/
I want to attach a function to Function.prototype. Then I need to bind a new function to the original function's name (which I'm not sure if it's possible).
That indeed is impossible, you don't know what refers to the function. And you cannot change the internal representation of a function, which is immutable.
The only thing you can do is to create a new function and return that, to let the caller of your method use it somehow - specifically assigning it to the original variable:
somefunction = somefunction.augmentSomehow();
Your method for that will look like this:
Function.prototype.augmentSomehow = function() {
var origFn = this;
return function() {
// in here, do something special
// which might include invoking origFn() in a different way
};
};
Not sure if this helps, but I would implement described problem in following way:
// defined by somebody else - unknown to developer
var someFunction = function() {
alert("this is initial behavior");
}
someFunction(); // returns "this is initial behavior"
// defines parent object on which someFunction() is called
var parentObject = this; // returns window object (as called direclty in the
// browser)
// if you are calling someFunction from some object (object.someFunction())
// it would be:
// var parentObject = object;
// augumentThis definition
someFunction.augumentThis = function() {
var newFunction = function() {
alert("this is changed behavior");
};
parentObject.someFunction.somePropertyFunction = function() {
parentObject.someFunction = newFunction;
parentObject.someFunction();
};
};
someFunction.augumentThis(); // change function behavior
someFunction(); // "this is initial behavior"
someFunction.somePropertyFunction(); // "this is changed behavior"
someFunction(); // "this is changed behavior"
Could someone please explain the significance of prototype.init function in JavaScript and when it is called during object instantiation?
Why would you want to overwrite it with an empty function?
I am reading the JavaScript for Web book and am stuck on the this for the past few hours...what is piece of code supposed to achieve?
var Class = function(){
var klass = function(){
this.init.apply(this, arguments);
};
klass.prototype.init = function(){};
// Shortcut to access prototype
klass.fn = klass.prototype;
// Shortcut to access class
klass.fn.parent = klass;
...
}
This is just too much magic for me...:)
I'm not sure what you don't understand. init is simply a method like any other, that happens to be called in the constructor and with the same parameters as the constructor. If it's empty then it's just because the person who wrote it didn't need to put anything in it for now but wanted to lay down the groundworks of his class.
function Foo(a, b, c) {
this.init.apply(this, arguments); //This simply calls init with the arguments from Foo
}
Foo.prototype.init = function(a, b, c) {
console.log(a, b, c);
}
var f = new Foo(1, 2, 3); //prints 1 2 3
http://jsfiddle.net/Hmgch/
what is piece of code supposed to achieve?
Confusion.
var Class = function() {
// initialization logic
}
// Shortcut to access prototype
Class.fn = klass.prototype;
// Shortcut to access class
Class.fn.constructor = Class;
I've been messing around with using Node.js and CouchDB. What I want to be able to do is make a db call within an object. Here is the scenario that I am looking at right now:
var foo = new function(){
this.bar = null;
var bar;
calltoDb( ... , function(){
// what i want to do:
// this.bar = dbResponse.bar;
bar = dbResponse.bar;
});
this.bar = bar;
}
The issue with all of this is that the CouchDB callback is asynchronous, and "this.bar" is now within the scope of the callback function, not the class. Does anyone have any ideas for accomplishing what I want to? I would prefer not to have a handler object that has to make the db calls for the objects, but right now I am really stumped with the issue of it being asynchronous.
Just keep a reference to the this around:
function Foo() {
var that = this; // get a reference to the current 'this'
this.bar = null;
calltoDb( ... , function(){
that.bar = dbResponse.bar;
// closure ftw, 'that' still points to the old 'this'
// even though the function gets called in a different context than 'Foo'
// 'that' is still in the scope and can therefore be used
});
};
// this is the correct way to use the new keyword
var myFoo = new Foo(); // create a new instance of 'Foo' and bind it to 'myFoo'
Save a reference to this, like so:
var foo = this;
calltoDb( ... , function(){
// what i want to do:
// this.bar = dbResponse.bar;
foo.bar = dbResponse.bar;
});