Javascript: why "this" inside the private function refers to the global scope? - javascript

Consider the following code:
function A() {}
A.prototype.go = function() {
console.log(this); //A { go=function()}
var f = function() {
console.log(this); //Window
};
f();
}
var a = new A();
a.go();
Why does 'this' inside function 'f' refers to the global scope? Why it is not the scope of function 'A' ?

JavaScript has a different concept of what the special name this refers to
than most other programming languages do. There are exactly five different
ways in which the value of this can be bound in the language.
The Global Scope
this;
When using this in global scope, it will simply refer to the global object.
Calling a Function
foo();
Here, this will again refer to the global object.
ES5 Note: In strict mode, the global case no longer exists.
this will instead have the value of undefined in that case.
Calling a Method
test.foo();
In this example, this will refer to test.
Calling a Constructor
new foo();
A function call that is preceded by the new keyword acts as
a constructor. Inside the function, this will refer
to a newly created Object.
Explicit Setting of this
function foo(a, b, c) {}
var bar = {};
foo.apply(bar, [1, 2, 3]); // array will expand to the below
foo.call(bar, 1, 2, 3); // results in a = 1, b = 2, c = 3
When using the call or apply methods of Function.prototype, the value of
this inside the called function gets explicitly set to the first argument
of the corresponding function call.
As a result, in the above example the method case does not apply, and this
inside of foo will be set to bar.
Note: this cannot be used to refer to the object inside of an Object
literal. So var obj = {me: this} will not result in me referring to
obj, since this only gets bound by one of the five listed cases.
Common Pitfalls
While most of these cases make sense, the first one is to be considered another
mis-design of the language because it never has any practical use.
Foo.method = function() {
function test() {
// this is set to the global object
}
test();
}
A common misconception is that this inside of test refers to Foo; while in
fact, it does not.
In order to gain access to Foo from within test, it is necessary to create a
local variable inside of method which refers to Foo.
Foo.method = function() {
var that = this;
function test() {
// Use that instead of this here
}
test();
}
that is just a normal variable name, but it is commonly used for the reference to an
outer this. In combination with closures, it can also
be used to pass this values around.
Assigning Methods
Another thing that does not work in JavaScript is function aliasing, which is
assigning a method to a variable.
var test = someObject.methodTest;
test();
Due to the first case, test now acts like a plain function call; therefore,
this inside it will no longer refer to someObject.
While the late binding of this might seem like a bad idea at first, in
fact, it is what makes prototypal inheritance work.
function Foo() {}
Foo.prototype.method = function() {};
function Bar() {}
Bar.prototype = Foo.prototype;
new Bar().method();
When method gets called on a instance of Bar, this will now refer to that
very instance.
Disclaimer: Shamelessy stolen from my own resources at http://bonsaiden.github.com/JavaScript-Garden/#function.this

The reason why is you are invoking f as a function and not a method. When invoked as a function this is set to window during the execution of the target
// Method invocation. Invoking a member (go) of an object (a). Hence
// inside "go" this === a
a.go();
// Function invocation. Invoking a function directly and not as a member
// of an object. Hence inside "f" this === window
f();
// Function invocation.
var example = a.go;
example();

The scope of all functions is window.
To circumvent that, you can do this:
function A() {}
A.prototype.go = function() {
var self = this;
console.log(self); //A { go=function()}
var f = function() {
console.log(self); //A { go=function()}
};
f();
}

Because function f() is not called without any object reference. Try,
f.apply(this);

Related

Can someone explain working of this js code with reference to 'this' keyword?

JS code is:
this.sound1 ="global";
function cat(){
this.sound = 'meawo!!!!';
this.sound1 = 'meawooooo!!!!';
meawo1 = function(){
console.log(this.sound1);
console.log(this);
};
function meawo2(){
console.log(this.sound1);
console.log(this);
};
this.meawo = function(){
console.log(this.sound);
console.log(this);
meawo1();
meawo2();
};
};
var c = new cat();
c.meawo();
Output is:
Question: How come this inside of meawo1(function expression) & meawo2(function expression declaration) is referring to "global" and not to object c? Why is that?
Always remember a simple tip while wanting to know to which object does this refer to.
obj.method();
In the above, method's is called on obj, and hence the this in method will be what it's called on, i.e obj = this.
In your case, though meowo is called on c, meowo1 and meowo2 aren't on the object you want it to refer to.
Functions which don't have an explicit scope from which they are called, default to global context, though the function itself isn't global and can leverage all the variables in its parent context due to a closure.

Function object, context and this [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
this operator in javascript
The term context is bit confusing me.If i declare a function within a function i.e nested function and execute there itself,like below...
function foo(){
function fo(){
alert(this);
}
fo();
}
the this keyword should point to the function object rather than window since function fo() is within its parent function.Since function is also an javascript object,than why the this keyword is traversing the function object and pointing to window?
Also this keyword points to the current object on which the function operates ,so function object is the object on which the nested function operates.
If you just call foo() in the top level, it is identical to window.foo().
And window is the actual context of foo, so, this points to the window object.
Adding to what dlutxx said. If you have a function (in the global space) and you simply call it like foo() the context is the window itself (since the function is a member of the window object). However, if you use the new keyword for getting a new instance of the function, this will refer to the function object.
function foo() {
alert(this);
}
foo(); // "this" inside the function will be window
new foo(); // "this" inside the function will be the function object.
If you want to have a custom value for this inside the function, you can call it using .call() like:
foo.call(x); // "this" inside the function will be x
Example code for your case:
function foo(){
function fo(){
alert(this);
}
fo(); // "this" is window
new fo(); // "this" is the function object
fo.call('x'); // "this" is 'x'
}
If you randomly use this inside of a function which is NOT a constructor, then you will get one of a few different results:
function callThis () { return this; }
callThis(); // returns window object
var Bob = { func : callThis };
Bob.func(); // returns Bob
callThis.call(Bob); // returns Bob
Call is a method which is used to determine the context of the call.
If the call's context can not be determined by:
a. What's in front of the "." (Bob.func();)
b. What's explicitly passed into .call(), .apply() or .bind()
Then it's set to window.
That is how context is resolved.
So if you have a specific object in mind for this, then your solutions are as follows:
function objMethod () {
var self = this;
function doStuff () {
self.otherFunc();
self.otherProperty = "bob";
}
doStuff();
}
var myObj = { myMethod : objMethod };
myObj.myMethod();
myObj calls objMethod with the context set to myObj.
objMethod saves a reference to the current context (myObj) as self. doStuff uses the reference to modify the properties of the referenced object.
function outer () {
function inner () { this.property = "Bob"; }
inner.call(this);
}
var obj = {};
outer.call(obj);
Here, outer is passed a context, using .call().
Then inner is passed the this of outer, again, using .call()
var bob = { name : "Bob" };
function sayName () { console.log(this.name); }
var bobFunc = sayName.bind(bob);
bobFunc();
Here, we use .bind() to create a version of sayName where this is always set to bob.
You can feel free to mix and match these systems all you'd like (and when dealing with async programming, you likely will).
my understanding is that although function fo() is defined in the scope of function foo(), which means that it is not accessible from outside of foo unless you return it, the rules that apply to the value of this when you call this internal function, are still the same as if you called any other function.
function f() {
function g() {
console.log(this)
}
console.log(this);
g();
g.apply(this);
}
f() // => Window, Window, Window
f.apply(this) // => Window, Window, Window
f.apply({}) // => Object, Window, Object

What does "Object.call" mean?

function bb_graphics_GraphicsContext(){
Object.call(this);
this.bbdevice=null;
this.bbmatrixSp=0;
this.bbix=1.000000;
this.bbiy=0;
this.bbjx=0;
this.bbjy=1.000000;
this.bbtx=0;
this.bbty=0;
this.bbtformed=0;
this.bbmatDirty=0;
this.bbcolor_r=0;
this.bbcolor_g=0;
this.bbcolor_b=0;
this.bbalpha=0;
this.bbblend=0;
this.bbscissor_x=0;
this.bbscissor_y=0;
this.bbscissor_width=0;
this.bbscissor_height=0;
this.bbmatrixStack=new_number_array(192);
}
What does Object.call(this) mean?
Functions in JavaScript are full-fledged objects. They also, when passed as an argument to another function, don't retain their scope. So, in the following code...
var obj1 = {
property1: "blah",
method1: function () {
alert(this.property1);
// do stuff
}
};
function func1 (passedFunction) {
passedFunction();
// do other stuff
}
func1(obj1.method1);
... func1 will call obj1.method1, but it won't alert the value of obj1's property1, because all we've done is pass the function object, not its this context. That's where call and apply come in. They allow you to inject scope, tell the function what the meaning of this will be. The following example works:
var obj1 = {
property1: "blah",
method1: function () {
alert(this.property1);
// do stuff
}
};
function func1 (passedObject, passedFunction) {
passedFunction.call(passedObject);
// do other stuff
}
func1(ob1, obj1.method1);
Now, we've forced or explicitly told obj1.method1 what its context will by invoking call, and passing it the object it's to use as this.
call and apply are almost identical, except for how they handle additional arguments to the function being invoked. See these articles on MDN for more information: call, apply and Function.
All of this having been said, bb_graphics_GraphicsContext is a constructor. (Which you've probably guessed.) You invoke it by using the new keyword, var obj1 = new bb_graphics_GraphicsContext();. When it reaches line 1 of the function, it takes the this object, and calls the generic Object constructor, explicitly injecting the new object this (in the bb_graphics_GraphicsContext constructor) as the this of the Object constructor. I'd assume the writer of this function/constructor was doing this to make sure that the newly created object in bb_graphics_GraphicsContext was getting all the base methods of the base Object. But I don't know why this would be necessary, as if you call bb_graphics_GraphicsContext with the new keyword it will grab all these properties naturally.
Object.call will execute a certain function under the provided context, it can be used to call functions from one object on an other.
The mozilla dev network provides a very good explanation
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/call
This will do absolutely nothing except wasting resource and memory allocation.
If the Object.call(this) will have been assigned to a variable or property of the function constructor bb_graphics_GraphicsContext
this.myObject = Object.call(this)
The only thing that you get in that instance is an empty object "THAT DO NO HOLD THE PROVIDED CONTEXT"
function MyConstructor(){
this.test01 = 0;
var b = Object.call(this); // similar to b = {}; or b = new Object()
console.log(b); // log object
console.log(b.test); // log undefined
this.test = 1;
}
var myObject = new MyConstructor();
console.log(myObject, window.test01)
Although Object.call will probably do nothing as expressed here, the concept might be important. Basically, the example you will see on inheritance in the Node.js documentation is:
const util = require('util');
const EventEmitter = require('events');
function MyStream() {
EventEmitter.call(this);
}
util.inherits(MyStream, EventEmitter);
The util.inherits will make a new MyStream inherit (have the same prototype as) EventEmmiter. This could be enough if we are interested in MyStream having access to the functions inherited through the EventEmmiter prototype. But what if there are variables passed on construction? What if we have:
function MyObject() {
this.code = "2nV_ahR";
}
In this case, the code variable is passed on runtime when MyObject gets instantiated. Therefore, a subclass needs to pass:
function MySubObject() {
MyObject.call(this);
}
In order to inherit the code variable. What call does accept a parameter that sets the this variable. So... when I do var o = new MySubObject(), the this inside of MySubObject refers to o, which is then passed to the call method, so that when MyObject does this.code = ... it is actually passing the code to o!
Every JavaScript function has a toString(), call() and apply().
Read more about them on this odetocode.com article

Namespaces in JavaScript: do I need to rewrite all my variable and function references?

I am namespacing some JavaScript code, and I want to know if I have rewritten all my function calls and references to global variables correctly. The current code is this:
var x = 10;
function foo() {
console.log('foo');
bar();
},
function bar() {
console.log('bar', x);
}
foo();
I have rewritten it as follows:
var namespace = {
x : 10,
foo: function() {
console.log('foo');
// Is this the correct way to call bar?
this.bar();
},
bar: function() {
// Is this the correct way to refer to x?
console.log('bar', this.x);
}
};
namespace.foo();
Is this correct, i.e. do I need to rewrite all function calls (EDIT: by which I mean all inside the namespace variable) to this.functionname() and all global variables to this.variablename?
If you like, you can make yourself some "real" private variables and methods by incorporating a closure. I favour the module pattern.
var ns = (function () {
var x = 10;
return {
foo: function () {
console.log('foo');
this.bar();
},
bar: function () {
console.log('bar', x);
},
increment: function () {
x++;
}
}
}());
ns.foo();
ns.increment();
ns.foo();
http://jsfiddle.net/DjYue/
No, in some places (code that calls those functions from outside of your namespace object) you would have to call namespace.foo(), namespace.bar(), namespace.varName
Actually, if you use namespace.bar() from the function in the object itself, you get the added benefit that your functions don't depend on context. That is, the following code doesn't work with what you have
var fun = namespace.foo;
fun(); // This would break, since the this value is going to be the global object
I usually don't like to use this from literal objects because of the problem mentioned above. It's definitely a preference, I just prefer to avoid problems with this
No, you shouldn't rewrite to this.funcname() but rather namespace.funcname(). The this keyword is reserved to refer to the current context object (or whatever it's called), meaning that you'd use it within your "namespaced" code to refer to the namespace object.
And generally, it's good to know that you aren't actually working with namespaces as you'd know it from more classical OOP. JavaScript is a prototype-based language, which means that you don't have namespaces - rather, what you're creating is an object containing several properties and methods. As previously mentioned, when you're working with methods of the object, the this keyword refers to the object itself. You'd need a reference to the object when outside of it's context.
Currently, the approach of using objects to contain all of your code as a sort of namespaces and classes in disguise is diminishing in favor of closures which attaches the methods and properties that should be publicly available to a function (which, in JavaScript, is a first class object), and either returns that function or attaches it to the global object. You may also, alternatively, use a function to contain the properties and methods instead of an object.
I disagree with the people who say No to your question. It really depends on what you want to accomplish here. Based the rewritten code, I don't see anything wrong with it. As long as you call namespace.foo(), the execution context of each function should be namespace. Thus, it is not wrong to use this.
There is a situation that invoking the function foo() will not work:
var foo1 = namespace.foo;
foo1();
Although foo1 is same as the function namespace.foo, foo1's execution context has changed. this will refer to window, not namespace.
Their is no need to rewrite that much because you can have more than one reference to a function - a private and a public one.
var namespace = (function() {
var ns = {}; // the 'namespace'
var x = 10;
var foo = // 'private' reference: bar();
ns.foo = // 'public' reference: ns.bar() -> namespace.bar();
function foo() { // the name is optional because it's a function expression
console.log('foo');
bar();
}; // don't forget the semicolon
var bar =
ns.bar =
function() {
console.log('bar', x);
};
return ns; // return the 'namespace'
})();
namespace.foo();
var foo = namespace.foo;
foo();
delete namespace.bar;
// namespace.bar(); // Error
foo(); // bar is called

this value in JavaScript anonymous function

Can anybody explain to me why A is true and B is false? I would have expected B to be true as well.
function MyObject() {
};
MyObject.prototype.test = function () {
console.log("A", this instanceof MyObject);
(function () {
console.log("B", this instanceof MyObject);
}());
}
new MyObject().test();
update:
since ecmascript-6 you can use arrow functions which would make it easy to refer to MyObject like this:
function MyObject() {
};
MyObject.prototype.test = function () {
console.log("A", this instanceof MyObject);
(() => {//a change is here, which will have the effect of the next line resulting in true
console.log("B", this instanceof MyObject);
})(); //and here is a change
}
new MyObject().test();
Inside of your anonymous function this is the global object.
Inside of test, this is the instance of MyObject on which the method was invoked.
Whenever you call a function like this:
someFunction(); // called function invocation
this is always the global object, or undefined in strict mode (unless someFunction was created with bind** — see below)
Whenever you call a function like this
foo.someMethod(); //called method invocation
this is set to foo
**EcmaScript5 defines a bind function that allows you to create a function that has a pre-set value for this
So this
var obj = { a: 12 };
var someFunction = (function () { alert(this.a); }).bind(obj);
someFunction();
Causes someFucntion to be invoked with this equal to obj, and alerts 12. I bring this up only to note that this is a potential exception to the rule I mentioned about functions invoked as
someFunction();
always having this equal to the global object (or undefined in strict mode)
this is special. It refers to the object that the function is being called on behalf of (most commonly via dot syntax).
So, in the case of A, the function is being called on behalf of a new MyObject object. B is in a different function that isn't explicitly being called on behalf of any object, so this defaults to the global object (window).
In other words, this changes depending on how the function is called, not where or how it is defined. The fact that you're using an anonymous function (defined inside another function) is coincidental and has no effect on the value of this.
In the anonymous function, this is bound to the global object (window in a browser environment).
There are various ways of accessing the instance:
var self = this;
(function () {
console.log("B", self instanceof MyObject);
}());
or
(function () {
console.log("B", this instanceof MyObject);
}).call(this);
this is set based on how you call the function.
Your anonymous function is a normal function call, so this is the global object.
You could write (function() { ... }).call(this) to explicitly call it with your this.

Categories

Resources