In example:
function foo() {
var bar = this.bar = function () {
return "bar";
};
this.mybar = function () {
return bar();
}
}
var myFoo = new foo();
myFoo.bar = function() {
return "notbar";
};
myFoo.bar(); // returns 'notbar'
myFoo.mybar(); // returns "bar"
Basically it allows for an internal private method to a closure, with the possibility of being overwritten only for external access. So the reference to the original function never changes, for references of that function within the closure. But instantiators of the closure object can overwrite that function without breaking the functionality of the object.
Is there a name for this particular construct, and is it even useful?
If you refer to assigning a function to a local variable and using this function in another public method, then yes, this would some form of data encapsulation. Apart from that, I'd say there is not special name for that.
var bar is a variable local to the function and this.bar is a property of the new object. The variable and the property happen to have the same name, but they are not related.
It is only useful if you want to make the function in bar publicly accessible and ensure the correct working of the other function, in case the public bar is overwritten.
So it is some form of protecting the other functions, but it is not a special pattern to allow external overwriting.
If the sole purpose of this.bar is to be overwritten, then you'd achieve the same with:
function foo() {
var bar = function () {
return "bar";
};
this.mybar = function () {
return bar();
}
}
var myFoo = new foo();
myFoo.bar = function() {
return "notbar";
};
myFoo.bar(); // returns 'notbar'
myFoo.mybar(); // returns "bar"
Of course, if you call myFoo.bar() before you assign a function to it, then you will get an error.
Related
Learning JavaScript Fundamentals, confused on what the function calls return.
I have an idea of f.bar returns 7 because when the f object is created it gets access to functions of Foo that have the "this" keyword. Also I believe f.baz returns an error because this function is only available locally and does not use the "this" keyword which makes it unavailable outside Foo. f.biz I am confused but I do know the Prototype keyword allows for inheritance of Foo properties.
An explanation for each function call would be awesome, thank you everyone!
var Foo = function(a){
this.bar = () => {
return a;
}
var baz = function(){
return a;
}
Foo.prototype = {
biz: () => {
return this.bar();
}
}
}
var f = new Foo(7);
f.bar();// what does this return?
f.baz(); // what does this return?
f.biz(); // what does this return?
As it is now, only the bar function will work as intended.
The baz function is in a local variable, so it's only accessible inside the Foo function as baz but not as this.baz (variables and instance properties (this.whatever) are not connected in any way).
The case of biz is a bit more complicated. Normally, that's more or less how you'd create a prototype method, but you did it in the wrong place. It should be outside the function, because the way it is now, it's:
reassigned on every call of new Foo() (unnecessary)
assigned only after the current instance is created, so it will take effect only on the next instance (also if you used a in it (which you shouldn't), you'd find that it always has the a of the previous call)
You also don't want to use an arrow function when you want to "let JS set this" (arrow functions copy their this from where they were defined).
So, to make biz work, you have to do this:
var Foo = function(a){
this.bar = () => {
return a;
}
}
Foo.prototype = {
biz: function (){
return this.bar();
}
}
var f = new Foo(7);
console.log(f.bar());
console.log(f.biz());
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())
I am just starting to learn Javascript and was experimenting with functions. I wrote the following thinking that it would work. Is something like this possible or is it just wrong?
function foo() {
console.log(this.language);
}
foo.language = "English";
foo();
It is not possible, because to gain access to this as the current object, you'll need to instantiate the (constructor) function, which is what invoking new will do for you. Accessing this for a reference to the current instance is not only the case in Javascript though; in Java, this also isn't accessible from static context.
What you're looking for is something like:
function Foo(language) {
this.language = language;
}
Foo.prototype.log = function(){
console.log(this.language);
}
var bar = new Foo("English");
bar.log();
You can make a foo object (an instance of foo) using the new keyword. Then set the language property of that instance. If foo has a function to output its language property, then you can invoke that function on your instance to see its language.
function foo() {
this.outputLanguage = function() {
console.log(this.language);
}
}
var f1 = new foo();
f1.language = "English";
var f2 = new foo();
f2.language = "French";
f1.outputLanguage();
f2.outputLanguage();
In this example, we make 2 foo objects, and assign each a different language.
The foo() function is a constructor function. We usually pass the initial values of the instance variables to it, like this:
function foo(language) {
this.language = language;
this.outputLanguage = function() {
console.log(this.language);
}
}
var f1 = new foo("English");
var f2 = new foo("French");
f1.outputLanguage();
f2.outputLanguage();
Javascript only supports prototypal Inheritance. So to assign a property (in your case language is the property) to an Object (in your case foo) you need to use constructor. And by convention constructor are written Initcap.
function Foo(lang){
this.language = lang;
}
Foo.prototype.getLanguage = function(){
return this.language;
}
var lang1 = new Foo('english');
var lang2 = new Foo('bengali');
console.log(lang1.getLanguage()); // english
console.log(lang2.getLanguage()); // bengali
this is available on instance variables, in your case it's named function
function foo() {
console.log(foo.language); //instead of this, use function property
}
foo.language = "English";
foo();
If you want to dive more, checkout my other answer for the same topic
I have a question on 'call' in javascript.
var humanWithHand = function(){
this.raiseHand = function(){
alert("raise hand");
}
}
var humanWithFoot = function(){
this.raiseFoot = function(){
alert("raise foot");
}
}
var human = function(){
humanWithHand.call( this );
humanWithFoot.call( this );
}
var test = new human();
so..when I use 'call' as humanWithHand.call(this), what happens internally?
does humanWithHand variable copies (or points?) its properties and members to human variable's prototype?
Yehuda Katz has a good writeup of JavaScript's Function#call method. His writeup should answer your question, and many followup questions besides.
When you call a function directly, using the general syntax:
var foo = function() {
console.log("foo");
return this;
};
foo(); // evaluates to `window`
Then this inside the function call is whatever this is outside the function call. By default, in the browser, this outside any function calls is window. So inside the function call as above, this is also by default window.
When you call a function using the method-call syntax:
var bar = {
foo: function() {
console.log("foo");
return this;
}
};
bar.foo(); // evaluates to `bar`
Then this inside the function call is the object to the left of the rightmost period: in this case, bar.
We can simulate this situation using call.
When you set up a function outside an object and want to call it with this inside the function call set to an object, you can:
var foo = function() {
console.log("foo");
return this;
}
var bar = { };
foo.call(bar); // evaluates to `bar`
You can use this technique to pass arguments as well:
var foo = function(arg1, arg2) {
console.log("foo");
return arg1 + arg2;
}
var bar = { };
foo.call(bar, "abc", "xyz"); // evaluates to `"abcxyz"`
.call() sets the this value and then calls the function with the arguments you passed to .call(). You use .call() instead of just calling the function directly when you want to set the this value inside the called function rather than let it be set to whatever javascript would normally set it to.
.apply() is a sister function. It can also set the this value and it can take arguments in an array so it can be used when you are trying to pass a variable argument list from some other function call or when you're constructing an argument list programmatically which may have different numbers of arguments depending upon the situation.
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.