-
• #2
The intended use is:
// class def function TestBind(x) { this.x = x; } TestBind.prototype.getX = function() { console.log('TestBind.getX(): returning ' + this.x); return this.x; } // usage to create an object instance bound method as function var tb = new TestBind(42); var gX = tb.getX; var bgX = gX.bind(tb); // var bgX = tb.getX.bind(tb);
...use of the bound method can now be used as plain function in all places where only a function can be passed:
- setInterval()
- setTimeout()
- callback
in a simplified and fast form:
setInterval(bgX,1500);
in replacement of anonymous function:
setInterval(function(){ tb.gX(); },1500);
Bind is nothing else than the above, just a bit faster, smarter, and leaner (less resources).
Often, you will see the pattern of a
var _this = this;
orvar _ = this;
in a method to refere to the current object and then the use of if in a 'closures'. Becausethis
is runtime executed in the context at that very (future) moment,this
as on setup is then not available anymore (or different), and with above approach one makes clear that it mans the current instance. For example with the your example above:TestBind.prototype.getX = function() { var _this = this; setTimeout(function(){ console.log('.getX(): for TestBind with x=' + _this.x + ' was accessed 10 seconds ago'); },10000); return this.x; }
There was a time that this was the only way to be done. But a while now, setTimeout() (and setInterval() ?) allow passing of arguments that are resolved at setup of setTimeout() (and setInterval()?):
TestBind.prototype.getX = function() { setTimeout(function(){ console.log('.getX(value): for TestBind with x=' + value + ' was accessed 10 seconds ago'); },10000,this.x); return this.x; }
Imagine a second method
TestBind.prototype.doY = function() { setTimeout(this.gX.bind(this),5000); console.log("...just did Y."); }
that will do something in a timeout or interval involving the
.getX()
, then you can do that with a an anonymous function and 'helper' variable_this
or with bind... bind... both work. I do not know the runtime differences and ramification for JS in Espruino vs others...var firstTB = new firstTB(1);
var secondTB = new firstTB(2);
firstTB.doY();
secondTB.doY();Take also a look at ```apply(...)``` and ```call(...)```. There are more applications to have a 'function' (or piece / block of - instant - code) as object that is passed around and then then executed. The unbound (undefined object context) or bound (to an object) function is passed around as a reference, and for execution use the regular function argument list parentheses, which is understood as: try to invoke ***the given thing*** as a function an passing the the arguments (if there are). You do that all the time with JS programming. The short form of defining functions obfuscates this a bit, but if you use the *long way with a variable* it becomes obvious... and shows the great Lambda that came to be in the 70'... only Java missed it for so long until recently... so much for progress an new things under the SUN. Here some fun to play Math Jeopardy with:
var f = function(a) { return a * a; }; // square
var g = function(a) { return a * a * a; }; // cubicfunction j = function(f,x) { // accepts function and a value as args
console.log("J: fnct(x) with x = " + x + " returns " + f(x) + ". What is fnct(x) do with x?");
}
setTimeout(function() {
j( (Math.random()<0.5) ? f : g, (new Date()).getSeconds() % 6) );
});;-) I added the JS modulo or modulus % with 10 so the numbers stay within 0..9 (or % 6 for 0..5) for players -like me when it it's late - used to pocket calculator or phone only and not anymore to learn square up to 59 and all the tricks that go with it like: 25 square is 2*(2+1) and appended 25... goes for a the one with 5 at the end... 125 square is 12*13 + "25"... Espruino will tell you in the console in an instant... this is for square... so for cubic I should simplify even more... also for me... (it's already late).
- setInterval()
-
• #3
I think as usual @allObjects has done an awesome job of answering the question about
bind
.But looking at the code above, there are a few big issues that I thought it might help if I point out in-line:
class TestBind { constructor() { var vX = 23; // This creates a LOCAL VARIABLE - you need this.vX=23; } getX() { return this.vX; } setX( obj ) { this.vX = obj; } } exports = TestBind; // not really useful in this case as you're using using 'TestBind' directly var tb = new TestBind(); var g = tb.getX; // This makes 'g' equal to the function 'getX' itself // Check out https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get for a real example of getters print g // this is not how you call a function in JS. It won't print anything at all. You need print(g) var tb = new TestBind(); tb.setX = 42; // This just overwrites the 'setX' function with the number 42 // Check out https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set for a real example of setters var g = tb.getX(); // this works, there is no 'Function "getX" not found!' error so I can only assume you're not uploading the code that you posted
I'm not sure any of these problems you're having would be fixed by how you use
bind
though.I think what you intended to do was probably:
class TestBind { constructor() { this.vX = 23; } getX() { return this.vX; } setX( obj ) { this.vX = obj; } } var tb = new TestBind(); print(tb.getX()); // prints 23 var g = tb.getX(); print(g); // prints 23 tb.setX(42); print(tb.getX()); // prints 42
-
• #4
Tue 2018.09.18
Thanks both for the quick and attentive responses.
I thought I'd found the culprit. I mistakenly used
tb.setX = 42;
when as @Gordon pointed out should usetb.setX(42);
Note line #6 that shows the class contents aren't getting updated
But when I run that
tb.setX(42);
, I'm faced with yet another error:>var tb = new TestBind(); =TestBind: { "vX": 25 } =25 >tb.setX = 42; =42 >print tb.getX(); =25 >var bg = g.bind(tb); Uncaught Error: Function "bind" not found! at line 1 col 12 var bg = g.bind(tb); ^ >print bg =undefined >tb.setX(42); Uncaught Error: Expecting a function to call, got Number at line 1 col 4 tb.setX(42); ^ >
This is why I originally used the syntax
tb.setX = 42;
to avoid the 'Expecting a function to call' error -
• #5
...it looks like hat you have some left-overs in your Espruino...
g is nowhere defined in that snipped, so I expect it came from previous post... but it also could come from some internal that the interpreter looks at, does not find it a bindable, but thinks it is a number.
Doing things in the console without wiping every thing out, creates a lot of confusion.
Again, I feel that Espruino is still playing tricks on you, @Robin... Espruino is a living object,... similar to the DOM of or in a Browser. Most operation on it leave some (big Bear claw) prints behind... to haunt later... Halloween is about to come... So we should get some Espruino driven flashy wearables... what about a contest, @Gordon?
-
• #6
could be a nice idea - I'll have a think! I've been meaning to try some contests - for example I reckon now tweets are 280 chars you could do some really interesting things in hardware JS :)
@Robin as @allObjects says, each command you write on the left-hand side after you upload is changing the state of the interpreter. If you thought that each command you typed was executed on a fresh instance of your code it could actually be a really big cause of the problems you're having.
Please check out some of the comments below - they might help.
>var tb = new TestBind(); =TestBind: { "vX": 25 } <---- was there a command missing here? =25 >tb.setX = 42; <---- after this, tb.setX is now set to 42. It's no longer a function =42 >print tb.getX(); <---- again, this is NOT how you use print or call a function in JS. if you want the console to say '=value' just type 'tb.getX()' - you don't need 'print' =25 >var bg = g.bind(tb); <---- as allObjects says - there must be some code here you're not posting up as you didn't define 'g' previously, but lets assume that code was 'g = tb.getX()'. 'g' will be 25, so is a number and won't have a 'bind' method Uncaught Error: Function "bind" not found! at line 1 col 12 var bg = g.bind(tb); ^ >print bg <---- not how you call print, as mentioned above. However the code above errored so you wouldn't expect it to have written anything to 'bg' =undefined >tb.setX(42); <---- If you did this right at the start, it would have worked. Since you called it after 'tb.setX = 42', 'tb.setX' is now 42 so it is not a function you can call Uncaught Error: Expecting a function to call, got Number at line 1 col 4 tb.setX(42); ^
Mon 2018.09.17
Goal:
1) Retrieve the internal contents of an instantiated class
2) Modify the internal value and retain through subsequent retrieval attempts
The MDN example works using the Json object notation form. When I attempt to use a class however, I'm greeted with either function not found or undefined
The constructor seems to ignore the initial default assignment - why not -1
Then if I use a setter, then it's not clear if the constructor initialized correctly
If I use the () notation - so which is correct, without the () or using the () ?
How can function getX() not be found when it is clearly defined?
Following the example from MDN, and applying to this class
VERSION 1v99
1 Attachment