alternative for the var self = this pattern - javascript

I am looking for var self = this alternative plan.
var Animal = function(name){
this.name = name;
this.arr = [1,2,3,4];
this.inc = function(num){
return num + 1;
};
this.fireArr = function(){
var self = this;
this.arr.forEach(function(item){
console.log(self.inc(item));
});
};
};
var dog = new Animal("dog");
console.log(dog.fireArr());
My fiddle is here.
http://jsfiddle.net/haradashinya/TtYpc/
Do you have any idea?
Thanks in advance.

You can set the second argument to forEach, which is the this value.
this.arr.forEach(function(item){
console.log(this.inc(item));
}, this);

You can use .bind() to make sure the function is called with the right this value:
function fireArr() {
this.arr.forEach(function(item){
console.log(this.inc(item));
}.bind(this));
}
But imho the self (that, _this) variable is easier to understand, because it directly states that not the normal this value is used, although one would expect it (e.g. in an event handler, or jQuery's each()). Especially on long functions, where you don't see the bind() in the end, this is of importance. Also, some ancient browsers do not support bind() and you would need to shim it.
So, for any in-place function expressions I recommend the use of a dereferencing variable.
But it can be of great use when you have a method defined somewhere, normally using this to point to the current object as it is common in that context, and then the method should be used somewhere else. Instead of a var self-wrapper, you can and should use bind for simplicity and clarity. Your example offers quite a good demo (assuming the inc method used the this keyword):
this.arr.forEach( this.inc.bind(this) );
(although forEach() allows us to pass a custom this argument - event attachers for example don't)

In your example, the inc function doesn't use the this value, so it doesn't need to be a method. You can define it as a local function:
var Animal = function ( name ) {
this.name = name;
this.arr = [ 1, 2, 3, 4 ];
var inc = function ( num ) {
return num + 1;
};
this.fireArr = function () {
this.arr.forEach(function ( item ) {
console.log( inc( item ) );
});
};
};

Related

What is the advantage of using call method instead of passing an object in the parameter

In the below code, which one is the right and how these two are different
Using call method
var obj = {
num: 10
};
var add = function(a) {
return this.num + a
}
console.log(add.call(obj,4))
Passing object in parameter
var obj = {
num: 10
};
var add = function(obj,a) {
return obj.num + a
}
console.log(add(obj,4))
Your second code block is just a regular function. The first one however is a bit more tricky. So the question is basically:
When to work with context in javascript?
In javascript, the term context basically means this. It is usually used when you call a method of an object, so that you can refer to the object. That's one of the core concepts of OOP, were we only define a function once inside the prototype, and every object of that class which inherits from it exposes this method, it won't work without context. So that's what this was invented for. However there are some cases, were context is useful without inheritance. E.g. Eventhandlers are usually contextless, as they are not part of any object:
window.addEventListener("load", function(evt){
const el = evt.target;
};
However as it is an Eventhandler of window, wouldn't it make sense that it is executed in the context of window? If you now say "YES", then you (will) probably love JS:
window.addEventListener("load", function(){
this.document.body.innerHTML = "Dynamic context can be cool!";
});
So in JS this is the way of refering to the object, the function refers to. Through Function.prototype.call we can make use of this everywhere. However that does not mean that we should use it everywhere. this should stay in the sense of context, as using it somewhere else will create confusion / uglify your code / make your code buggy.
var add = function(a) {
return this.num + a;
}
In your codesnippet i think its unclear what thisrefers to. So its rather a misuse of this. However it could get a meaning if you make it a method of obj, so its context becomes clear from the code:
const num = {
value:10,
add(a){ return this.value + a }
};
It gets even more beautiful if you use inheritance to make it reusable:
class CustomNumber {
constructor(n = 0){
this.value = n;
}
add(a){ return this.value + a; }
}
const num = new CustomNumber(10);

Understanding the superior method introduced by Crockford

In the functional inheritance pattern, Crockford introduces a new superior method via:
Object.method('superior', function (name) {
var that = this,
method = that[name];
return function () {
return method.apply(that, arguments);
};
});
Where method is :
Function.prototype.method = function (name, func) {
this.prototype[name] = func;
return this;
};
Example:
var coolcat = function (spec) {
var that = cat(spec),
super_get_name = that.superior('get_name');
that.get_name = function (n) {
return 'like ' + super_get_name() + ' baby';
};
return that;
};
My question is Why don't just assign that.get_name to super_get_name ?
"My question is Why don't just assign that.get_name to super_get_name?"
Because the way the get_name method has its this value set to the that object is by invoking it as:
that.get_name();
When a function is invoked as the method of an object, the object becomes the value of this in that invocation of the function.
If you had done this instead:
var super_get_name = that.get_name;
super_get_name();
Now you're invoking a detached function, so it doesn't know what its this value should be, and so it uses the default, which is usually the window object.
I don't like the solution that crockford shows at all. Typically, in that situation, you'd simply make a new function right there instead of relying on extensions to Object.prototype to do it for you. (Extending Object.prototype is very ugly IMO.)
var coolcat = function (spec) {
var that = cat(spec),
_original_get_name = that.get_name,
super_get_name = function() {
return _original_get_name.apply(that, arguments);
};
that.get_name = function (n) {
return 'like ' + super_get_name() + ' baby';
};
return that;
};
Or in modern implementations, you'd use Function.prototype.bind to create a new function with its this value bound to whatever you provided as the first argument to .bind().
var coolcat = function (spec) {
var that = cat(spec),
super_get_name = that.get_name.bind(that);
that.get_name = function (n) {
return 'like ' + super_get_name() + ' baby';
};
return that;
};
In the sense of Crockford's Functional Inheritance Pattern it is completely valid to reference the base class method
var super_get_name = that.get_name;
This is how Crockford teaches it in his lecture JavaScript Master Class , see the part on Functional Inheritance.
Later - the method might be overriden by the derived class - you invoke it simply
super_get_name();
Crockford's superior method makes no sense in the Functional Inheritance Pattern.
Because in my opinion this is never needed in a method defined by a producer function. If you use this in your methods you'll run in all sorts of trouble because of dynamic scoping and manipulation of this:
function mammal(spec){
var that = {};
that.legs = Math.round(Math.random() * 4);
that.get_name = function(){
return spec.name + "with" + that.legs; // always use that not this
};
that.isProperThis = function(){
console.log( this === that );
};
return that;
};
var myMammal = mammal({name: 'Herb'});
myMammal.isProperThis(); // true
myMammal.isProperThis.call(window); // false
setTimeout(myMammal.isProperThis, 1); // false
If you insist on using this in your methods you can no longer treat them as "first-class" variables in JavaScript. Instead you have to convert them to "binders" by calling bind as described in the first answer in this post.
superior is a method defined in the prototype of the Object constructor function. It caches an object's method, so that it returns the original method even if it were changed later.
From JavaScript: The Good Parts, p.54:
The function will invoke the original method even if the property is changed.
The accepted answer given by cookie monster is correct, but I would like to add clarification.
As cookie monster says, if you write
var super_get_name = that.get_name;
invocation of super_get_name will no longer bind any value to this, making it an unbound function.
However, in the case of the example Crockford gives in The Good Parts, it would not matter if super_get_name were unbound by writing it in the way you propose, because this would never be used in its invocation.
You would essentially end up doing the following:
super_get_name = function () {
return that.says() + ' ' + spec.name +
' ' + that.says();
(where the right operand executes in the context of the function assigned to cat).
I assume that Crockford avoids unbound functions here to demonstrate a general principle, even though his specific example does not require binding.

JavaScript function currying does not work on instance method

I am learning function currying in JavaScript by reading online and writing some simple code. I got following example in online article
function toArray(obj) {
return Array.prototype.slice.call(obj);
}
Function.prototype.curry = function() {
if (arguments.length<1) {
return this; //nothing to curry with - return function
}
var __method = this;
var args = toArray(arguments);
return function() {
return __method.apply(this, args.concat(toArray(arguments)));
}
}
var add = function(a,b) {
return a + b;
}
var addTen = add.curry(10); //create function that returns 10 + argument
alert(addTen(20)); //alerts 30 correctly
Then I tried to try it on the method of an instantiated function. So I tried following. But it gave me error "Unable to get property 'prototype' of undefined or null reference" on the second last line. I know this error is nothing to do with currying but I am messing up with some basics of JS functions concept. So where I am going wrong.
function Person()
{
this.age = 15;
}
Person.ageAfter = function (years) {
return this.age + years;
}
var personObj = new Person();
var ageAfterFiveYears = personObj.ageAfter.prototype.curry(5); //**Error**
alert(ageAfterFiveYears());
You have two issues:
The ageAfter function is not an instance method - you've added it to the "class" (i.e. it's kind of like a static method). It should be added to the prototype.
When you curry the function you lose your object's context, so you either need to rebind the context
e.g:
var ageAfterFiveYears = Person.prototype.ageAfter.curry(5).bind(personObj);
giving you a function that only works on the current instance, or better yet, as #Pointy suggests in the comments, you should just put the curried function back onto the prototype:
Person.prototype.ageAfterFiveYears = Person.prototype.ageAfter.curry(5);
which then adds the .ageAfterFiveYears method to every Person object.
You shouldn't include the prototype in your call:
var ageAfterFiveYears = personObj.ageAfter.curry(5);
The "ageAfter" property has a function for its value, so that function will have access to your "curry" function just like the function in your first example.
When you call it on the prototype, the value of this inside your function will be the prototype object, not the "ageAfter" function.
Also as a comment points out, you need to put "ageAfter" on the prototype:
Person.prototype.ageAfter = function(years) { ... }
edit — the binding issue that Alnitak points out is also important. (When I say "important", what I mean is "necessary to make your code work".)
Curry will not work for your use case. You need to bind the context so this is your personObj.
function Person() {
this.age = 15;
}
Person.prototype.ageAfter = function (years) {
return this.age + years;
}
var personObj = new Person();
var ageAfterFiveYears = personObj.ageAfter.bind(personObj, 5);
alert(ageAfterFiveYears());

how to get a reference to the defining 'class' inside an inner method in JavaScript?

I have the following JS code:
var Item = function ()
{
this.property = '';
this.myfunction = function ()
{
var value = this.property;
};
};
however, this does not point to the defining class so value doesn't get anything.
how do I access this.property from inside my function?
You need to create a closure which captures the value of parent scope's this:
var Item = function ()
{
this.property = '';
var self = this;
this.myfunction = function ()
{
var value = self.property;
};
};
Update: As others have pointed out, this closure is not needed when Item is used as a constructor (new Item()). Noting it here for future reference.
just create an alias for this. It will get closure'd.
var Item = function ()
{
this.property = '';
var self = this;
this.myfunction = function ()
{
var value = self.property;
};
};
Your code works as is if you call Item() as a constructor.
var item = new Item();
item.property = "the property";
item.myfunction(); // value = "the property"
this changes depending on the context. The context being how a function was invoked, not how it was defined, but how it was called.
Besides that, you seem to be mixing up two patterns here. I'm sure you meant something like:
var Item = function() {
this.property = '';
};
Item.prototype.myfunction = function() {
var value = this.property;
};
Instead you kind of mixed a closure pattern with prototypal, which doesn't seem very useful there. Closure is good for hiding members, allowing for true private members, but here you're exposing the property anyway. There's no reason not to stick that function on the prototype.
Do yourself a favor and ignore any concepts you have of more traditional OO, they won't do you any good here. Prototypal isn't nearly the same thing.

Can a method find out the "this" of its parent object?

Let's say I've come up with a particular sort function that I want to put in the prototype of some Array based object (I'll use Array itself here). I can do
Array.prototype.specialSort = function...
but what I'd really like to do is
Array.prototype.sort.special = function...
the problem, of course, is that when it's called, the latter won't know about the Array object, it will only know about the sort, so it can't sort. Is there any magical incantation to pass a "this" down the tree?
Secondary question (since the answer to the primary question is likely "no"): What would you do to implement the notion of "sub-methods" with maximum elegance?
This should be fairly close to what you want:
Array.prototype.sort = function () {
return {
self: this;
, special: function () {
return sortLogic (self);
}
};
};
var xs = [1, 2, 3];
xs.sort ().special ();
Another option would be to use Function.prototype.call or Function.prototype.apply, especially if you want arr.sort () to sort the list as normal.
Array.prototype.sort.special.call (arr, arg1, arg2, etc);
Using the second method over the first allows one to use the call and apply methods easily on the sort.special method. Could be useful when doing something like the following:
function () {
Array.prototype.sort.special.call (arguments);
}
If you want both worlds, something like this could work:
Array.prototype.sort = (function () {
var special = function () {
if (this [0] > this [1]) {
var tmp = this [0];
this [0] = this [1];
this [1] = tmp;
}
return this;
};
var sort = function () {
var context = this;
return {
special: function () {
return special.apply (context, arguments)
}
};
};
sort.special = special;
return sort;
}) ();
/*** Example Below ***/
function foo () {
Array.prototype.sort.special.call (arguments);
var xs = [5, 2, 3];
xs.sort ().special ();
alert (arguments);
alert (xs);
}
foo (9, 6);
Thanks for the guidance to both Pointy and trinithis. I think I am clear on the subject now. The sticking point is that, although sort() is a method of the Array, if it's not invoked, it's just a member (or property), so it has no "this". I was wanting the "this" it would have had if it had been invoked. And since I was invoking something at the end of the chain, I was kind of hoping there was some magic that would keep it all method-y. But no.
What I would probably do is have a separate "sorts" method to act as the grouper for my special methods, and leave the existing sort alone.

Categories