I'm currently learning prototyping in javascript, i wrote the below and it seems to work fine when i use it. my question was why do i need the () at the end of the prototype declaration, without that if i try to make an instance of the object I get an error.
var MyTest = function (agencyId, dataId) {
this.agencyId= agencyId;
this.dataId= dataId;
};
MyTest.prototype = function () {
var setObservables = function () {
...
},
init = function (url) {
...
};
// public members
return {
init: init
};
}();
to use it I call it like
var obj = new DetailsDivisionKO(1, 2);
obj.init(actionUrl);
this works fine, but I'm confused about the }(); at the end of the public members section, why is that needed and I can not have that and still use the above code to call it? As without that if i try to call the above code I get a error stating:
Uncaught TypeError: Object [object Object] has no method 'init'
What you have is an IIFE. Its an imidiately invoked function. You are basically creating a closure. You are exposing your init function while preserving a true private scope to your setObservables function. So every time you create a new instance of the constructor, your init function will always be in the prototype. But setObservables will not. In your example you could only access setObservables function internally (hence private scope). Usually you would do that if you only want your init function to call your private functions which in your case is setObservables. But if this is not what you want, you simply can do this:
var MyTest = function (agencyId, dataId) {
this.agencyId= agencyId;
this.dataId= dataId;
};
MyTest.prototype = {
setObservables: function () {
...
},
init: function (url) {
...
}
}
Now every time you will create a new instance of MyTest, both of your functions will be in its prototype.
var test = new MyTest(1, 2);
test.init();
test.setObservables();
Related
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())
Shouldn't hello be printed in the console because of the return statement? The code is immediately invoked because of the () at the end so why isn't it printing?
var Module = (function () {
var privateMethod = function () {
// private
};
var someMethod = function () {
// public
console.log('hello');
};
var anotherMethod = function () {
// public
};
return {
someMethod: someMethod,
anotherMethod: anotherMethod
};
})();
return {
someMethod: someMethod, // just a function reference
anotherMethod: anotherMethod // again a function reference
};
So, you're not calling the function. You're just returning the function reference attached to a property of an object. Try to use comma operator here, which evaluates to the right most statement, whilst executing someMethod() function.
return {
someMethod: someMethod(), someMethod, // first getting called and someMethod ref is passed to the property
anotherMethod: anotherMethod
};
It's because of the var keyword on the top infront of Module.
f you do the following in the console:
var a = 5 // a is set to 5 yet undefined is shown in the console.
If you were to take off the var keyword:
a = 5 // a is again set to 5 yet 5 is shown in the console.
But in your real code you would want to use the var keyword.
So simply put it's just the console's way of outputting like that, idk why.
Enlighting more,
function itseld is object of Function (see https://msdn.microsoft.com/en-us/library/ie/x844tc74%28v=vs.94%29.aspx)
So Basically you are adding a reference to object of type Function, which is not IIFE.
I thought I understood the javascript prototype object and how to use it, but now I've run into something that has me a little stumped. When trying to run the code below mpo.testFire() fires with no issues, but I get the error Uncaught TypeError: Object # has no method 'fireAlert' when trying to invoke mpo.fireAlert() which I thought was part of the prototype:
<body>
Click Me
</body>
// Click handler, create new object
// call parent method and prototype method
$("#testBtn").click(function(e) {
e.preventDefault();
var mpo = new Myobject();
mpo.testFire();
mpo.fireAlert();
});
Myobject = function () {
var testFire = function () {
alert('testFire');
};
return {
testFire:testFire
};
};
Myobject.prototype = function() {
var fireAlert = function() {
alert('made it to fireAlert');
};
return {
fireAlert:fireAlert
};
}();
If I change the code and move everything to the object's prototype like the code below everything works as expected:
$("#testBtn").click(function(e) {
e.preventDefault();
var mpo = new Myobject();
mpo.testFire();
mpo.fireAlert();
});
Myobject = function () {
// constructor logic here maybe?
};
Myobject.prototype = function() {
var fireAlert = function() {
alert('made it to fireAlert');
};
var testFire = function () {
alert('testFire');
};
return {
fireAlert:fireAlert,
testFire:testFire
};
}();
I'm guessing there is a scope issue since in the first example I return an interface from the parent object. Can anyone explain why the first example does not work?
You are returning an object literal from your first implementation of MyObject constructor which knows nothing of the prototype chain MyObject is part of. In the second implementation the empty constructor returns the new context that was created which is in fact a MyObject object which knows about the appropriate prototype chain
You're returning an object literal
return {
testFire:testFire
};
which "overrides" the result from new (because it's an object. Returning, for example, a string literal would return the created object).
This is in ES5 spec 13.2.2.
I have this code here:
var myRequest = new httpReq.myRequest(buffer,socket);
if(!myRequest.hasSucceded()){ //return error
return;
}
arr=myRequest.getCookies();
....
and i definitely have this function on my myRequest object:
function myRequest(buffer, socket) {
...
this.cookies = new Array();
...
//returns the cookie array
function getCookies() {
return this.cookies;
}
...
}
exports.myRequest = myRequest;
and i get an error saying:
TypeError: Object #<myRequest> has no method 'getCookies'
Y U NO GIVE COOKIES???
help please...
You are declaring getCookies as a local function.
To call it externally, you need to create a property getCookies on your object so you can call it.
Try this:
function myRequest(buffer, socket) {
...
this.cookies = new Array();
...
//returns the cookie array
this.getCookies = function() {
return this.cookies;
}
...
}
You also could just do myRequest.cookies instead of myRequest.getCookies()
function myRequest(buffer, socket) {
this.cookies = [];
}
myRequest.prototype.getCookies = function () {
return this.cookies;
};
First, declaring getCookies inside constructor directly causes this method to be a private method, which only lives within the constructor.
Second, usually it is considered a good practice to define the prototype getCookies outside the constructor. If it is defined in the constructor (like, this.getCookies = function () {...}), this method would need to be initialized every time when this prototype is instantiated.
i have JavaScript components, that has following architecture:
var MyComponent = function(params)
{
setup(params);
this.doSomething()
{
// doing something
};
function setup(params)
{
// Setup
// Interaction logic
var _this = this; // "this" points to DOMWindow, not to created object
$(".some-element").click(function(){
_this.doSomething(); // it craches here, because of above
});
}
};
When something, being controlled by interaction logic, happens, sometimes i must forward execution to "public" methods of component.
In this situation, i have a problem with "this" pointer.
Sample code demonstrates it:
var Item = function()
{
this.say = function()
{
alert("hello");
};
this.sayInternal = function()
{
_sayInternal();
};
function _sayInternal()
{
this.say();
};
};
To test it,
Create an object:
var o = new Item();
This works fine:
o.say(); // alerts "hello"
This crashes:
o.sayInternal();
I get an error:
TypeError: Result of expression 'this.say' [undefined] is not a function.
I think, such a behaviour takes place, because _sayInternal() function is declared (and not assigned to object, like "this.say = function()"). This way, it is shared across all created objects and acts like a static function in C++.
Is this true ?
No, sayInternal is not shared between created objects. But you are right, the created objects don't have access to sayInternal as it is not assigned to them. This function is only local to the constructor function.
this always refers to the context a function is invoked in. If you call it like func(), then this refers to the global object (which is window in browser). If you set the function as property of an object and call it with obj.func(), then this will refer to obj.
If you assign a "bound" function to a variable and call it:
var method = obj.func;
method();
then this will again refer to the global object. In JavaScript, functions are like any other value, they don't have a special relationship to the object they are assigned to.
You can explicitly set the context with call or apply:
var MyComponent = function(params)
{
setup.call(this, params); // <- using `call`
this.doSomething()
{
// doing something
};
function setup(params)
{
// Setup
// Interaction logic
var _this = this; // "this" to new created object
$(".some-element").click(function(){
_this.doSomething();
});
}
};
or in you other example:
var Item = function()
{
this.say = function()
{
alert("hello");
};
this.sayInternal = function()
{
_sayInternal.call(this);
};
function _sayInternal()
{
this.say();
};
};
That said, this approach to assign functions to objects is not good, because every instance will have its own this.sayInternal function. So for the Item code above, every creation of an instance involves creating three functions too, which is a waste of memory.
Making use of prototype inheritance would be a better way:
var Item = function() {
};
Item.prototype = (function() {
function _sayInternal() {
this.say();
};
return {
say: function() {
alert("hello");
},
sayInternal: function(){
_sayInternal.call(this);
}
}
}());
This way, _sayInternal is only created once and all instances inherit (refer to) the prototype, so say and sayInternal also exist only once. The "trick" with the immediate function makes _sayInternal only accessible by say and sayInternal.