Could you please tell me what is Menu in the return statement below (return Menu;) ? Is it a variable (which is not defined) or the name of the inner function ?
var Menu = (function () {
// A straightforward constructor.
function Menu(item_list, total_pages) {
// The this keyword is mandatory.
this.items = item_list;
this.pages = total_pages;
}
// Methods
Menu.prototype.list = function () {
console.log("Our menu for today:");
for (var i = 0; i < this.items.length; i++) {
console.log(this.items[i]);
}
};
return Menu;
}());
Is it a variable...?
Effectively. It comes from the function declaration:
function Menu(item_list, total_pages) {
// The this keyword is mandatory.
this.items = item_list;
this.pages = total_pages;
}
Function declarations create what the spec calls a "binding" in the current execution context for the scope. It's effectively a variable.
So return Menu; returns the Menu function reference out of the anonymous function, and the outer var Menu = ... assignment assigns it to the Menu variable in the containing scope.
Function declarations create a variable, in the scope of the function they are declared in, with a name that is the same as the name of the function itself.
So the return value is the function, which is the same as the value of the Menu variable.
function return_function() {
function foo() {
console.log(1);
}
console.log(foo);
var bar = foo;
foo = 2;
console.log(foo);
return bar;
}
var baz = return_function();
baz();
Related
I have read this answer and IIFE but I can't seem to find the correct solution to my problem.
I have a simple class here:
define(['jquery'], function($) {
// Need 'self' because someCallback() is being called with .call() and 'this' changes
var self;
function Foo(number) {
self = this;
this.someNumber = number;
}
Foo.prototype = {
someCallback: function () {
//Use self because 'this' changes to a DOM element
var num = self.someNumber;
//Do something with the num
return num * 2;
}
};
return Foo;
});
and someCallBack() is being called by a jQuery plugin using .call(). Because of this, the context changed, hence the use of the self variable.
However, this is wrong because:
define(['foo'], function(Foo) {
describe('context question', function () {
var foo1 = new Foo(1);
var foo2 = new Foo(2);
it('"this" should work', function () {
var call1 = foo1.someCallback.call(this); // 4
var call2 = foo2.someCallback.call(this); // 4
expect(call2).toBe(4); // Only works because it is 'new' last
expect(call1).toBe(2); // Fails because 'self' is taken from foo2
});
});
});
How exactly should I wrap the self variable to make this code work?
You could probably just use the revealing module pattern and declare it as a "global" variable (local to the module):
define(['jquery'], function($) {
var someNumber;
function Foo(number) {
someNumber = number;
}
Foo.prototype = {
someCallback: function () {
return someNumber * 2;
}
};
return Foo;
});
Two ways of calling an object method which stores its own this value include
Define the method as a nested function which references its this value in a closure which stores this value in a variable. The function defined could be anonymous or declared with a name but must be evaluated each time a class instance is created, so as to create a new Function object capturing different values of self in function scope.
Take a statically defined function object and bind its this value using bind. Bind creates a new wrapper function object each time it is called.
The first method looks like (without Jquery or Jasmine):
function Foo(number)
{ var self = this;
this.num = number;
this.someCallback = function() // method with new Foo object stored as self in function scope
{ // something with num:
return self.num * 2;
}
}
and the second method could look like
function Foo(number)
{ this.num = number
this.someCallback = this.someCallback.bind(this); // bind prototypical method as local method.
}
Foo.prototype = {
someCallback: function () {
// this value is bound by constructor;
//Do something with the num
return this.num * 2;
}
};
I have this code - I just wonder why after I add 'var' to foo variable, it doesn't work (it shows me foo is undefined)... Can anyone help explain these two functions? Thanks!
window.onload = function() {
var test = foo().steps(2);
console.log(test);
}
(function() {
//if I remove var, then it prints out a function which is what I expected
var foo = function() {
var steps = 1;
function callMe(g) {
//do something else
console.log("hello" + g);
}
callMe.steps = function(x) {
//if no arguments then return the default value
if (!arguments.length) return steps;
console.log(arguments);
//otherwise assign the new value and attached the value to callMe
steps = x;
return callMe;
}
return callMe;
}
})();
adding var to foo makes foo a local variable inside the IIFE and thus you can't access it outside.
I have following function:
function outer(){
index = 1;
inner();
}
function inner(){
alert(this.index);
}
I want to see 1 in alert. Also I want that function inner would without arguments.
Is it possible?
You can specify the context manually when invoking a function with Function.prototype.call
function outer () {
this.index = 1;
inner.call(this);
}
If you define the index variable outside the scope of the outer() function, it will be available to both functions.
var index = 0;
function outer() {
index = 1;
inner();
}
function inner() {
alert(index);
}
outer(); // alerts "1"
You could use apply the functions to an object, which would control the context:
function blarg() {
var self = this;
self.outer = function(){
self.index = 1;
self.inner();
};
self.inner = function(){
alert(self.index);
};
self.outer(); // Call it in the constructor
self.go = function() {
self.outer(); // Or in another function
};
}
var blargObj = new blarg();
blargObj.go();
I've been playing with the new ECMAScript 6 features and this question has to do with arrow functions. The following code is a simple functional composition method assigned to the Function object's prototype. It works perfectly well using a simple anonymous function but does not when using an arrow function instead.
Function.prototype.compose = function (bar) {
var foo = this;
return function () {
return foo(bar.apply(null, arguments));
};
};
var addFive = function (baz) {
return baz + 5;
};
var addTen = function (hello) {
return hello + 10;
};
var addFifteen = addFive.compose(addTen);
console.log(addFifteen(10));
http://jsfiddle.net/oegonbmn/
Function.prototype.compose = function (bar) {
var foo = this;
return () => foo(bar.apply(null, arguments));
};
var addFive = function (baz) {
return baz + 5;
};
var addTen = function (hello) {
return hello + 10;
};
var addFifteen = addFive.compose(addTen);
console.log(addFifteen(10));
http://www.es6fiddle.com/hyo32b2p/
The first one logs 25 correctly to the console whereas the second one logs function (hello) { return hello + 10; }105 which doesn't exactly tell me what I'm doing wrong.
I am not returning the value within the arrow function since it is supposed to implicitly return the very last statement (the first and last in this instance) and I suppose the issue at hand has something to do with the lexical scoping and the values of this, maybe. Can anyone explain?
Both this and arguments are not (re)bound in arrow functions, but instead lexically scoped. That is, you get whatever they are bound to in the surrounding scope.
In ES6, using arguments is deprecated anyway. The preferred solution is to use rest parameters:
Function.prototype.compose = function (bar) {
return (...args) => this(bar.apply(null, args));
};
or, in fact:
Function.prototype.compose = function (bar) {
return (...args) => this(bar(...args));
};
When I use var keyword to declare any variable it gets declared inside the enclosing scope. However in the code below, I have declared function c (inside an object method a.b) with var keyword and still this inside the function c is bound to the global object window. Why is this?
var a = {
b: function () {
var c = function () {
return this;
};
return c();
}
};
document.write(a.b()); //prints: [object Window]
The value of this is determined by context, not scope.
When you call a function without any context (context.func()) as you do there (c()), the default context is the default object (which is window in browsers) unless you are in strict mode (in which case it is undefined instead).
(There are exceptions to this rule, such as apply, call, bind, and new but none of them apply here).
Many people get confused by this. The value this depends on one of 4 methods of invocation.
However, functional invocation and method-invocation cause most of the confusion.
If a function is a member of an object, this is the object itself.
obj.someFunction(); //method invocation
If a function is called without context this is the global object (in 'strict mode' this is undefined.)
someFunction(); //functional invocation
The confusion occurs when a function is called within an object, but not as a member of the object as in anObject.testWithHelper(..);
var testForThis = function(isThis, message) {
//this can be confusing
if(this === isThis)
console.log("this is " + message);
else
console.log("this is NOT " + message);
};
//functional invocation
testForThis(this, "global"); //this is global
var anObject = {
test: testForThis, //I am a method
testWithHelper: function(isThis, message) {
//functional invocation
testForThis(isThis, message + " from helper");
}
};
//method invocation
anObject.test(anObject, "anObject"); //this is anObject
//method invocation followed by functional invocation
anObject.testWithHelper(anObject, "an object"); //this is NOT anObject from helper
Here is my JSFIDDLE
If you would like c to return a, you can use closure:
var a = {
b: function () {
var that = this;
var c = function () {
return that;
};
return c();
}
};
Or avoid this all together:
var getNewA = function() {
var newA = {};
newA.b = function() {
var c = function() {
return newA;
};
return c();
};
return newA;
};
var newA = getNewA();