Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

javascript prototype and "this" access in closure

I am a beginner in js, and am puzzled by the following code:

Foo = function(arg) {
    this.arg = arg;
};

Foo.prototype = {
    init: function () {
        var f = function () {
            alert("current arg: " + this.arg); // am expecting "bar", got undefined
        }
        f();
    }
};

var yo = Foo("bar");
yo.init();

I was expected to get "current arg: bar", but got "current arg: undefined". I noticed that by copying this.arg into a "normal" variable first, and refering this variable in the closure works:

Foo.prototype = {
    init: function () {
        var yo = this.arg;
        var f = function () {
            alert("current arg: " + yo);            }
        f();
    }
};

Am I doing something wrong, got wrong expectations, or does it fall into one of the js WTF ?

like image 736
David Cournapeau Avatar asked Nov 12 '10 05:11

David Cournapeau


People also ask

What are JavaScript prototypes and closures?

The Prototype Closure coding style organizes the constructor and prototype methods inside a closure for easy identification of the prototype object. var AdditionUtility = (function(){ var Constructor = function(value){ this. value = value || 0; }; Constructor. prototype = { value: null, add: function(numToAdd) { this.

What is the closure in JavaScript can access?

This is called a JavaScript closure. It makes it possible for a function to have "private" variables. The counter is protected by the scope of the anonymous function, and can only be changed using the add function. A closure is a function having access to the parent scope, even after the parent function has closed.

What is difference between __ proto __ and prototype?

prototype is a property of a Function object. It is the prototype of objects constructed by that function. __proto__ is an internal property of an object, pointing to its prototype.

What is JavaScript prototype inheritance?

The Prototypal Inheritance is a feature in javascript used to add methods and properties in objects. It is a method by which an object can inherit the properties and methods of another object. Traditionally, in order to get and set the [[Prototype]] of an object, we use Object. getPrototypeOf and Object.


2 Answers

Vanilla functions will be run with this referring to window. Your second piece of code is a perfect example of how to work around this problem using closures.

(You can also use call and apply to call a function with a particular context.)

like image 180
theazureshadow Avatar answered Sep 27 '22 21:09

theazureshadow


It depends on how the function was invoked.

If invoked with keyword new then this refers to the object being constructed (which will be implicitly returned at the end of the function).

If invoked as a normal function, this refers to the global window object.

Example:

// Constructor for Foo,
// (invoke with keyword new!)
function Foo()
{
  this.name = "Foo" ;
}

myFoo = new Foo() ;
alert( 'myFoo ' + myFoo.name + '\n' + 'window: ' + window.name ) ; // window.name will be empty

// now if we invoke Foo() WITHOUT keyword NEW
// then all references to `this` inside the
// function Foo will be to the
// __global window object__, i.e. the global window
// object will get clobbered with new properties it shouldn't
// have! (.name!)

Foo() ;  // incorrect invokation style!
alert( 'myFoo ' + myFoo.name + '\n' + 'window: ' + window.name ) ;

JavaScript doesn't have "constructors" per se, the only way JavaScript knows that your function is actually a "constructor" is invokation style (namely you using keyword new whenever you invoke it)

like image 30
bobobobo Avatar answered Sep 27 '22 21:09

bobobobo