function's local var not getting argument value - javascript

This seems strange to me. I have
var j = "x";
var k = "y";
function fun1 ( a, b) {
var j = a;
var k = b;
console.log("this.j is:", this.j);
console.log("this.k is:", this.k);
this.j = a;
this.k = b;
return this.j + this.k;
};
console.log("j is ", j);
console.log("k is ", k);
console.log("fun1(3,4) is ", fun1(3,4));
console.log("j is ", j);
console.log("k is ", k);
console.log("fun1(2,7) is ", fun1(2,7));
console.log("j is ", j);
console.log("k is ", k);
When I run this in Node.js, I get:
j is x
k is y
this.j is: undefined
this.k is: undefined
fun1(3,4) is 7
j is x
k is y
this.j is: 3
this.k is: 4
fun1(2,7) is 9
j is x
k is y
Why aren't j and k being set to arguments a and b in the function when they are declared? It just doesn't seem right that I have to do BOTH var j = a; AND this.j = a; !! What am I doing wrong?
In node, the output properly shows that the j and k variables in global are not being clobbered by the local variables j and k in fun1. When I run this in Chrome or Firefox, the global variables DO GET clobbered. In other words I get
j is x
k is y
this.j is: undefined
this.k is: undefined
fun1(3,4) is 7
j is 3
k is 4
this.j is: 3
this.k is: 4
fun1(2,7) is 9
j is 2
k is 7
Why isn't the local scope protecting the global var?
Thanks for any hints.

I recommend you to go read that! :) That explain precisely how to use this and what is the this!
Read here! Mozilla Developper Network
Here is the article if the link is dead. (Sorry, the formating is not perfect and the text is very long.)
Summary
A function's this keyword behaves a little differently in JavaScript
compared to other languages. It also has some differences between
strict mode and non-strict mode.
In most cases, the value of this is determined by how a function is
called. It can't be set by assignment during execution, and it may be
different each time the function is called. ES5 introduced the bind
method to set the value of a function's this regardless of how it's
called.
Syntax this Global context In the global execution context (outside of
any function), this refers to the global object, whether in strict
mode or not.
console.log(this.document === document); // true
// In web browsers, the window object is also the global object:
console.log(this === window); // true
this.a = 37; console.log(window.a); // 37 Function context Inside a
function, the value of this depends on how the function is called.
Simple call
function f1(){ return this; }
f1() === window; // global object In this case, the value of this is
not set by the call. Since the code is not in strict mode, the value
of this must always be an object so it defaults to the global object.
function f2(){ "use strict"; // see strict mode return this; }
f2() === undefined;
In strict mode, the value of this remains at
whatever it's set to when entering the execution context. If it's not
defined, it remains undefined. It can also be set to any value, such
as null or 42 or "I am not this".
Note: In the second example, this should be undefined, because f2 was
called without providing any base (e.g. window.f2()). This feature
wasn't implemented in some browsers when they first started to support
strict mode. As a result, they incorrectly returned the window object.
As an object method
When a function is called as a method of an object, its this is set to
the object the method is called on.
In the following example, when o.f() is invoked, inside the function
this is bound to the o object.
var o = { prop: 37, f: function() {
return this.prop; } };
console.log(o.f()); // logs 37 Note that this behavior is not at all
affected by how or where the function was defined. In the previous
example, we defined the function inline as the f member during the
definition of o. However, we could have just as easily defined the
function first and later attached it to o.f. Doing so results in the
same behavior:
var o = {prop: 37};
function independent() { return this.prop; }
o.f = independent;
console.log(o.f()); // logs 37 This demonstrates that it matters only
that the function was invoked from the f member of o.
Similarly, the this binding is only affected by the most immediate
member reference. In the following example, when we invoke the
function, we call it as a method g of the object o.b. This time during
execution, this inside the function will refer to o.b. The fact that
the object is itself a member of o has no consequence; the most
immediate reference is all that matters.
o.b = {g: independent, prop: 42}; console.log(o.b.g()); // logs 42
this on the object's prototype chain
The same notion holds true for methods defined somewhere on the
object's prototype chain. If the method is on an object's prototype
chain, this refers to the object the method was called on, as if the
method was on the object.
var o = {f:function(){ return this.a + this.b; }}; var p =
Object.create(o); p.a = 1; p.b = 4;
console.log(p.f()); // 5 In this example, the object assigned to the
variable p doesn't have its own f property, it inherits it from its
prototype. But it doesn't matter that the lookup for f eventually
finds a member with that name on o; the lookup began as a reference to
p.f, so this inside the function takes the value of the object
referred to as p. That is, since f is called as a method of p, its
this refers to p. This is an interesting feature of JavaScript's
prototype inheritance.
this with a getter or setter
Again, the same notion holds true when a function is invoked from a
getter or a setter. A function used as getter or setter has its this
bound to the object from which the property is being set or gotten.
function modulus(){ return Math.sqrt(this.re * this.re + this.im *
this.im); }
var o = { re: 1, im: -1, get phase(){
return Math.atan2(this.im, this.re); } };
Object.defineProperty(o, 'modulus', {
get: modulus, enumerable:true, configurable:true});
console.log(o.phase, o.modulus); // logs -0.78 1.4142 As a constructor
When a function is used as a constructor (with the new keyword), its
this is bound to new object being constructed.
Note: while the default for a constructor is to return the object
referenced by this, it can instead return some other object (if the
return value isn't an object, then the this object is returned).
/* * Constructors work like this: * * function MyConstructor(){ *
// Actual function body code goes here. * // Create properties on
|this| as * // desired by assigning to them. E.g., * this.fum =
"nom"; * // et cetera... * * // If the function has a return
statement that * // returns an object, that object will be the *
// result of the |new| expression. Otherwise, * // the result of
the expression is the object * // currently bound to |this| * //
(i.e., the common case most usually seen). * } */
function C(){ this.a = 37; }
var o = new C(); console.log(o.a); // logs 37
function C2(){ this.a = 37; return {a:38}; }
o = new C2(); console.log(o.a); // logs 38 In the last example (C2),
because an object was returned during construction, the new object
that this was bound to simply gets discarded. (This essentially makes
the statement "this.a = 37;" dead code. It's not exactly dead, because
it gets executed, but it can be eliminated with no outside effects.)
call and apply
Where a function uses the this keyword in its body, its value can be
bound to a particular object in the call using the call or apply
methods that all functions inherit from Function.prototype.
function add(c, d){ return this.a + this.b + c + d; }
var o = {a:1, b:3};
// The first parameter is the object to use as // 'this', subsequent
parameters are passed as // arguments in the function call
add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16
// The first parameter is the object to use as // 'this', the second
is an array whose // members are used as the arguments in the function
call add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34 Note that with
call and apply, if the value passed as this is not an object, an
attempt will be made to convert it to an object using the internal
ToObject operation. So if the value passed is a primitive like 7 or
'foo', it will be converted to an Object using the related
constructor, so the primitive number 7 is converted to an object as if
by new Number(7) and the string 'foo' to an object as if by new
String('foo'), e.g.
function bar() { console.log(Object.prototype.toString.call(this));
}
bar.call(7); // [object Number] The bind method
ECMAScript 5 introduced Function.prototype.bind. Calling
f.bind(someObject) creates a new function with the same body and scope
as f, but where this occurs in the original function, in the new
function it is permanently bound to the first argument of bind,
regardless of how the function is being used.
function f(){ return this.a; }
var g = f.bind({a:"azerty"}); console.log(g()); // azerty
var o = {a:37, f:f, g:g}; console.log(o.f(), o.g()); // 37, azerty As
a DOM event handler
When a function is used as an event handler, its this is set to the
element the event fired from (some browsers do not follow this
convention for listeners added dynamically with methods other than
addEventListener).
// When called as a listener, turns the related element blue function
bluify(e){ // Always true console.log(this === e.currentTarget);
// true when currentTarget and target are the same object
console.log(this === e.target); this.style.backgroundColor =
'#A5D9F3'; }
// Get a list of every element in the document var elements =
document.getElementsByTagName('*');
// Add bluify as a click listener so when the // element is clicked
on, it turns blue for(var i=0 ; i
elements[i].addEventListener('click', bluify, false); } In an in–line
event handler
When code is called from an in–line handler, its this is set to the
DOM element on which the listener is placed:
Show this
The above alert shows button. Note however that only the
outer code has its this set this way:
Show inner
this In this case, the inner function's this isn't set so it
returns the global/window object (i.e. the default object in
non–strict mode where this isn't set by the call).

Related

Javascript Function Strange Behavior [duplicate]

What are the exact circumstances for which a return statement in Javascript can return a value other than this when a constructor is invoked using the new keyword?
Example:
function Foo () {
return something;
}
var foo = new Foo ();
If I'm not mistaken, if something is a non-function primitive, this will be returned. Otherwise something is returned. Is this correct?
In other words, what values can something take to cause (new Foo () instanceof Foo) === false?
The exact condition is described on the [[Construct]] internal property, which is used by the new operator:
From the ECMA-262 3rd. Edition Specification:
13.2.2 [[Construct]]
When the [[Construct]] property for a Function object F is
called, the following steps are taken:
Create a new native ECMAScript object.
Set the [[Class]] property of Result(1) to "Object".
Get the value of the prototype property of F.
If Result(3) is an object, set the [[Prototype]] property of Result(1) to Result(3).
If Result(3) is not an object, set the [[Prototype]] property of Result(1) to the original Object prototype object as
described in 15.2.3.1.
Invoke the [[Call]] property of F, providing Result(1) as the this value and
providing the argument list passed into [[Construct]] as the
argument values.
If Type(Result(6)) is
Object then return Result(6).
Return Result(1).
Look at steps 7 and 8, the new object will be returned only if the
type of Result(6) (the value returned from the F constructor
function) is not an Object.
Concrete examples
/*
ECMA 262 v 5
http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
"4.3.2
primitive value
member of one of the types Undefined, Null, Boolean, Number, Symbol, or String as defined in clause 6"
*/
var Person = function(x){
return x;
};
console.log(Person.constructor);
console.log(Person.prototype.constructor);
console.log(typeof(Person));
console.log(typeof(Person.prototype));
function log(x){
console.log(x instanceof Person);
console.log(typeof x);
console.log(typeof x.prototype);
}
log(new Person(undefined));
log(new Person(null));
log(new Person(true));
log(new Person(2));
log(new Person(""));
//returns a function not an object
log(new Person(function(){}));
//implementation?
//log(new Person(Symbol('%')));
I couldn't find any documentation on the matter, but I think you're correct. For example, you can return new Number(5) from a constructor, but not the literal 5 (which is ignored and this is returned instead).
As a side note, the return value or this is just part of the equation.
For example, consider this:
function Two() { return new Number(2); }
var two = new Two;
two + 2; // 4
two.valueOf = function() { return 3; }
two + 2; // 5
two.valueOf = function() { return '2'; }
two + 2; // '22'
As you can see, .valueOf() is internally used and can be exploited for fun and profit. You can even create side effects, for example:
function AutoIncrementingNumber(start) {
var n = new Number, val = start || 0;
n.valueOf = function() { return val++; };
return n;
}
var auto = new AutoIncrementingNumber(42);
auto + 1; // 43
auto + 1; // 44
auto + 1; // 45
I can imagine this must have some sort of practical application. And it doesn't have to be explicitly a Number either, if you add .valueOf to any object it can behave as a number:
({valueOf: function() { return Math.random(); }}) + 1; // 1.6451723610516638
You can exploit this to make an object that always returns a new GUID, for instance.
Trying to put a few points in simpler words.
In javascript, when you use a new keyword on a function and if,
function does not return anything, it will return an intended object
function User() {
this.name = 'Virat'
}
var user = new User();
console.log(user.name); //=> 'Virat'
function returns any truthy complex object [object, array, function etc], that complex object takes priority and user variable will hold the returned complex object
function User() {
this.name = 'Virat';
return function(){};
}
var user = new User();
console.log(user.name); //=> undefined
console.log(user); //=> function
function returns any literal, constructor takes priority and it will return an intended object
function User() {
this.name = 'Virat';
return 10;
}
var user = new User();
console.log(user.name); //=> 'Virat'
When you are using the new keyword, an object is created. Then the function is called to initialise the object.
There is nothing that the function can do to prevent the object being created, as that is done before the function is called.

Super Tricky Javascript quiz, need to figure out about the answer

//1st question
var x = 4,
obj = {
x: 3,
bar: function() {
var x = 2;
setTimeout(function() {
var x = 1;
alert(this.x);
}, 1000);
}
};
obj.bar();
//2nd question
function foo(a) {
arguments[0] = 2;
alert(a);
}
foo(1);
1.why it returns 4 instead of 1? i thought this.x refer to 1, but it seems wrong....i just dont understand why it returns 4
2.why it return alert 2 instead of 1, i thought i pass a to function a, and as far as i know, i pass 1 to function foo, and 1 should be alerted because of a(which is 1 when i pass)....i just don't understand why it alert 2
The runtime (in non-strict mode) invokes the setTimeout() callback with this bound to window (the global context), so this.x refers to the outer x.
The arguments object serves as a way to alias the formal parameters of a function. Setting the value of arguments[0] also sets the value of the first declared parameter to the function.
1. why it returns 4 instead of 1?
Notice the first initialization: var x = 4, which in non-strict mode attaches a property x to global object: window.x = 4.
setTimeout(function() {
var x = 1;
alert(this.x);
}, 1000);
setTimout() callback has this context as the global object. And actually calling alert(this.x) -> alert(window.x) -> alert(4).
2.why it return alert 2 instead of 1
arguments object represents the list of function arguments. When modifying it, you actually modify the arguments values: arguments[0] = 2 modifies first argument a = 2.

On Javascript, why is a function that is not bound using bind() still binds to the object?

In the following code, the first function is not bound to obj, but the second function is, so f() returns fifi and g() returns Mark Twain as expected. But the 3rd attempt, it is by (obj.getCallBack) first, which is now a function, and then it is invoked, essentially it should be the same as the f case. But they do print out Mark Twain instead. Why are they not bound to obj using bind() but still got executed with this pointing to obj?
(the 4th attempt is just a usual invocation of a method, and this should bind to the object on which the method is invoked on).
(tested on the current Chrome, Firefox, and IE 9)
window.name = "fifi";
var obj = {
name: "Mark Twain",
getCallBack: function() {
return this.name;
}
}
var f = obj.getCallBack;
var g = f.bind(obj);
console.log(f);
console.log(f());
console.log(g);
console.log(g());
console.log((obj.getCallBack)());
console.log(obj.getCallBack());
You are forgetting that if a function is called as a property of some object, that object will be the this for the call. So:
obj.getCallBack() //The function referenced by `obj.getCallBack`
//is called as a property of `obj`, so obj will be `this`
//for the call
f() //The function referenced by f, is not called as a property of some object so
//`this` will depend on strict mode.
After these basic rules, the bound function will be invoked, which can be thought of as a proxy function (any shim does this) that uses .call/.apply to explicitly set the context for the target function. So the this value for the proxy function doesn't matter, but behind the scenes it was set by the basic rules.
Edit:
(obj.getCallBack) does not return the function as value, because getValue is not called.. So it is exactly the same as obj.getCallback and the first post applies.
So you can do this and not get an error:
(obj.getCallback) = 5;
As opposed to:
(function(){}) = 5; //invalid assignment
To complement Esailija's answer, the desired effect actually should be:
var obj = {
name: "Mark Twain",
getCallBack: function() {
return function() { return this.name; };
}
}
var f = obj.getCallBack();
var g = f.bind(obj);
console.log(f);
console.log(f());
console.log(g);
console.log(g());
console.log((obj.getCallBack())());
console.log(obj.getCallBack()());
console.log(obj.getCallBack().bind(obj)());
Then in this case, the third attempt will give fifi, and so will the 4th attempt. To get the name inside obj, the fifth attempt binds it and invoke it and will get Mark Twain.
But the method that returns the callBack function should bind it, so let's change the code to:
var obj = {
name: "Mark Twain",
getCallBack: function() {
return (function() { return this.name;}).bind(this); // <-- note here
}
}
and now all attempts, even f(), will return Mark Twain.

JavaScript objects as function parameters

Using JavaScript, say I have a function X, and in that function an object called objectX is created. function X returns objectX. Later in the code function Z(somevar, anObject) receives objectX as one of it's parameters.
Now in function Z, is objectX and all its properties referred to as anObject inside function Z?
And what happens if function Z returns anObject? Will the rest of the code see the object as "objectX" or "anObject"?
function X() {
...
objectX = {};
...
return objectX;
}
X();
function Z(anything, anObject) {
...
return anObject
}
Z(something, objectX);
anObject and objectX both are referencing to the same space in memory, so, name it as you want, it's always the same object.
Good luck!
This is mostly a question of scope.
function X() {
// local objectX, only accessible through this name inside X()
var objectX = {};
objectX.foo = 'bar';
return objectX;
}
function Z(somevar, anObject) {
// anObject is passed in as a parameter
// it's only accessible through this name inside Z()
anObject.foo = somevar;
return anObject;
}
// get the 'objectX' from X() and store it in global variable a
var a = X();
// pass the received 'objectX' into Z()
// note that the variable names objectX and anObject cannot be accessed
// because they are local variables of the functions X() / Z()
var b = Z('baz', a);
// a is now the same as b, they both reference the same var
// a.foo and b.foo both are set to 'baz'
I believe an example is the best way to teach. Here is some code (click here to see it in JS Bin):
// Defines the variable to keep track of how many objects X() defines.
var num = 1;
// Instantiate another variable to see if it is changed by Z().
var anObject;
// Creates an object with a comment and a random number.
function X() {
// Create an object and give it a name.
var objectX = {comment : "Creation #" + num};
// Increase the value of num.
num++;
// Add another random number between 0 and 100 inclusively.
objectX.randNum = Math.round(Math.random() * 100);
// Return objectX.
return objectX;
}
// Modifies the second parameter by adding the value of the first parameter.
function Z(somevar, anObject) {
anObject.somevar = somevar;
return anObject;
}
var objectX = X(), objectY = X();
objectX2 = Z('coolness', objectX);
// Notice that objectX is still the result of calling X() the first time.
alert("objectX.comment = " + objectX.comment);
// Notice that objectX is not equal to objectY.
alert("objectX === objectY evaluates to " + (objectX === objectY));
// Notice that objectX2 is the same thing as objectX.
alert("objectX === objectX2 evaulates to " + (objectX === objectX2));
// Notice that anObject is not defined.
alert("typeof anObject evaluates to " + (typeof anObject) + " after Z is called.");​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​
alert("Now review the JavaScript code.");
If read through the comments, you will find the answers to your questions. First you will notice that in function Z, since I passed objectX as the second parameter, inside of the function, it could be referred to by anObject. Second you will notice that once outside of function Z, anObject no longer refers to objectX. The comments also reveal other things that are true in JavaScript.
Javascript has function scope. This means that every variable declared within a function, will only be accessible from within that function.
If you’d properly declared the objectX variable with var, as follows:
function X() {
...
var objectX = {};
...
return objectX;
}
then objectX would only be known as objectX inside the X function. Elsewhere, it would be known as whatever variable you’d assigned it to. Since in your code, you don’t assign the result of X() to anything, objectX would not be accessible from anywhere.
However, here’s one of Javascript’s more serious design flaws: if you don’t explicitly declare a variable (using the var statement, or as a function parameter), that variable will automatically become a global variable. That means that it will be accessible anywhere.
Because of this, in your code above, you can access objectX everywhere by that name.
anObject, on the other hand, is properly declared (as a parameter), and that means its scope will be limited to the Z function.
In short, the way your code is written, objectX is accessible everywhere by way of the objectX variable, and inside the function Z, you can reference it both as objectX and as anObject.
Do note, however, that global variables are a Bad Thing™, since they can make it quite hard to figure out what variable gets assigned by who, when, and why — as you’ve noticed.
While Javascript makes it impossible to completely avoid them, as a rule you should try to keep the scope of your variables as small as possible (scope = where in your program that variable can be accessed).
To that end, I would recommend refactoring your code like igorw has.
Here is link to jsfiddle
Lets take the following example below:
Person = function(name){
this.name = name;
}
function x(){
var john = new Person('john');
return john;
}
function z(tempVar, anObject){
var newObj = anObject;
newObj.name = tempVar;
return newObj;
}
myPerson = x();
console.log(myPerson.name); //john
console.log(z('peter', myPerson).name); //peter
console.log(myPerson.name); //peter
You can see, even though you created a new object in z but because they are referencing to the same object myPerson's name property is also changed after z() is called.

What does "this" refer to

what is the this (inside inner functions) referring to in the following code context? Does it point to TimeSpan?
var TimeSpan = function (days, hours, minutes, seconds, milliseconds) {
var attrs = "days hours minutes seconds milliseconds".split(/\s+/);
var gFn = function (attr) {
return function () {
return this[attr];
};
};
var sFn = function (attr) {
return function (val) {
this[attr] = val;
return this;
};
};
}
Thanks
The this value is set implicitly depending on how the function is invoked, there are three cases where this happens:
When a reference with no base-object, or a non-reference is invoked:
myFn(); // the myFn reference has no base object
(function () {})(); // non-reference
The this value will point to the global object 1
When a reference contains a base object, for example:
myObj.method();
The this value inside method will point to myObj.
When the new operator is used:
var obj = new Foo();
The this value inside the Foo function, will point to a newly created object that inherits from Foo.prototype.
The this value can be set also explicitly, by using the call and apply methods, for example, with call:
function test(a) {
return alert(this + a);
}
test.call("hello", " world"); // alerts "hello world"
Or with apply if we need to "apply" a set of arguments from an array to a function:
function test(a, b) {
return alert(this + a + b);
}
var args = ["my ", "world "];
test.apply("hello ", args); // alerts "hello my world"
[1] This has changed on the new ECMAScript 5th Strict Mode, now when a function reference with no base object, or a non-reference is invoked (as the first case), the this value will contain undefined.
This was made because when working with constructor functions, people often forgot to use the new operator when calling the constructor.
When that happened, the this value pointed to the global object, and that ended up adding unwanted global properties.
Now on strict mode, this will contain undefined, and if property lookup is made on it (this.foo = 'foo') we will have a nice TypeError exception, instead of having a global foo property.
this refers to the current object, in this case the function you are inside of. Since everything in JavaScript is an object you can modify the attributes of a function object using the this keyword:
var f = function() {
this.key = "someValue";
}
console.log(f.key); // prints "someValue"
So in this case this should point to the function at the deepest scope level, and not TimeSpan.

Categories

Resources