Understanding "this" in Javascript - javascript

I have 2 blocks of code, one that does not work, and one that works because I assign that = this and use that in my function instead of this. Can someone help me understand why this is so. It would help to know how one should think of accessing variables in functions in objects in JavaScript, and the nature of "this", if I am saying that right (if not, please enlighten me). Thank you!
var add = function (x, y) {
return x + y;
}
var myObject = {
value: 0,
increment: function (inc) {
this.value += typeof inc === 'number' ? inc : 1;
}
};
myObject.double2 = function () {
// var that = this;
var helper = function () {
this.value = add(this.value, this.value)
};
helper();
};
myObject.increment(100);
document.writeln(myObject.value); // Prints 100
myObject.double2();
document.writeln('<BR/>'); // Prints <BR/>
document.writeln(myObject.value); // Prints 100, **FAILS**
And the modified code:
var add = function (x, y) {
return x + y;
}
var myObject = {
value: 0,
increment: function (inc) {
this.value += typeof inc === 'number' ? inc : 1;
}
};
myObject.double2 = function () {
var that = this;
var helper = function () {
that.value = add(that.value, that.value)
};
helper();
};
myObject.increment(100);
document.writeln(myObject.value); // Prints 100
myObject.double2();
document.writeln('<BR/>'); // Prints <BR/>
document.writeln(myObject.value); // Prints 200 - **NOW IT WORKS**

The first one doesn't work because when each function's this depends on how it was called.
First you do myObject.double2() and so this = myObject. But inside double2, you call helper() by itself and there is no object you're calling it under (it's not myObject.helper()). So this defaults to the global object (or window object in a browser).
In the second example, you "capture" a reference to myObject (that=this=myObject) and so that.value=myObject.value.

I think this link would greatly help you in understanding the differences of object and private members in Javascript to tackle your problem, please take a look at the Private section. Hope it helps!

Mozilla has some good reading on this. If you want this to work without assigning this to that, you can always use call.
Example: jsfiddle.net/5azde/

And you can always remember this:
When a function of an object is called, the object will be passed as this value(as the case 'add' and 'increment' function which belong to 'window' and 'myObject' separately). And if the function doesn't belong to any objects, window(or global) will be passed as this value.(as the case with function helper in your sample code).
And I'm glad to see a pure js question. No jQuery, No css, No dom selector. haha.
May it helps. :-)

Related

What does binding a function to 'this' do in the constructor? [duplicate]

What is the use of bind() in JavaScript?
Bind creates a new function that will force the this inside the function to be the parameter passed to bind().
Here's an example that shows how to use bind to pass a member method around that has the correct this:
var myButton = {
content: 'OK',
click() {
console.log(this.content + ' clicked');
}
};
myButton.click();
var looseClick = myButton.click;
looseClick(); // not bound, 'this' is not myButton - it is the globalThis
var boundClick = myButton.click.bind(myButton);
boundClick(); // bound, 'this' is myButton
Which prints out:
OK clicked
undefined clicked
OK clicked
You can also add extra parameters after the 1st (this) parameter and bind will pass in those values to the original function. Any additional parameters you later pass to the bound function will be passed in after the bound parameters:
// Example showing binding some parameters
var sum = function(a, b) {
return a + b;
};
var add5 = sum.bind(null, 5);
console.log(add5(10));
Which prints out:
15
Check out JavaScript Function bind for more info and interactive examples.
Update: ECMAScript 2015 adds support for => functions. => functions are more compact and do not change the this pointer from their defining scope, so you may not need to use bind() as often. For example, if you wanted a function on Button from the first example to hook up the click callback to a DOM event, the following are all valid ways of doing that:
var myButton = {
... // As above
hookEvent(element) {
// Use bind() to ensure 'this' is the 'this' inside click()
element.addEventListener('click', this.click.bind(this));
}
};
Or:
var myButton = {
... // As above
hookEvent(element) {
// Use a new variable for 'this' since 'this' inside the function
// will not be the 'this' inside hookEvent()
var me = this;
element.addEventListener('click', function() { me.click() });
}
};
Or:
var myButton = {
... // As above
hookEvent(element) {
// => functions do not change 'this', so you can use it directly
element.addEventListener('click', () => this.click());
}
};
The simplest use of bind() is to make a function that, no matter
how it is called, is called with a particular this value.
x = 9;
var module = {
x: 81,
getX: function () {
return this.x;
}
};
module.getX(); // 81
var getX = module.getX;
getX(); // 9, because in this case, "this" refers to the global object
// create a new function with 'this' bound to module
var boundGetX = getX.bind(module);
boundGetX(); // 81
Please refer to this link on MDN Web Docs for more information:
Function.prototype.bind()
bind allows-
set the value of "this" to an specific object. This becomes very helpful as sometimes this is not what is intended.
reuse methods
curry a function
For example, you have a function to deduct monthly club fees
function getMonthlyFee(fee){
var remaining = this.total - fee;
this.total = remaining;
return this.name +' remaining balance:'+remaining;
}
Now you want to reuse this function for a different club member. Note that the monthly fee will vary from member to member.
Let's imagine Rachel has a balance of 500, and a monthly membership fee of 90.
var rachel = {name:'Rachel Green', total:500};
Now, create a function that can be used again and again to deduct the fee from her account every month
//bind
var getRachelFee = getMonthlyFee.bind(rachel, 90);
//deduct
getRachelFee();//Rachel Green remaining balance:410
getRachelFee();//Rachel Green remaining balance:320
Now, the same getMonthlyFee function could be used for another member with a different membership fee. For Example, Ross Geller has a 250 balance and a monthly fee of 25
var ross = {name:'Ross Geller', total:250};
//bind
var getRossFee = getMonthlyFee.bind(ross, 25);
//deduct
getRossFee(); //Ross Geller remaining balance:225
getRossFee(); //Ross Geller remaining balance:200
From the MDN docs on Function.prototype.bind() :
The bind() method creates a new function that, when called, has its
this keyword set to the provided value, with a given sequence of
arguments preceding any provided when the new function is called.
So, what does that mean?!
Well, let's take a function that looks like this :
var logProp = function(prop) {
console.log(this[prop]);
};
Now, let's take an object that looks like this :
var Obj = {
x : 5,
y : 10
};
We can bind our function to our object like this :
Obj.log = logProp.bind(Obj);
Now, we can run Obj.log anywhere in our code :
Obj.log('x'); // Output : 5
Obj.log('y'); // Output : 10
This works, because we bound the value of this to our object Obj.
Where it really gets interesting, is when you not only bind a value for this, but also for its argument prop :
Obj.logX = logProp.bind(Obj, 'x');
Obj.logY = logProp.bind(Obj, 'y');
We can now do this :
Obj.logX(); // Output : 5
Obj.logY(); // Output : 10
Unlike with Obj.log, we do not have to pass x or y, because we passed those values when we did our binding.
Variables has local and global scopes. Let's suppose that we have two variables with the same name. One is globally defined and the other is defined inside a function closure and we want to get the variable value which is inside the function closure. In that case we use this bind() method. Please see the simple example below:
var x = 9; // this refers to global "window" object here in the browser
var person = {
x: 81,
getX: function() {
return this.x;
}
};
var y = person.getX; // It will return 9, because it will call global value of x(var x=9).
var x2 = y.bind(person); // It will return 81, because it will call local value of x, which is defined in the object called person(x=81).
document.getElementById("demo1").innerHTML = y();
document.getElementById("demo2").innerHTML = x2();
<p id="demo1">0</p>
<p id="demo2">0</p>
Summary:
The bind() method takes an object as an first argument and creates a new function. When the function is invoked the value of this in the function body will be the object which was passed in as an argument in the bind() function.
How does this work in JS anyway
The value of this in javascript is dependent always depends on what Object the function is called. The value of this always refers to the object left of the dot from where is the function is called. In case of the global scope this is window (or global in nodeJS). Only call, apply and bind can alter the this binding differently. Here is an example to show how the this keyword works:
let obj = {
prop1: 1,
func: function () { console.log(this); }
}
obj.func(); // obj left of the dot so this refers to obj
const customFunc = obj.func; // we store the function in the customFunc obj
customFunc(); // now the object left of the dot is window,
// customFunc() is shorthand for window.customFunc()
// Therefore window will be logged
How is bind used?
Bind can help in overcoming difficulties with the this keyword by having a fixed object where this will refer to. For example:
var name = 'globalName';
const obj = {
name: 'myName',
sayName: function () { console.log(this.name);}
}
const say = obj.sayName; // we are merely storing the function the value of this isn't magically transferred
say(); // now because this function is executed in global scope this will refer to the global var
const boundSay = obj.sayName.bind(obj); // now the value of this is bound to the obj object
boundSay(); // Now this will refer to the name in the obj object: 'myName'
Once the function is bound to a particular this value we can pass it around and even put it on properties on other objects. The value of this will remain the same.
The bind() method creates a new function instance whose this value is bound to the value that was passed into bind().
For example:
window.color = "red";
var o = { color: "blue" };
function sayColor(){
alert(this.color);
}
var objectSayColor = sayColor.bind(o);
objectSayColor(); //blue
Here, a new function called objectSayColor() is created from sayColor() by calling bind() and passing in the object o. The objectSayColor() function has a this value equivalent to o, so calling the function, even as a global call, results in the string “blue” being displayed.
Reference : Nicholas C. Zakas - PROFESSIONAL JAVASCRIPT® FOR WEB DEVELOPERS
I will explain bind theoretically as well as practically
bind in javascript is a method -- Function.prototype.bind . bind is a method. It is called on function prototype. This method creates a function whose body is similar to the function on which it is called but the 'this' refers to the first parameter passed to the bind method. Its syntax is
var bindedFunc = Func.bind(thisObj,optionsArg1,optionalArg2,optionalArg3,...);
Example:--
var checkRange = function(value){
if(typeof value !== "number"){
return false;
}
else {
return value >= this.minimum && value <= this.maximum;
}
}
var range = {minimum:10,maximum:20};
var boundedFunc = checkRange.bind(range); //bounded Function. this refers to range
var result = boundedFunc(15); //passing value
console.log(result) // will give true;
Creating a new Function by Binding Arguments to Values
The bind method creates a new function from another function with one or more arguments bound to specific values, including the implicit this argument.
Partial Application
This is an example of partial application. Normally we supply a function with all of its arguments which yields a value. This is known as function application. We are applying the function to its arguments.
A Higher Order Function (HOF)
Partial application is an example of a higher order function (HOF) because it yields a new function with a fewer number of argument.
Binding Multiple Arguments
You can use bind to transform functions with multiple arguments into new functions.
function multiply(x, y) {
return x * y;
}
let multiplyBy10 = multiply.bind(null, 10);
console.log(multiplyBy10(5));
Converting from Instance Method to Static Function
In the most common use case, when called with one argument the bind method will create a new function that has the this value bound to a specific value. In effect this transforms an instance method to a static method.
function Multiplier(factor) {
this.factor = factor;
}
Multiplier.prototype.multiply = function(x) {
return this.factor * x;
}
function ApplyFunction(func, value) {
return func(value);
}
var mul = new Multiplier(5);
// Produces garbage (NaN) because multiplying "undefined" by 10
console.log(ApplyFunction(mul.multiply, 10));
// Produces expected result: 50
console.log(ApplyFunction(mul.multiply.bind(mul), 10));
Implementing a Stateful CallBack
The following example shows how using binding of this can enable an object method to act as a callback that can easily update the state of an object.
function ButtonPressedLogger()
{
this.count = 0;
this.onPressed = function() {
this.count++;
console.log("pressed a button " + this.count + " times");
}
for (let d of document.getElementsByTagName("button"))
d.onclick = this.onPressed.bind(this);
}
new ButtonPressedLogger();
<button>press me</button>
<button>no press me</button>
As mentioned, Function.bind() lets you specify the context that the function will execute in (that is, it lets you pass in what object the this keyword will resolve to in the body of the function.
A couple of analogous toolkit API methods that perform a similar service:
jQuery.proxy()
Dojo.hitch()
Bind Method
A bind implementation might look something like so:
Function.prototype.bind = function () {
const self = this;
const args = [...arguments];
const context = args.shift();
return function () {
return self.apply(context, args.concat([...arguments]));
};
};
The bind function can take any number of arguments and return a new function.
The new function will call the original function using the JS Function.prototype.apply method.The apply method will use the first argument passed to the target function as its context (this), and the second array argument of the apply method will be a combination of the rest of the arguments from the target function, concat with the arguments used to call the return function (in that order).
An example can look something like so:
function Fruit(emoji) {
this.emoji = emoji;
}
Fruit.prototype.show = function () {
console.log(this.emoji);
};
const apple = new Fruit('🍎');
const orange = new Fruit('🍊');
apple.show(); // 🍎
orange.show(); // 🍊
const fruit1 = apple.show;
const fruit2 = apple.show.bind();
const fruit3 = apple.show.bind(apple);
const fruit4 = apple.show.bind(orange);
fruit1(); // undefined
fruit2(); // undefined
fruit3(); // 🍎
fruit4(); // 🍊
/**
* Bind is a method inherited from Function.prototype same like call and apply
* It basically helps to bind a function to an object's context during initialisation
*
* */
window.myname = "Jineesh";
var foo = function(){
return this.myname;
};
//IE < 8 has issues with this, supported in ecmascript 5
var obj = {
myname : "John",
fn:foo.bind(window)// binds to window object
};
console.log( obj.fn() ); // Returns Jineesh
Consider the Simple Program listed below,
//we create object user
let User = { name: 'Justin' };
//a Hello Function is created to Alert the object User
function Hello() {
alert(this.name);
}
//since there the value of this is lost we need to bind user to use this keyword
let user = Hello.bind(User);
user();
//we create an instance to refer the this keyword (this.name);
Simple Explanation:
bind() create a new function, a new reference at a function it returns to you.
In parameter after this keyword, you pass in the parameter you want to preconfigure. Actually it does not execute immediately, just prepares for execution.
You can preconfigure as many parameters as you want.
Simple Example to understand bind:
function calculate(operation) {
if (operation === 'ADD') {
alert('The Operation is Addition');
} else if (operation === 'SUBTRACT') {
alert('The Operation is Subtraction');
}
}
addBtn.addEventListener('click', calculate.bind(this, 'ADD'));
subtractBtn.addEventListener('click', calculate.bind(this, 'SUBTRACT'));
The bind function creates a new function with the same function body as the function it is calling .It is called with the this argument .why we use bind fun. : when every time a new instance is created and we have to use first initial instance then we use bind fun.We can't override the bind fun.simply it stores the initial object of the class.
setInterval(this.animate_to.bind(this), 1000/this.difference);
function.prototype.bind() accepts an Object.
It binds the calling function to the passed Object and the returns
the same.
When an object is bound to a function, it means you will be able to
access the values of that object from within the function using
'this' keyword.
It can also be said as,
function.prototype.bind() is used to provide/change the context of a
function.
let powerOfNumber = function(number) {
let product = 1;
for(let i=1; i<= this.power; i++) {
product*=number;
}
return product;
}
let powerOfTwo = powerOfNumber.bind({power:2});
alert(powerOfTwo(2));
let powerOfThree = powerOfNumber.bind({power:3});
alert(powerOfThree(2));
let powerOfFour = powerOfNumber.bind({power:4});
alert(powerOfFour(2));
Let us try to understand this.
let powerOfNumber = function(number) {
let product = 1;
for (let i = 1; i <= this.power; i++) {
product *= number;
}
return product;
}
Here, in this function, this corresponds to the object bound to the function powerOfNumber. Currently we don't have any function that is bound to this function.
Let us create a function powerOfTwo which will find the second power of a number using the above function.
let powerOfTwo = powerOfNumber.bind({power:2});
alert(powerOfTwo(2));
Here the object {power : 2} is passed to powerOfNumber function using bind.
The bind function binds this object to the powerOfNumber() and returns the below function to powerOfTwo. Now, powerOfTwo looks like,
let powerOfNumber = function(number) {
let product = 1;
for(let i=1; i<=2; i++) {
product*=number;
}
return product;
}
Hence, powerOfTwo will find the second power.
Feel free to check this out.
bind() function in Javascript
The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.
An example for the first part
grabbed from react package useSt8
import { useState } from "react"
function st8() {
switch(arguments.length) {
case 0: return this[0]
case 1: return void this[1](arguments[0])
default: throw new Error("Expected 0 or 1 arguments")
}
}
function useSt8(initial) {
// this in st8 will be something like [state, setSatate]
return st8.bind(useState(initial))
}
// usage
function Counter() {
const count = useSt8(0);
return (
<>
Count: {count()}
<button onClick={() => count(0)}>Reset</button>
<button onClick={() => count(prevCount => prevCount + 1)}>inc</button>
</>
);
}
An example for the second part
const add = (a, b) => a+b
someThis = this
// new function with this value equal to someThis
add5 = add.bind(someThis, 5)
add5(10) // 15
// we don't use this in add decelartion so this will work too.
add10 = add.bind(null, 10)
add10(5) // 15
Here's the simplest possible explanation:
Say you have a function
function _loop(n) { console.log("so: " + n) }
obviously you can call it like _loop(69) as usual.
Rewrite like this:
var _loop = function() { console.log("so: " + this.n) }
Notice there are now
no arguments as such
you use "this. " to get to the named arguments
You can now call the function like this:
_loop.bind( {"n": 420} )
That's it.
Most typical use case:
A really typical use is when you need to add an argument to a callback.
Callbacks can't have arguments.
So just "rewrite" the callback as above.
Simple example
function lol(second, third) {
console.log(this.first, second, third);
}
lol(); // undefined, undefined, undefined
lol('1'); // undefined, "1", undefined
lol('1', '2'); // undefined, "1", "2"
lol.call({first: '1'}); // "1", undefined, undefined
lol.call({first: '1'}, '2'); // "1", "2", undefined
lol.call({first: '1'}, '2', '3'); // "1", "2", "3"
lol.apply({first: '1'}); // "1", undefined, undefined
lol.apply({first: '1'}, ['2', '3']); // "1", "2", "3"
const newLol = lol.bind({first: '1'});
newLol(); // "1", undefined, undefined
newLol('2'); // "1", "2", undefined
newLol('2', '3'); // "1", "2", "3"
const newOmg = lol.bind({first: '1'}, '2');
newOmg(); // "1", "2", undefined
newOmg('3'); // "1", "2", "3"
const newWtf = lol.bind({first: '1'}, '2', '3');
newWtf(); // "1", "2", "3"
Another usage is that you can pass binded function as an argument to another function which is operating under another execution context.
var name = "sample";
function sample(){
console.log(this.name);
}
var cb = sample.bind(this);
function somefunction(cb){
//other code
cb();
}
somefunction.call({}, cb);
In addition to what have been said, the bind() method allows an object to borrow a method from another object without making a copy of that method. This is known as function borrowing in JavaScript.
i did not read above code but i learn something in simple so want to share here about bind method after bind method we can use it as any normal method.
<pre> note: do not use arrow function it will show error undefined </pre>
let solarSystem = {
sun: 'red',
moon : 'white',
sunmoon : function(){
let dayNight = this.sun + ' is the sun color and present in day and '+this.moon + ' is the moon color and prenet in night';
return dayNight;
}
}
let work = function(work,sleep){
console.log(this.sunmoon()); // accessing the solatSystem it show error undefine sunmmon untill now because we can't access directly for that we use .bind()
console.log('i work in '+ work +' and sleep in '+sleep);
}
let outPut = work.bind(solarSystem);
outPut('day','night')
bind is a function which is available in java script prototype, as the name suggest bind is used to bind your function call to the context whichever you are dealing with for eg:
var rateOfInterest='4%';
var axisBank=
{
rateOfInterest:'10%',
getRateOfInterest:function()
{
return this.rateOfInterest;
}
}
axisBank.getRateOfInterest() //'10%'
let knowAxisBankInterest=axisBank.getRateOfInterest // when you want to assign the function call to a varaible we use this syntax
knowAxisBankInterest(); // you will get output as '4%' here by default the function is called wrt global context
let knowExactAxisBankInterest=knowAxisBankInterest.bind(axisBank); //so here we need bind function call to its local context
knowExactAxisBankInterest() // '10%'

Javascript dynamically created functions in an object

I'm just studying javascript and I faced an issue related to scoping.
Here's the code
function User (properties) {
for (var i in properties) {
(function () {
this ['get' + i] = function () {
return properties [i];
};
}) ();
}
}
var me = new User ({
Id : 54,
Name : 'ohyou'
});
console.log (me.getName ());
console.log (me.getId ());
How I want it to work: it should create two functions getName and getId that belong to the me object.
How it works: it creates two functions just as I want, but they belong to the window
What I tried:
I tried removing the function on the line 3. It does what I want, but now it returns the name "ohyou" two times, instead of returning the id and the name
I tried using the functions from the window scope, the problem as in the previous case persists - it returns the name twice.
The question: what am I doing wrong and how do I make it work as I want?
P.S. Making this post using phone, sorry for possible typos or formatting issues. Also, please forgive me my english skills.
Try to understand why the following code works:
function User(properties) {
for (var i in properties) {
with ({ i: i, self: this, props: properties }) {
self["get" + i] = function () {
return props[i];
};
}
}
}
var me = new User({
Id: 54,
Name: "ohyou"
});
alert(me.getName());
alert(me.getId());
This is an example of one of the legitimate uses of the with statement.
I find the with statement to be more succinct than using an immediately invoked function expression (IIFE) as others are suggesting.
Edit: The with keyword is not bad if you use it correctly. There are some legitimate uses of with:
http://webreflection.blogspot.in/2009/12/with-worlds-most-misunderstood.html
The reason your code doesn't work is because every function has it's own value of this. Hence when you immediately invoke the function expression within the for loop, the value of this inside the function is no longer your new object. It is window. To solve that problem you could do something like:
(function (i, self, props) {
self["get" + i] = function () {
return props[i];
};
}(i, this, properties))
However using the with statement is clean and faster. It's faster because you're not calling a function.
function User (properties) {
var that = this;
for (var i in properties) {
(function (i) {
that ['get' + i] = function () {
return properties [i];
};
}) (i);
}
}
var me = new User ({
Id : 54,
Name : 'ohyou'
});
You can avoid all these closures and other things if you use Object.keys and then forEach, which already introduces a new scope. Then you'd have to pass the this value, which is the second parameter:
function User(properties) {
Object.keys(properties).forEach(function(k) {
this['get'+ k] = function() {
return properties[k]
}
},this)
}
One thing you must remember, any function that does not belong to any object, will always belong to window object.
For example if we modify your object and add a new method,
me.doSomeWork = function(){
this.myLuckyNumber = 10;
var that = this;
function doubleMyLuckyNumber(){
console.log(this); //window
that.myLuckyNumber = that.myLuckyNumber * 2;
}
doubleMyLuckyNumber();
};
me.doSomeWork();
console.log(me.myLuckyNumber) //outputs 20
So always save the reference to a var to use it in inner methods. You can use any of the way that others suggested but I prefer James emanon's approach.

Javascript anonymous function use-case

I am working my way through Eloquent Javascript and I came across a code snippet that looks like this:
function greaterThan(x) {
return function(y) {
return y > x;
};
}
var greaterThanTen = greaterThan(10);
show(greaterThanTen(9));
Is there any real use-case to defining the function like this with an anonymous function inside of it? Wouldn't it be much simpler to do this:
function greaterThan(x,y){
return x > y;
}
var greaterThanTen = greaterThan(9, 10);
any ideas/comments/suggestions would be very helpful.
This is an example of a "closure". Basically, a call to greaterThan() gives you a function. That function, instead of just a mere function, carries with it the value of x - it's like embedding the value of x permanently into the function.
function obj(x) {
//"public interface"
//only these are exposed (inc and getX). x is private.
return {
inc: function() {
return ++x;
},
getX: function() { //a getter function to retrieve private x
return x;
}
}
}
//the value 10 is "embedded" to the returned object
var myobj = obj(10);
//every call to inc increments that "embedded" value
console.log(myobj.inc()); //11
console.log(myobj.inc()); //12
console.log(myobj.inc()); //13
//but you can never access the variable of `x` directly without a "getter"
console.log(myobj.getX());​
Closures are one of the great features of JavaScript. One of it's great uses is to emulate private variables.
The first example you are combining functions.
Of course you can write in different ways but the idea of greaterThanTen in the first example is be something different. For example you can pass this to a filter
var a = [ 1 , 10, 100 , 9, 43 ];
function greaterThan(x) {
return function(y) {
return y > x;
};
}
var greaterThanTen = greaterThan(10);
a.filter(greaterThanTen);
returns [100, 43]
It is functional programming. There is many advantages.
Unless I missed something, the first code returns a function.
The second one returns the result.
That's not a particularly good use case. A better use case for anonymous functions is callbacks, as in: you wish to execute function #2 once function #1 is completed.
function a(param1, param2, callback) {
//work on param1 and param2 here
callback.call(); //triggers the callback function
}

Can I redefine a JavaScript function from within another function?

I want to pass a function reference "go" into another function "redefineFunction", and redefine "go" inside of "redefineFunction". According to Johnathan Snook, functions are passed by reference, so I don't understand why go() does not get redefined when I pass it into redefineFunction(). Is there something that I am missing?
// redefineFunction() will take a function reference and
// reassign it to a new function
function redefineFunction(fn) {
fn = function(x) { return x * 3; };
}
// initial version of go()
function go(x) {
return x;
}
go(5); // returns 5
// redefine go()
go = function(x) {
return x * 2;
}
go(5); // returns 10
// redefine go() using redefineFunction()
redefineFunction(go);
go(5); // still returns 10, I want it to return 15
​
Or see my fiddle http://jsfiddle.net/q9Kft/
Pedants will tell you that JavaScript is pure pass-by-value, but I think that only clouds the issue since the value passed (when passing objects) is a reference to that object. Thus, when you modify an object's properties, you're modifying the original object, but if you replace the variable altogether, you're essentially giving up your reference to the original object.
If you're trying to redefine a function in the global scope: (which is a bad thing; you generally shouldn't have global functions)
function redefineFunction(fn) {
window[fn] = function() { ... };
}
redefineFunction('go');
Otherwise, you'll have to return the new function and assign on the calling side.
function makeNewFunction() {
return function() { ... };
}
go = makeNewFunction();
Nothing is "passed by reference" in JS. There are times that references are passed, but they're passed by value. The difference is subtle, but important -- for one thing, it means that while you can manipulate a referenced object pretty much at will, you can't reliably replace the object (read: alter the reference itself) in any way the caller will see (because the reference was passed by value, and is thus merely a copy of the original reference; attempting to reassign it breaks in the same way it would if the arg were a number or string).
Some cowboys will assume you're redefining a global function and mess with it by name to get around the limitations of pass-by-value, but that will cause issues the second you decide not to have globals all over the place.
The real solution: return the new function, and let the caller decide what to do with it. (I'd argue that redefining functions right out from under the code that uses them is a pretty bad design decision anyway, but eh. I guess there could be a reason for it...)
Snook is wrong. And I don't think it's pedantic at all (#josh3736 :) to point out that EVERYTHING in JavaScript is pass by value. The article by Snook gets this COMPLETELY wrong. Passing a primitive and passing an object work the exact same way. These are equivalent:
var x = 2;
var y = x;
y = 3; //x is STILL 2.
function stuff(y){
y = 3; //guess what. x is STILL 2
}
stuff(x);
///////////////////
var x = {stuff: 2};
var y = x;
y = {stuff: 3}; //x.stuff is STILL 2
function stuff(y){
y = {stuff: 3}; //guess what. x.stuff is STILL 2
}
stuff(x);
This is important. Java, C#, and MOST languages work this way. That's why C# has a "ref" keyword for when you really do want to pass something by reference.
You can't modify the variable from inside the function, so the quick fix is to return the value and assign it outside the function, like this
// log() just writes a message to the text area
function log(message) {
$('#output').val($('#output').val() + message + "\n");
}
// redefineFunction() will take a function reference and
// reassign it to a new function
function redefineFunction() {
newvalue = function(x) { return x * 3; };
return newvalue;
}
// initial version of go()
function go(x) {
return x;
}
log(go(5)); // returns 5
// redefine go()
go = function(x) {
return x * 2;
}
log(go(5)); // returns 10
// redefine go() using redefineFunction()
go = redefineFunction();
log(go(5)); // returns 10, I want it to return 15
I believe functions are 'passed in by value'. If you put log(f(5)); inside your redefineFunction function it will output 15, but 10 when you call log(go(5)) afterwards.
If you change redefineFunction to return the function and then assign it to go (go = redefineFunction()) it will work as you expect.
This is equivalent to asking if you can redefine any variable by passing it as an argument to some function. No. You can reassign it by, uhh, reassigning it. In this case, if you make redefineFunction return a function, you can simply assign it to go:
function redefineFunction() {
var fn = function(x) { return x * e; };
return fn;
}
function go(x) {
return x;
}
go = redefineFunction();
go(5); // return 15
This is working in firefox:
function redefineFunction(fn) {
window[fn] = function(x) {
return x * 3;
}
};
function go(x) {
return x;
};
alert(go(5));
go=function(x) {
return x * 2;
}
alert(go(5));
redefineFunction('go');
alert(go(5));
The secret is that a global function called go also is called window.go and window["go"].
This can also be used at styles: element.style["overflow"] = "hidden", and in attributes:
element["value"] = "hello there".
This is a very useful knowlege.
Why dont use a object? something like this:
var o = {
go: function( x ) {
return x;
},
redefineFunction: function ( fn ) {
if (typeof fn === 'function') {
this.go = fn;
}
}
}
console.log(o.go(5)); // return 5
var fn = function (x) {
return x * 2;
};
o.redefineFunction(fn);
console.log(o.go(5));​ //return 10
Hope it helps!

function invocation pattern scoping rules in JavaScript

Here is a working example from "Javascript - The Good Parts".
function add(x, y){ return x + y};
var myObject = {
value: 0,
increment: function (inc) {
this.value += typeof inc === 'number' ? inc : 1;
}
};
myObject.increment(2);
document.writeln(myObject.value);
myObject.double = function ( ) {
var that = this; // Workaround.
var helper = function ( ) {
that.value = add(that.value, that.value)
};
helper( ); // Invoke helper as a function.
};
myObject.double( );
document.writeln(myObject.value); // 4
For function invocation pattern, 'this' object will have global reference. But I cannot fully understand under-the-hood of mentioned workaround:-
var that = this; // Workaround.
if we do this, aren't we just copying the reference to 'this' to 'that' ? i.e 'that' will hold to global scope same as 'this' ? how does this work internally ?
It's not the same here, this refers to myObject so you're getting the right value property it has, this would refer to window...which is why you want to keep the reference like it's doing.
You can test it out here, a few alerts inside the helper function show what's happening pretty well.
An alternative would be to .call() or .apply() the function with the right context, so this continues to refer to the myObject instance you want...like this:
myObject.double = function () {
var helper = function () {
this.value = add(this.value, this.value)
};
helper.call(this); // Invoke helper as a function.
};
You can test that version here.
There are two functions being involved here: one is myObject.double and the other is helper. When you call myObject.double() this refers to myObject. So that === myObject. Later, inside that function, you also call helper(), and inside that scope you have this === the global object.

Categories