Is there any meaningful difference bind() vs arrow function + call()?
let a = function(){};
let b = function(){};
a.m = 1
b.m = 2
a.someMethod = function(x, y, z){ return this.m + x + y + z }
let x = a.someMethod.bind(b, 1, 2, 3);
let y = () => a.someMethod.call(b, 1, 2, 3)
console.log( x(1,2,3) )
console.log( y(1,2,3) )
function goBind() {
for (var i = 0; i < 1000000; i++) {
x(1,2,3)
}
}
function goArrow() {
for (var i = 0; i < 1000000; i++) {
y(1,2,3)
}
}
function race() {
var start = performance.now();
goBind();
console.log('bind: ' + (performance.now() - start));
start = performance.now();
goArrow()
console.log('arrow: ' + (performance.now() - start));
start = performance.now();
goBind();
console.log('bind: ' + (performance.now() - start));
start = performance.now();
goArrow()
console.log('arrow: ' + (performance.now() - start));
console.log('------');
}
<button onclick="race()">RACE!</button>
How does ecmascript-6 Function.prototype.bind() handle a class constructor?
This doesn't have anything to do with classes specifically but with how .bind
works.
You have been on the right track. The most relevan section here is 9.4.1.2.
Just as a recap: ECMAScript distinguishes between two types of functions: callable functions and constructable functions. Function expressions/declarations are both, whereas e.g. class
constructors are only constructable and arrow functions are only callable.
In the specification this is represented by function's internal [[Call]]
and [[Construct]]
methods.
new
will trigger the invocation of the internal [[Construct]]
method.
.bind
will return a new function object with different implementations for [[Call]]
and [[Construct]]
. So what does the "bound" version of [[Construct]]
look like?
9.4.1.2 [[Construct]] ( argumentsList, newTarget )
When the [[Construct]] internal method of a bound function exotic object, F that was created using the bind function is called with a list of arguments argumentsList and newTarget, the following steps are taken:
- Let target be F.[[BoundTargetFunction]].
- Assert: IsConstructor(target) is true.
- Let boundArgs be F.[[BoundArguments]].
- Let args be a new list containing the same values as the list boundArgs in the same order followed by the same values as the list argumentsList in the same order.
- If SameValue(F, newTarget) is true, set newTarget to target.
- Return ? Construct(target, args, newTarget).
What this means is that the bound constructor will "construct" the original function (F.[[BoundTargetFunction]]
) with the bound arguments (F.[[BoundArguments]]
) and the passed in arguments (argumentsList
), but it completely ignores the bound this
value (which would be F.[[BoundThis]]
).
but are there other sorts of functions that are being fed something else than the value passed to bind() ?
Yes, arrow functions. Arrow functions do not have their own this
binding (the value from the closest this
providing environment is used instead), so bound arrow functions also ignore the bound this
value.
ES6 Arrow functions vs ES5: how to know which function to bind `this` to when using ES5 non-arrow function
Why do you use
bind(this)
with the callback tosetTimeout
rather than with the counter function?
Because the counter
function (which works like a method of the obj
object) already has the proper this
because you call it like obj.counter()
so it gets this
from calling it as obj.counter()
. Assuming you call counter as obj.counter()
, then if you do console.log(this.id)
on the first line of the counter()
function, it will properly show the id
value.
The callback you pass to setTimeout()
however has no natural this
value unless you use an arrow function or .bind()
on the callback function itself because when setTimeout()
calls your callback it does not set a specific this
value (it just calls your callback as a normal function), therefore the this
value goes to the default. That means this
will be undefined
if running strict mode or the global object if running in loosey-goosey mode inside of the setTimeout()
callback.
See the 6 ways that the value of this
is set here when calling a function.
I should also mention that if you did what you were proposing like this:
var obj = {
id: 42,
counter: function counter() {
setTimeout(function() {
console.log(this.id);
}, 1000);
}.bind(this);
};
Not only would it not help the setTimeout()
callback at all, but it would also bind the wrong value of this
to the counter()
method. You would get whatever this
was before the var obj
definition (also known as the lexical value of this
).
What is the difference between () = {} and function() {} in react-native javascript?
The () => {}
is called an arrow function. They are, as you said, part of ES6. From the linked page:
An arrow function expression has a shorter syntax compared to function expressions and lexically binds the
this
value (does not bind its ownthis
,arguments
,super
, ornew.target
). Arrow functions are always anonymous.
Are 'Arrow Functions' and 'Functions' equivalent / interchangeable?
tl;dr: No! Arrow functions and function declarations / expressions are not equivalent and cannot be replaced blindly.
If the function you want to replace does not use this
, arguments
and is not called with new
, then yes.
As so often: it depends. Arrow functions have different behavior than function declarations / expressions, so let's have a look at the differences first:
1. Lexical this
and arguments
Arrow functions don't have their own this
or arguments
binding. Instead, those identifiers are resolved in the lexical scope like any other variable. That means that inside an arrow function, this
and arguments
refer to the values of this
and arguments
in the environment the arrow function is defined in (i.e. "outside" the arrow function):
// Example using a function expression
function createObject() {
console.log('Inside `createObject`:', this.foo);
return {
foo: 42,
bar: function() {
console.log('Inside `bar`:', this.foo);
},
};
}
createObject.call({foo: 21}).bar(); // override `this` inside createObject
Related Topics
Rendering Raw HTML with Reactjs
Cross-Browser Method to Determine Vertical Scroll Percentage in JavaScript
Does Every JavaScript Function Have to Return a Value
How to Round Up a Number in JavaScript
Replace Multiple Strings at Once
Is There an Equivalent of the _Nosuchmethod_ Feature for Properties, or a Way to Implement It in Js
Using Queryselectorall(). Is the Result Returned by the Method Ordered
Event When User Stops Scrolling
How to Get "Get" Request Parameters in JavaScript
How to Reset (Clear) Form Through JavaScript
JavaScript Variable Definition: Commas VS. Semicolons
Is It True That Every Function in JavaScript Is a Closure
Sequelize Model Association Won't Create a New Column
Check If Element Exists in Jquery
Rerender View on Browser Resize with React
Cross-Platform, Cross-Browser Way to Play Sound from JavaScript