This question already has answers here:
Javascript: Do I need to put this.var for every variable in an object?
(6 answers)
Closed 6 months ago.
I have this snippet of code. I am very new to JavaScript, and I have an error in:
class X {
constructor() {
this.pick = -1;
this.isClosed = false;
this.pline = [];
}
add(mx, my) {
pline.push(Point(mx,my));
}
draw() {
beginShape();
for (let i = 0; i < pline.length; i++) {
p = pline[i];
vertex( p.x, p.y );
}
... //ignore the rest for now
the issue I am getting is: X, line 14:ReferenceError: Can't find variable: pline
I am a little confused because I am initializing it as a class property, so I am not sure why it cannot be found in the draw function. Any help is highly appreciated.
This is because you have scoped pline to this, so it must be this.pline.push.
Also, if you want to use this scope, it's best to use arrow function methods to maintain the scope. Example:
class clazz{
constructor() {
this.something = 1;
}
add = () => {
console.log(this.something);
};
}
pline refers to a variable (either local or global), not a property. If you want to access a property, then you must use this.pline. Although variables and properties seem the same, under the hood they are fairly different because of how JavaScript classes work (which is quite different from most languages).
in your add() function you are referring to "pline.push()", you need to use this.pline.push()
Related
I think the question title sums it up pretty well, if not, let me explain:
I have a class, that one has a function and inside that function A I NEED to have another function (function B), which needs to access a variable of function A. I hope this is enough, I really can not find any better words of how to describe this issue.
I think you need arrow functions for that
class Some() {
constructor() {
/* ... */
}
A(params) {
let localVariable = 1
const B = () => {
// here you can access to the context (this)
// and to A local variables (params, localVariable )
}
}
}
If i understood you correctly. And please ask more specific questions next time. Also try to share your code. It would be easier to understand
This sounds like a design problem. It sounds like you're attempting to break variable scoping rules. It seems to me, that this is what you're trying to do:
class some_class {
A_function() {
let variable1 = 5;
}
B_function() {
let variable1 = 10;
}
}
'variable1' is defined in A_function and is not accessible to B_function because of scoping rules. In fact, the variable1 in A_function and the variable1 in B_function are different variables.
However, a better implementation, that would likely work as you intend would be more like this:
class some_class {
constructor() {
this.variable1 = 5;
}
A_function() {
this.variable1 = 10;
}
B_function() {
this.variable1 = 15;
}
}
Now, this.variable1 is defined as a property of the class and is accessible to both functions. Either function can modify the value of the variable.
Is this what you have in mind?
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 4 years ago.
I have this method of a JavaScript class that I've created:
resetRule() {
let sheetRules = Array.from(this.sheet.rules);
sheetRules.forEach(function(node, i) {
if(node.name != undefined) {
newRule.sheet.deleteRule(i);
}
});
}
when you instantiate a class, it essentially has to be set to a variable, like so:
const newRule = new NewRule(*params*);
and the methods/properties of said class can refer to the class object using this. like so:
this.method();
this.property;
What I'd like to know is: how does one refer back to the variable that instantiated the class within a function that is called by a method of said class?
To be even clearer: a function that is called within a method of a class alters the scope, which also means it alters the definition of this.. My question is: how do you get around this? How could you access the variable that instantiated the class when you are out the of scope of the methods within said class?
As I was composing this question, I realized that you can set the this value for a .forEach loop like this:
resetRule() {
let sheetRules = Array.from(this.sheet.rules);
sheetRules.forEach(function(node, i) {
if(node.name != undefined) {
this.sheet.deleteRule(i);
}
}, this);
}
However, the way this code works is something that--as far as I know--is just a benefit of the .forEach method, and I'd still like to know how it should be handled in general.
Hopefully this should help you out, using your example.
class Rule {
constructor(rules) {
this.sheet = {
rules: rules || []
}
}
log(){
console.log('rules:',this.sheet.rules)
}
resetRule() {
let sheetRules = Array.from(this.sheet.rules);
let self = this; // <-- here you can capture the instance
sheetRules.forEach(function(node, i) {
self.log() // <-- here you can use it in forEach
if (node.name != undefined)
this.sheet.deleteRule(i);
});
}
}
const fooRule = new Rule(['foo'])
const barRule = new Rule(['bar'])
fooRule.resetRule()
barRule.resetRule()
fooRule.log()
barRule.log()
Your forEach works because as you discovered, you passed this as an argument for the thisArg parameter. However, if you didn't, you could have just as easily set it to a variable in the outer scope and used it in the block scope.
Generally creating a variable called self or that and setting it to this is helpful, especially for arrow functions, which set this to the encapsulating scope and not the instance object.
You could make a temporary variable called self or something which would allow you to use both the object containing "this" instance as well as within that anonymous function passed to forEach, this which will refer to sheetRules when you don't specify another variable to use as this
resetRule() {
let sheetRules = Array.from(this.sheet.rules);
let self = this;
sheetRules.forEach(function(node, i) {
if(node.name != undefined) {
self.sheet.deleteRule(i);
}
});
}
If I've not misunderstood you're looking for a way to retain your scope? You have a few options here.
The immediate answers would be to use Function.prototype.bind() or Function.prototype.call() to specify the context of this when invoking those methods.
Alternatively you could just make the scope of your this available where needed:
var MyClass = function () {
// Here we bind the local scope to a variable that will give us context where necessary.
// While it's not needed here, it can give context and set a pattern of reability through repitition.
var vm = this;
vm.methodA = function () {
// We continue to set our 'vm' pointer variable when needed.
var vm = this;
globalMethod.then(function () {
// We're able to retain context of our `this` through having scope of our 'vm' variable.
vm.methodB();
});
};
vm.methodB = function () {
console.log('I did stuff!');
};
};
This question already has answers here:
How to use arrow functions (public class fields) as class methods?
(4 answers)
Closed 8 months ago.
When i change a function draw(){ //} to draw = () => { // }
I am getting an error like "Uncaught SyntaxError: Unexpected token =".
What may be the reason?
First of all, you probably shouldn't do that. Why? Well, because arrow functions are not semantically the same as regular functions.
If you register the functions as this.draw = () => {//}, then every instance of your class* will have a duplicate definition of that function which is a waste of space and a misuse of some core language features such as prototype inheritance.
draw() on the other hand registers that function on the prototype so that definition of the draw function can be shared between all instances and even changed dynamically for ALL instances at the same time.
In your constructor you can have this.draw = () => {//} but there isn't really much point in doing this. draw(){//} should be fine for anything you want.
Below, in my example, I've shown both use cases as you can see nothing is saved by using an arrow function.
class StandardFunction {
draw() {
console.log('StandardFunction: you called draw')
}
}
class ArrowFunction {
constructor() {
this.draw = () => {
console.log('ArrowFunction: you called draw')
}
}
}
const test1 = new StandardFunction();
const test2 = new ArrowFunction();
test1.draw();
test2.draw();
I hope you find this helpful
You will need to use babel's Class properties transform, which will transpile:
class Picture {
draw = () => {
console.log('drawing')
}
}
into:
class Picture {
constructor() {
this.draw = () => {
console.log('drawing');
};
}
}
You can try it in this repl (make sure to enable the class properties transform plugin)
This question already has answers here:
What does 'var that = this;' mean in JavaScript?
(6 answers)
Closed 8 years ago.
I'd like to know and understand the different between this and that, and when I have to use it.
I ready many post and many tutorial but I don't understand yet
this is my class
function Container(param) {
function dec() {
if (secret > 0) {
secret -= 1;
return true;
} else {
return false;
}
}
this.member = param;
var secret = 3;
var that = this;
this.service = function () {
console.log(this.member); // foo
console.log(that.member); // foo
return dec() ? that.member : null;
};
}
New
var myContainer = new Container('foo');
myContainer.service()
Calling myContainer.service() will return 'abc' the first three times it is called.
After that, it will return null
Why i have to do var that = this ??
this is a variable that gets the context of the current function (which depends on how it was called).
that has no special meaning. It is just a variable to which a value has been assigned.
In this particular case, that is assigned the value that this has while the Container is running, and is used inside the service function (but still has the value that is the context of the call to Container. Since service is a different function, its value of this could be different.
Normally, for this particular design of function, Container would be called as a constructor function (so this would be the instance object of Container) and then service would be called in the context of that instance object so you could use this instead of passing the value around via that. I have no idea why the author of that code chose to use that here.
This question already has answers here:
Use of 'prototype' vs. 'this' in JavaScript?
(15 answers)
Closed 9 years ago.
So, I am not a JavaScript expert, just trying to understand what the difference is between two following snippets of code. I have a project that I want to convert to TypeScript and I need to understand the difference between two code snippets being generated.
var Pony = (function () {
function Pony() { }
Pony.prototype.bite = function () {
alert("Chomp!");
};
return Pony;
})();
var Pony2 = (function () {
function Pony2() {
var self = this;
self.bite = function () {
alert("Chomp!");
};
}
return Pony2;
})();
The difference between the two is that you can get to the prototype of the first Pony via attributes on the object stored in var Pony and could expand upon or use the associated bits of that prototype elsewhere where as Pony2 would just be considered a function. So if you do not plan on using any sort of prototypical inheritance later on they are equivalent.
The answers above give a good overview on the difference between putting on the prototype and putting on the instance. As to your question about converting to TypeScript, below is how you would write them both:
class Pony {
bite(){
alert('chomp');
}
}
class Pony2 {
bite: () => void;
constructor(){
this.bite = () => alert('chomp');
}
}
As far as how you use them, there's no difference. However, from a performance standpoint the former method would be preferable. Let's extend your example a little bit:
var prototypePony1 = new Pony();
var prototypePony2 = new Pony();
var thisPony1 = new Pony2();
var thisPony2 = new Pony2();
prototypePony1.hasOwnProperty('bite'); //returns false
prototypePony2.hasOwnProperty('bite'); //returns false
thisPony1.hasOwnProperty('bite'); //returns true
thisPony2.hasOwnProperty('bite'); //returns true
Pony.prototype.bite = function() { alert('Nomnomnom!'); };
Pony2.prototype.bite = function() { alert('Nomnomnom!'); };
prototypePony1.bite(); //alerts 'Nomnomnom!'
prototypePony2.bite(); //alerts 'Nomnomnom!'
thisPony1.bite(); //alerts 'Chomp!', instance property is accessed first
delete thisPony2.bite;
thisPony2.hasOwnProperty('bite'); //returns false
thisPony2.bite(); //alerts 'Nomnomnom!'
In the example above, thisPony1 and thisPony2 both get their own copy of the bite function, since it was defined using this However, prototypePony1 and prototypePony2 both share the same copy of bite from Pony's constructor.
Once we define the bite prototype on Pony2, the instance property is still accessed first on thisPony1. It's not until we delete the instance property that we see the newly defined prototype property on thisPony2.
For more detailed info on defining object methods, have a look here.