Cannot set property 'weather' of undefined [duplicate] - javascript

This question already has answers here:
What is the use of the JavaScript 'bind' method?
(23 answers)
Closed 3 years ago.
Putting Json data in a this.variable but I keep getting the error Uncaught (in promise) TypeError: Cannot set property 'weather' of undefined. Does anyone know how to fix this.
var currentWeather;
function setup() {
createCanvas(400, 400);
currentWeather = new CurrentWeather();
currentWeather.create();
loadJSON(currentWeather.api, currentWeather.gotData);
}
function draw() {
background(0);
}
///////////////////////////////////////////////////////////////////
class CurrentWeather{
create(){
let url = 'https://api.openweathermap.org/data/2.5/weather?q=';
let city = 'Manassas';
let apiKey ='ApiKeyHere';
let units = '&units=imperial';
this.api = url + city + apiKey + units;
this.weather;
}
gotData(data){
this.weather = data;
}
}

Try to change this line loadJSON(currentWeather.api, currentWeather.gotData); to
loadJSON(currentWeather.api, currentWeather.gotData.bind(currentWeather));
You are having scoping issues. this is being overridden/lost from your callback methods. In your case this supposed to be the instance of CurrentWeather which you have as currentWeather = new CurrentWeather();. .bind(currentWeather) is used to scope this to a specific function. Also since the currentWeather is defined globally you may need to just use that variable instead of using this in some cases. It's hard to tell where other issues are without the full code.

Related

I am not sure why am i keep getting error. history.push is not a function

var history=[];
function log(p,i,pm,y,m)
{
var details = {
amt:p,
int:i,
paym:pm,
yea:y,
mon:m
};
history.push(details); //error is here. Uncaught TypeError: history.push is not a function
var currDetails = history[history.length-1];
document.getElementById("mydiv").innerHTML += currDetails.amt;
}
I am trying push the data into history array. But, why am i keep getting error?
Basically you are accessing the global window property history and it is read only. You are getting the error because there is no push() implemented on that property. Try some other name so that it does not match with any of the global window property to get the expected behavior from the declared variable:
var historyArr=[];
function log(p,i,pm,y,m)
{
var details = {
amt:p,
int:i,
paym:pm,
yea:y,
mon:m
};
historyArr.push(details);
var currDetails = historyArr[historyArr.length-1];
console.log(currDetails)
}
log('a','b','c','d','e');
The global variable history is predefined in browsers and is read only.
var history=[]; therefore fails silently.
history.push therefore fails because history is not an array object.
Wrap your code in an IIFE so that you aren't trying to create unneeded variables in the global scope, this will mean you can create a history variable as you won't be overwriting the existing one.
var log = (function() {
var history = [];
function log(p, i, pm, y, m) {
var details = {
amt: p,
int: i,
paym: pm,
yea: y,
mon: m
};
history.push(details); //error is here. Uncaught TypeError: history.push is not a function
var currDetails = history[history.length - 1];
document.getElementById("mydiv").innerHTML += currDetails.amt;
}
return log;
})();
(This is a simplified version of the revealing module pattern.

How do you (best) access 'this' in an object method passed as callback [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 4 years ago.
I'm writing a simple word game to practice my javascript (I'm new to it) using the NPM package prompt (https://www.npmjs.com/package/prompt) to query the user when I need a response.
Since I come from an OOP background (in other languages) I've been experimenting with encapsulating different functionalities in different objects. So I have all the prompt related code in one object, like this
function Prompter() {
this.getUserName = function (callback) {
var schema = {
properties: {
name: {
description: "Tu nombre por favor:",
pattern: /^[ñÑa-zA-Z\s\-]+$/,
message: 'Solo letras, por favor',
required: true
}
}
};
prompt.get(schema, callback);
};
}
and game logic in another object like this (this is the relevant part of the code)
function Game() {
this.qGenerator = null;
this.prompter = null;
this.user = "";
this.doNextRound = function () {
//// omitted for brevity
};
this.init = function () {
this.qGenerator = new QuestionGenerator();
this.prompter = new Prompter();
};
this.startGame = function () {
this.prompter.getUserName(this.storeUserName);
};
this.storeUserName = function (err, result) {
if (err) {
this.handleErr(err);
return;
}
this.user = result.name;
this.doNextRound();
};
}
and I start the game like this
const game = new Game();
game.init();
game.startGame();
The problem I have is that in the Game method storeUserName, which I've passed as a callback to prompt, I have no access to the Game object through this, and thus, when I call
this.doNextRound
inside of storeUserNameI get
TypeError: this.doNextRound is not a function
I understand why, as this refers to Node inside the callback. But I don't know how to keep a reference to the correct this inside the method I'm passing as callback. I understand how to do it in more 'vanilla' Javascript -- using that = this, or apply,etc, but I'm not sure what the best way to handle this inside Node callbacks is when you're passing another object's methods. Any advice much appreciated.
Use Function.prototype.bind:
this.prompter.getUserName(this.storeUserName.bind(this));
or an arrow function:
this.prompter.getUserName( _ => this.storeUserName() );
Either of those will work.

How to update Array In Vue.js using method? [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 5 years ago.
I Can't Update my array using methods in Vue.js !
<script>
import Vue from 'vue';
export default {
data () {
return {
from:'',
to:'',
places:[]
}
},
methods:{
searchFrom:function(){
var autoComplete = new google.maps.places.AutocompleteService();
autoComplete.getPlacePredictions({input:this.from},function(data){
this.places=data;
});
}
},
computed:{
}
}
</script>
<style>
</style>
This throws an error on console: "Uncaught TypeError: Cannot read property 'places' of undefined"
This is because you're not using fat arrows, change the code to:
methods:{
searchFrom (){
var autoComplete = new google.maps.places.AutocompleteService();
autoComplete.getPlacePredictions({input:this.from}, data => {
this.places=data;
});
}
},
In more details:
when you call autoComplete.getPlacePredictions it uses a callback, and in that callback the this context is changed and is no longer Vue context, so it does not know what this.places is. Fat arrow (=>) takes care of it and makes sure that the context remains the same.
I've never had good luck using fat arrows in Vue. The this is not what you expect. Try explicitly assigning this at the start of your searchFrom() method, like this...
methods:{
searchFrom (){
var me = this;
var autoComplete = new google.maps.places.AutocompleteService();
autoComplete.getPlacePredictions({me.from}, data => {
me.places=data;
});
}
}

Trying to pass "this" as an argument [duplicate]

This question already has answers here:
Set "this" variable easily?
(5 answers)
Closed 6 years ago.
I am trying to find out the class of an element when hovered over, and I am getting a
TypeError: undefined is not an object (evaluating 'classString.split')
console error. Here is my code.
function findClass(){
var classString = $(this).attr('class');
var myClass = classString.split(' ')[0];
alert(myClass);
}
//blog
$(".img2.blog").mouseenter(function() {
$('.img2.blog').css('opacity', '0');
$('.img1.blog').removeClass('hidden');
findClass(this);
});
//albums
$(".img2.albums").mouseenter(function() {
$('.img2.albums').css('opacity', '0');
$('.img1.albums').removeClass('hidden');
findClass(this);
});
//videos
$(".img2.videos").mouseenter(function() {
$('.img2.videos').css('opacity', '0');
$('.img1.videos').removeClass('hidden');
findClass(this);
});
//contact
$(".img2.contact").mouseenter(function() {
$('.img2.contact').css('opacity', '0');
$('.img1.contact').removeClass('hidden');
findClass(this);
});
Not sure how to pass "this" as an argument. Any help appreciated.
You can pass this, by using the call method:
findClass.call(this);
Someone will soon say it also works with apply. They only differ in how to pass the real arguments to the function (in case that were needed).
Check out the documentation on the two.
And to add one other method of the same family, with bind you can also achieve it:
findClass.bind(this)();
You still have to let the function know what the parameter is:
function findClass(self) {
var classString = $(self).attr('class');
var myClass = classString.split(' ')[0];
alert(myClass);
}
Use call or apply function.
Here is a slightly modified example that demonstrates how you can do this:
function findClass(){
var classString = this['class'];
var myClass = classString.split(' ')[0];
alert(myClass);
}
findClass.call({'class': "Hello World"})
findClass.apply({'class': "Hello World"})

javascript - how to get object from array, and use its methods?

i have a problem using a class methods, after it was inserted into array. when i pull it back i can no longer use it methods.
and i know javascript does not have class, when i say class i mean object -or js equal.
suppose i have the following:
// a simple atomic class
function raw_msg(msg) {
this.msg = msg;
this.print = function () {
console.log(this.msg);
}
}
// and then i have this container for this "atomic" class
// which accept array of unknown object (known to me though..) = in_buffer
// i.e in_buffer is just an array of objects (one type of object)
function buffer(in_buffer) {
this.trans_buffer = null;
if (in_buffer!=null)
this.set_buffer (in_buffer);
this.set_buffer = function (buffer) {
this.trans_buffer = [];
var length = buffer.length,
row, new_raw_msg;
for(var x = 0; x < length; x++) {
row = buffer[x];
this.trans_buffer.push(new raw_msg(row));
}
console.log(this.trans_buffer);
}
this.use_some_raw_msg_method = function () {
var firstrow = this.trans_buffer[0];
firstrow.print(); // here is the problem!!!
//this here where i need help as it yield the error:
//Uncaught TypeError: Object #<Object> has no method 'print'
}
}
// this is how i use it, this code sits in a diffrent yet another class...
// this here im just building fake array
var buffer_in = [];
for (var x=0;x<10;x++)
buffer_in.push ("whatever" + x);
this.trans_buffer = new trans_helper(buffer_in);
this.trans_buffer.use_some_raw_msg_method (); // will yield the error as described
i hope this here, is clear, ask away if you need clarifications.
thanks for your help!
note to future readers - there is no problem in retrieving an object and using its methods.
You had several problems with your code.
Associative array does not have .push() method so the following line failed:
buffer_in.push ("whatever" + x);
To fix this just declare plain array:
var buffer_in = [];
You tried to create instance of function called trans_helper which does not exist. The name is buffer instead, so fix would be:
var trans_buffer = new buffer(buffer_in);
Last but not least, you tried to call function in the "class" when it still did not exist yet. JavaScript does not "compile" functions in advance, when inside function it will go line by line. So in this line in your code:
this.set_buffer (in_buffer);
There was still no function called "set_buffer" in your class. To fix this, place the function declaration above, on top.
Live test case.

Categories