Can anyone please explain me the behavior of this code?
var arguments = 42;
var arr = () => arguments;
arr(); // 42
function foo() {
var f = (i) => arguments[0] + i; // foo's implicit arguments binding
return f(2);
}
foo(1); // 3
I know what implicit arguments binding is.
What I don't understand is how foo(1) is returning 3?
What does return f(2) does? As in which function it calls?
PS: I'm following this Mozilla docs.
Arrow functions do not bind arguments so when you use arguments[0] inside f you are accessing foo's arguments (ie 1). Since you have passed 2 as i you get 1 + 2
For example if you use an arrow function that tries to access arguments outside of a function call you should get a ReferenceError
const f = i => console.log(arguments[0])
try {
f()
console.assert(false, 'should not get here')
} catch (e) {
console.assert(e instanceof ReferenceError,
'should get reference error on trying to access arguments')
console.log(e.message)
}
To make this a little clearer for you I'll re-write it as ES5
function foo(){
var arg1 = arguments[0]; // argument is 1 in your example
var f = function(i) {
return arg1 + i; // i is 2 in your example
};
return f(2); // returns 3
}
foo(1); // sets argument to 1 and returns 3
In ES6 arrow functions do not have an arguments property like standard functions. You're accessing the foo function arguments array like object. As the first argument you passed in is 1, the arrow function accesses the foo function arguments object and retrieves the first value within the arrow function.
Related
So I'm learning Javascript and I see this code:
var apple = {//... an object with some properties};
var fruit = apple.someMethod(function (b) {return b.a_property_of_apple});
Where someMethod and a_property_of_apple are valid methods and properties.
My question pertains to the argument, b, of the anonymous function which is not declared or defined anywhere else:
function (b) {return ...
What is going on here? What is b and why is it being used?
Apologies in advance for the basic nature of the question. If someone just wants to drop some focused terms on me to read up on that would be great short of an explanation.
The anonymous function is a callback function being passed to the apple.method() invocation.
apple.method() will invoke that anonymous function at some point during it's execution, ( or pass it to another function ). Whenever it's invoked it will be invoked with an argument that will be available inside the callback. You could call it b, or response, or whatever you want (logical names are best) and be able to use it within the anonymous function.
You should read about Callback functions over at MDN.
EDIT: I will explain the parts to you
var apple = {} This is the definition of an object
var fruit = apple.someMethod(function (b) {return b.a_property_of_apple}); is defining that fruit is equal to the return value of the invocation of apple.someMethod(...)
apple.someMethod(function (b) {return b.a_property_of_apple}); is the invocation of apple.someMethod with function (b) {return b.a_property_of_apple} as the only argument.
The b argument in the anonymous function function (b) {return b.a_property_of_apple} will be passed to it's invocation within the apple.someMethod.
Here is an example snippet.
// define apple
var apple = {
// define method
someMethod: function( callback ) {
var obj = {
a_property_of_apple: "Eat me!" // this will be returned
}
// return the invocation of callback with obj as argument
return callback(obj);
}
}
var fruit = apple.someMethod(function (b) {return b.a_property_of_apple});
console.log(fruit);
EDIT: Ok, going to use something slightly less abstract as an example.
// notice employees being passed to this function
// that is called an argument and is usable inside the function
var orginization = function( employees ) {
// this will take the empoyees argument and assign it to this.employees
// or set this.employees to an empty array if there is no employees argument
this.employees = employees || [ ];
// this is a method ( a method is a function on an object )
// this function takes 3 arguments
this.addEmployee = function( employee ) {
// we use the 3 arguments to push a new object with title, name, and salary
// properties provided by the function arguments
this.employees.push( employee );
}
// this method returns the value stored in this.employees
this.getEmployees = function() {
return this.employees;
}
}
// this is a variable an array of employees only containing 1 employee
// i will use it in the creation of my new orginization
var employess = [
{
title: "CEO",
name: "Enola",
salary: "$$$$$$$"
}
];
// i use the new to create learningInc from originization( employees )
// originization is a constructor function which creates an object
// with methods and properties found on the constructor
var learningInc = new orginization( employess );
// console.log learningInc.getEmployees() an you will see still only the CEO
// works here
console.log( "before newHire: ", learningInc.getEmployees() );
// lets make a newHire
var newHire = {
title: "Peon",
name: "Sadly McFrownFace",
salary: "$"
};
// add the newHire to the employess of learningInc wth out getEmployees() method
learningInc.addEmployee( newHire );
// log the new value of learningInc.getEmployees and you see we now have 2 employees
console.log( "after newHire: ", learningInc.getEmployees() );
Ok now notice this line var learningInc = new orginization( employess );
The employees variable I'm passing to this function as an argument is used in this function var orginization = function( employees ) { ... }.
Hope this help.
My question pertains to the parameter, b, of the anonymous function which is not declared or defined anywhere else: What is going on here?
What is b and why is it being used?
Why you say it is not declared? It is declared right there. Consider this simple JavaScript function:
function doSomething(a, b){
//do something here;
}
In this code, we are creating a function, naming it "doSomething", and declaring two parameters for it a and b. This is how we declare function parameters in JavaScript. Now your example:
function (b) {return ...
is exactly the same, except we didn't give this function a name, which means it is an anonymous function. That's the only difference, but its parameter b is declared right there like any standard function. So there is nothing special going here, it's a standard function parameter and used as such.
There are a couple concepts at work here
Function declarations vs function expressions; you can use function as an operator to define a function, and assign the function to an identifier and pass it around like any normal object
Callbacks; you can pass a function CB into another function A to be called by A (as defined by A)
Passing something without an identifier
Function Declaration
// declare function
function foo(argFoo) {
console.log('foo', argFoo);
}
// invoke function
foo('was declared'); // "foo" "was declared"
Function Expression
// express function
var bar = function (argBar) {
console.log('bar', argBar);
};
// invoke function
bar('was expressed'); // "bar" "was expressed"
Callbacks
function fizz(callback) {
console.log('first I fizz');
callback();
}
function buzz() {
console.log('then I buzz');
}
fizz(buzz);
// "first I fizz"
// "then I buzz"
Passing without an Identifier,
Basically, defining things in-place
// say we have some fn fizzbuzz
function fizzbuzz(foo) {
console.log(foo);
}
// we could pre-define what we want to pass to it
var i = 1;
fizzbuzz(i); // 1
// or we could pass directly
fizzbuzz(1); // 1
// with anything we like
fizzbuzz({some: 'object'}); // {some: "object"}
// even a function
fizzbuzz(function () {}); // function () {}
Maybe if I break down what is happening into more readable code, you can see what is happening.
someMethod is a method that take a function as an argument. This is more easily seen when broken down like below.
It's up to someMethod to determine what they do with that function. In this example, I am executing the function being passed into someMethod and passing it my this context.
var apple = {
name: 'Apple',
someMethod: function(func) {
return func(this);
}
};
function getName (b) {
return b.name;
};
const name = apple.someMethod(getName); // Apple
To your question: b is defined as the first argument to your anonymous function. This is more clearly expressed when the code is broken out above. But you could also express it like this:
const name = apple.someMethod(function(x) { return x.name; }); // Apple
or like this using ES6:
const name = apple.someMethod(x => x.name); // Apple
Please look at the code below and explain: what am I doing wrong?
function doStuff(a, b){
return a + b + 1 ;
}
var myContext = {
c: 1,
d: 3
};
// myContext = this (result => 5)
doStuff.call(myContext,myContext.c,myContext.d)
// ... so why doesn't the below work? (result => NaN)
doStuff.call(myContext,this.c,this.d)
// To make the above work, i must replace "this" with "myContext" (result => 5)...
doStuff.call(myContext,myContext.c,myContext.d)
// ...which is no different to...
doStuff(myContext.c,myContext.d)
// ...so what was the point of call() method?
Am I being thick?
The main point of call is to set the value of this within the function. Since your doStuff doesn't use this within the function, using call with it is pointless.
Here's an example where it matters:
function doStuff(a, b) {
return this.sum(a, b);
}
var obj = {
sum: function(a, b) {
return a + b;
}
};
console.log(doStuff.call(obj, 3, 4)); // 7, because `obj` has a `sum` property
console.log(doStuff(3, 4)); // Fails with an error that `this.sum` is not a function
so why doesn't the below work? (result => NaN)
doStuff.call(myContext,this.c,this.d)
Because this.c is evaluated before the call to doStuff, using whatever the current this value is. How you're probably calling that code, this is (in loose mode) the global object (the window object, on browsers), which probably doesn't have a c or d property. (In strict mode, again making assumptions about how you're calling that, you'd get an exception, because this is undefined and you can't retrieve properties from undefined.)
.call and .apply are Function methods that 'manipulate' what this means inside a function.
doStuff.call(myContext, myContext.c, myContext.d):
here you've set myContext as context for doStuff function
and you may refer to it inside by using this,
and you've passed two arguments to it: myContext.c, myContext.d,
it works as you've intended...
doStuff.call(myContext, this.c, this.d):
again myContext is context for doStuff()
but you've passed .c and .d properties of what this points to
in context in which it appears (global object, window) in your case.
So doStuff's context is myContext, and parameters are 2 undefineds,
because this === window in context where you are calling the function,
and you are passing .c and .d properties of global into the function.
you are actually getting this: return undefined + undefined + 1; (NaN)
if you redefine 'doStuff' like this:
function doStuff () {
return this.a + this.b + 1;
// here it looks whatever this is set to
// by `.call()` or `.apply()` methods
}
and call it like this:
var sum = doStuff.call(myContext);
// notice that using `.call` here
// means that 'myContext' is manualy set
// as `this` value inside the function above
// and is refered to by dynamic variable 'this'
I try to sort my thoughts about how javascript's bind() works.
I see that if I do
var f = function (a) { ... }
var g = f.bind(obj);
g(1)
then f is called with obj as this and 1 as a.
What I thought is g is a wrapper function around f.
But when I do
var f = function (a) { ... }
var g = f.bind(obj);
g.call(1)
then f is called with 1 as this and a undefined.
So it seems g is not just a simple wrapper, but call somehow differentiates between normal and bound functions.
One more thing is I cannot partially apply a function more times.
var f = function (a) { ... }
var g = f.bind(obj);
var h = g.bind(1);
h();
Then f is called with obj as this and a undefined.
What is the cause of this behavior?
Edit
The constructs in this question are actually wrong, see the accepted answer on what they should look like (in general I haven't noticed that call and bind do always need the context argument as the first argument).
Once you bound an object to a function with bind, you cannot override it. It's clearly written in the specs, as you can see in MDN documentation:
"The bind() function creates a new function (a bound function) with the same function body (internal call property in ECMAScript 5 terms) as the function it is being called on (the bound function's target function) with the this value bound to the first argument of bind(), which cannot be overridden."
That means, also if you do:
g.call(1);
You will get obj as this, and not 1 – on the browsers that follows the specs.
You can of course binds multiple arguments, so:
var sum = function(a, b, c) { return a + b + c };
var sumAB = sum.bind(null, 1, 5);
var sumC = sumAB.bind(null, 2);
console.log(sumC());
But the context object will be always the one specified with the first bind, because it cannot be overwritten.
Just to avoid confusion, the first argument of call is the context object (this), then you will have the rest of the argument.
It means:
var obj = { foo: function(bar) { console.log(bar) } };
obj.foo('hello');
// equivalent to:
var foo = obj.foo;
foo.call(obj, 'hello');
Hope it helps.
You never passed any arguments — you only ever set context. call's first argument is received as context (this), and arguments 2 onwards are received as the called function's arguments 1 and onwards. Meanwhile, bind creates a new function with a new context — arguments are passed when it's invoked.
Here are ways of passing 1 as function f's argument a following on from your first code block:
f( 1 );
g( 1 );
g.call( this, 1 );
g.apply( this, [ 1 ] );
Function.prototype.call()
With the call() method, you can write a method that can be used on different objects. In other words with call(), an object can use a method belonging to another object. More information
const person = {
fullName: function() {
return this.firstName + " " + this.lastName;
}
}
const person1 = {
firstName:"John",
lastName: "Doe"
}
const person2 = {
firstName:"Mary",
lastName: "Doe"
}
// This will return "John Doe":
console.log(person.fullName.call(person1));
The call() allows for a function/method belonging to one object to be assigned and called for a different object.
call() provides a new value of this to the function/method. With call(), you can write a method once and then inherit it in another object, without having to rewrite the method for the new object.
> Using call to chain constructors for an object
You can use call to chain constructors for an object (similar to Java).
In the following example, the constructor for the Product object is defined with two parameters: name and price.
Two other functions, Food and Toy, invoke Product, passing this, name, and price. Product initializes the properties name and price, both specialized functions define the category.
function Product(name, price) {
this.name = name;
this.price = price;
}
function Food(name, price) {
Product.call(this, name, price);
this.category = 'food';
}
function Toy(name, price) {
Product.call(this, name, price);
this.category = 'toy';
}
const cheese = new Food('feta', 5);
const fun = new Toy('robot', 40);
console.log(cheese);
console.log(fun);
> Using call to invoke an anonymous function
In this example, we create an anonymous function and use call to invoke it on every object in an array.
The main purpose of the anonymous function here is to add a print function to every object, which is able to print the correct index of the object in the array.
const animals = [
{ species: 'Lion', name: 'King' },
{ species: 'Whale', name: 'Fail' }
];
for (let i = 0; i < animals.length; i++) {
(function(i) {
this.print = function() {
console.log('#' + i + ' ' + this.species
+ ': ' + this.name);
}
this.print();
}).call(animals[i], i);
}
> Using call to invoke a function and specifying the context for 'this'
In the example below, when we call greet, the value of this will be bound to object obj.
function greet() {
const reply = [this.animal, 'typically sleep between', this.sleepDuration].join(' ');
console.log(reply);
}
const obj = {
animal: 'cats', sleepDuration: '12 and 16 hours'
};
greet.call(obj); // cats typically sleep between 12 and 16 hours
> Using call to invoke a function and without specifying the first argument
In the example below, we invoke the display function without passing the first argument. If the first argument is not passed, the value of this is bound to the global object.
var sData = 'Wisen';
function display() {
console.log('sData value is %s ', this.sData);
}
display.call(); // sData value is Wisen
Note: In strict mode, the value of this will be undefined. See below.
'use strict';
var sData = 'Wisen';
function display() {
console.log('sData value is %s ', this.sData);
}
display.call(); // Cannot read the property of 'sData' of undefined
For more read you can visit reference
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.
const module = {
x: 42,
getX: function() {
return this.x;
}
};
const unboundGetX = module.getX;
console.log(unboundGetX()); // The function gets invoked at the global scope
// expected output: undefined
const boundGetX = unboundGetX.bind(module);
console.log(boundGetX());
// expected output: 42
> Creating a bound function
The simplest use of bind() is to make a function that, no matter how it is called, is called with a particular this value.
A common mistake for new JavaScript programmers is to extract a method from an object, then to later call that function and expect it to use the original object as its this (e.g., by using the method in callback-based code).
Without special care, however, the original object is usually lost. Creating a bound function from the function, using the original object, neatly solves this problem:
this.x = 9; // 'this' refers to global 'window' object here in a browser
const module = {
x: 81,
getX: function() { return this.x; }
};
module.getX();
// returns 81
const retrieveX = module.getX;
retrieveX();
// returns 9; the function gets invoked at the global scope
// Create a new function with 'this' bound to module
// New programmers might confuse the
// global variable 'x' with module's property 'x'
const boundGetX = retrieveX.bind(module);
console.log(boundGetX());
// returns 81
> Partially applied functions
The next simplest use of bind() is to make a function with pre-specified initial arguments.
These arguments (if any) follow the provided this value and are then inserted at the start of the arguments passed to the target function, followed by whatever arguments are passed to the bound function at the time it is called.
function list() {
return Array.prototype.slice.call(arguments);
}
function addArguments(arg1, arg2) {
return arg1 + arg2;
}
const list1 = list(1, 2, 3);
// [1, 2, 3]
const result1 = addArguments(1, 2);
// 3
// Create a function with a preset leading argument
const leadingThirtysevenList = list.bind(null, 37);
// Create a function with a preset first argument.
const addThirtySeven = addArguments.bind(null, 37);
const list2 = leadingThirtysevenList();
// [37]
const list3 = leadingThirtysevenList(1, 2, 3);
// [37, 1, 2, 3]
const result2 = addThirtySeven(5);
// 37 + 5 = 42
const result3 = addThirtySeven(5, 10);
// 37 + 5 = 42
// (the second argument is ignored)
> With setTimeout()
By default within setTimeout(), the this keyword will be set to the window (or global) object. When working with class methods that require this to refer to class instances, you may explicitly bind this to the callback function, in order to maintain the instance.
function LateBloomer() {
this.petalCount = Math.floor(Math.random() * 12) + 1;
}
// Declare bloom after a delay of 1 second
LateBloomer.prototype.bloom = function() {
window.setTimeout(this.declare.bind(this), 1000);
};
LateBloomer.prototype.declare = function() {
console.log(`I am a beautiful flower with ${this.petalCount} petals!`);
};
const flower = new LateBloomer();
flower.bloom();
// after 1 second, calls 'flower.declare()'
And if you want to know more about bind method, read this resource
Suppose I have JavaScript code like
myClass = function(){
function doSomething(){
alert(this); // this1
}
}
alert(this); //this2
What those two 'this' objects are refer for??
The this value in the global execution context, refers to the global object, e.g.:
this === window; // true
For Function Code, it really depends on how do you invoke the function, for example, the this value is implicitly set when:
Calling a function with no base object reference:
myFunc();
The this value will also refer to the global object.
Calling a function bound as a property of an object:
obj.method();
The this value will refer to obj.
Using the new operator:
new MyFunc();
The this value will refer to a newly created object that inherits from MyFunc.prototype.
Also, you can set explicitly that value when you invoke a function, using either the call or apply methods, for example:
function test(arg) {
alert(this + arg);
}
test.call("Hello", " world!"); // will alert "Hello World!"
The difference between call and apply is that with apply, you can pass correctly any number of arguments, using an Array or an arguments object, e.g.:
function sum() {
var result = 0;
for (var i = 0; i < arguments.length; i++) {
result += arguments[i];
}
return result;
}
var args = [1,2,3,4];
sum.apply(null, args); // 10
// equivalent to call
sum(1,2,3,4); // 10
If the first argument value of call or apply is null or undefined, the this value will refer to the global object.
(note that this will change in the future, with ECMAScript 5, where call and apply pass the thisArg value without modification)
I understand calling function(1) but not function(1)(2), how does it work?
also possible for function(1)(2)(3)(4) too?
In this case you are supposing that function(1) returns a function, than you are calling this new, anonymous function with an argument of 2.
See this example:
function sum(a) {
return function(b) {
return a+b;
}
}
// Usage:
window.alert(sum(5)(3)); // shows 8
var add2 = sum(2);
window.alert(add2(5)); // shows 7
window.alert(typeof(add2)); // shows 'function'
Here we create a function sum that takes one argument. Inside the function sum, we create an anonymous function that takes another argument. This anonymous function is returned as the result of executing sum.
Note that this anonymous function is a great example of what we call closure. A closure is a function that keeps the context in which it was created. In this case, it will keep the value of the variable a inside it, as did the example function add2. If we create many closures, they are independent as you can see:
var add3 = sum(3);
var add4 = sum(4);
window.alert(add3(3)); // shows 6
window.alert(add4(3)); // shows 7
Furthermore, they won't get "confused" if you have similarly named local variables:
var a = "Hello, world";
function multiply(a) {
return function(b) {
return a * b;
}
}
window.alert(multiply(6)(7)); // shows 42
var twoTimes = multiply(2);
window.alert(typeof(twoTimes));
window.alert(twoTimes(5));
So, after a call to sum(2) or multiply(2) the result is not a number, nor a string, but is a function. This is a characteristic of functional languages -- languages in which functions can be passed as parameters and returned as results of other functions.
You have a function that returns a function:
function f(n) {
return function(x) {
return n + x;
};
}
When you call f(1) you get a reference to a function back. You can either store the reference in a variable and call it:
var fx = f(1);
var result = fx(2);
Or you can call it directly:
var result = f(1)(2);
To get a function that returns a function that returns a function that returns a function, you just have to repeat the process:
function f(n) {
return function(x) {
return function(y) {
return function(z) {
return n + x + y + z;
}
}
};
}
If your function returns a function, you can call that too.
x = f(1)(2)
is equivalent to:
f2 = f(1)
x = f2(2)
The parenthesis indicate invocation of a function (you "call" it). If you have
<anything>()
It means that the value of anything is a callable value. Imagine the following function:
function add(n1) {
return function add_second(n2) {
return n1+n2
}
}
You can then invoke it as add(1)(2) which would equal 3. You can naturally extend this as much as you want.