I am not sure how to find the right one or to search me out of it
// Assignment 8: Fix the code
// Assignment 8: Fix the code
var Friends = (function() {
var i = 0;
function Friends() {
var ival = setInterval(function() {
console.log(this.friends[i]);
i++;
if(i === this.friends.length) {
clearInterval(ival);
}
}, 1000);
}
Friends.prototype.friends = ['Mikkel', 'Jens', 'Filip'];
return Friends;
})();
var f = new Friends();
var f2 = new Friends();
/* it should log:
Mikkel
Mikkel
Jens
Jens
Filip
Fili
/* it should log:
Mikkel
Mikkel
Jens
Jens
Filip
Fili
There are two issues with this code snippet,
Uncaught TypeError: Cannot read property '0' of undefined
context of variable "i" is same for both instance of friends.
First issue was due to the context of the variable this inside setInterval function. To access the friends inside setInterval keep the reference of this into a variable outside setInterval and access that variable inside the function. In the below code I have assigned this to a variable me, and accessed friends list using me.
Second issue is with the indexing of item using i. As we have defined it out side the function Friends, indexing will same in both initialisation. Which will result in following result:
Mikkel
Jens
Filip
undefined
undefined
undefined ....
So to make sure when ever we call new Friends() the it should start from the beginning of the friends list move the initialisation of var i = 0 inside Friends function.
Below is the updated code which will give the exact result.
var Friends = (function() {
function Friends() {
var i = 0; // Solution for second issue
var me = this; // Solution for first issue
var ival = setInterval(function() {
console.log(me.friends[i]);
i++;
if(i === me.friends.length) {
clearInterval(ival);
}
}, 1000);
}
Friends.prototype.friends = ['Mikkel', 'Jens', 'Filip'];
return Friends;
})();
var f = new Friends();
var f2 = new Friends();
Related
On load of the document, I am initiating a function calling itself. And later from the returned function, i am trying to get the output. but i am not getting. the way what i do this wrong here.
any one correct me and teach the correct way to use the self initiated functions?
here is my try :
var BankAccount = (function () {
function BankAccount() {
this.balance = 0;
}
BankAccount.prototype.deposit = function(credit) {
this.balance += credit; return this.balance;
};
return BankAccount;
})();
var myDeposit = BankAccount.deposit(50); //throws error as ankAccount.deposit is not a function
Live
You need to return instance of BankAccount:
return new BankAccount();
You need to invoke your constructor before you can call .deposit
var account = new BankAccount();
var balance = account.deposit(50);
console.log(balance); // 50
This would allow you to manage multiple accounts where each account has its own balance.
var a = new BankAccount();
a.deposit(50); // 50
var b = new BankAccount();
b.deposit(20); // 20
console.log(a.balance); // 50
console.log(b.balance); // 20
You've written a constructor function, but you haven't called it as one.
var myBankAccount = new BankAccount();
var myDeposit = myBankAccount.deposit(50);
I am trying to divide 1 by the console.count() every time it is used. However, this code does not work.
var counter = console.count();
console.log(1/counter);
Any suggestions on how I could do this? I tried doing parseInt but no luck.
Way to save console.count() as an integer?
No. console.count() does not return anything, it directly prints to the console, just like console.log().
Simple implementation of console.count:
var count = (function() {
var counter = {};
return function(v) {
return (counter[v] = (counter[v] || 0) + 1);
}
}());
console.log('foo', count('foo'));
console.log('foo', count('foo'));
console.log('bar', count('bar'));
Here is a script that intercepts messages sent to the console.
var counter = 0;
function takeOverConsole(){
var console = window.console
if (!console) return
function intercept(method){
var original = console[method]
console[method] = function(){
var message = Array.prototype.slice.apply(arguments).join(' ')
// do sneaky stuff
if (original.call){
// Do this for normal browsers
original.call(console, message)
}else{
// Do this for IE
original(message)
}
counter++;
}
}
var methods = ['log', 'warn', 'error', 'count']
for (var i = 0; i < methods.length; i++)
intercept(methods[i])
}
To take Felix King's answer a bit further. Here is a more accurate way to intercept and count anything being sent to the console.
You can customize the function a bit and add any methods you want to track and count.
All console methods
I talk about it more here
I'm learning how to actually use JavaScript. I've run into a situation where I'm getting an error. The error is: TypeError: 'undefined' is not an object (evaluating 'this.flagged'). I've narrowed down my code to where its happening. My code looks like this:
var flagged = false;
var intervals = [];
return {
flagged: flagged,
intervals: intervals,
createInterval : function (options) {
var defer = $q.defer();
if (this.throwsError) {
defer.reject('There was an error creating the interval.');
} else {
this.intervals.push(
$interval(function() {
console.log('here 1');
console.log(this.flagged);
},
1000
));
}
}
};
The error gets thrown at the: console.log(this.flagged); I'm guessing it has to do with the fact that "this" isn't visible. Yet, if "this" isn't visible, I'm not sure how to get the value for flagged. Can someone please explain to me what I need to do to get the value for flagged?
Thank you!
When you are using this inside $interval it won't be pointing to your original object, however, you can do this:
var flagged = false;
var intervals = [];
return {
flagged: flagged,
intervals: intervals,
createInterval : function (options) {
var defer = $q.defer(),
self = this;
if (this.throwsError) {
defer.reject('There was an error creating the interval.');
} else {
this.intervals.push(
$interval(function() {
console.log('here 1');
console.log(self.flagged);
},
1000
));
}
}
};
notice var self = this;
In JavaScript,
var flagged
will be a scoped variable, i think what you need here is a global scope variable for that, simply remove var from behind it.
flagged = false;
that should do the trick.
I have a function which works just fine the first if I call it just once, but when I call it repeatedly within a for loop, I get the following error:
TypeError: getNamedRange is not a function, it is string.
Doing a search on this error gives me a clue that this is a javascript error, not a Google Apps Script error. I haven't worked much with javascript, but I suspect it may have something to do with how I return the value from the function.
This is the code which calls the function:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var baseSheet = ss.getSheetByName("Base");
var catCol = 9;
var riskAreaColumn = 10;
var numRows = baseSheet.getDataRange().getNumRows();
// I am not using this var, should I be?
var data = baseSheet.getDataRange().getValues();
var cell;
var rangeName;
var range;
var rule;
for(var i=2; i<numRows; i++){
cell = baseSheet.getRange(i, riskAreaColumn);
rangeName = getNamedRange("CategoryRiskRange",baseSheet.getRange(i, catCol).getValue());
range = SpreadsheetApp.getActiveSpreadsheet().getRangeByName(rangeName);
rule = SpreadsheetApp.newDataValidation().requireValueInRange(range).build();
cell.setDataValidation(rule);
}
SpreadsheetApp.flush();
}
This is the function being called:
function getNamedRange(categoryRange, category) {
var categoryList = SpreadsheetApp.getActive().getRangeByName(categoryRange).getValues();
for (var i = 0; i < categoryList.length; i++) {
if (categoryList[i][0] == category) {
getNamedRange = categoryList[i][1];
return getNamedRange;
}
}
}
The first time through the for loop works, the second time gives me the aforementioned error. Thank you for reading this, I hope it's clear.
you are overwriting the function definition here:
getNamedRange = categoryList[i][1];
this will work:
if (categoryList[i][0] == category) {
return categoryList[i][1];
}
Javascript doesn't interpret things until it gets to them, and is very happy to redefine things when you tell it to.
The first time through, it sees
function getNamedRange(categoryRange, category)
and says "oh, a function! Cool!" But in that function, you have the line
getNamedRange = categoryList[i][1];
and it says "Oh, so getNamedRange is something else now. Okay, I'm fine with that."
Rename your variable, and you should be fine.
Ok after a day I managed to narrow down the problem to 2 lines of code. Maybe I am trying to use the this statement incorrectly.
function scheduleItemView(myId){
this.update = function(show){
document.getElementById(this.id+'-title').innerHTML = show.title +": "+ show.startDate;
document.getElementById(this.id+'-title-overlay').innerHTML = show.title +": "+ show.startDate;
document.getElementById(this.id+'-description').innerHTML = truncate(show.description,190);
document.getElementById(this.id+'-time-start').innerHTML = show.startTime;
document.getElementById(this.id+'-time-end').innerHTML = show.endTime;
};
this.id=myId;
return true;
}
function nowNextView(){
this.now = new scheduleItemView('now');
this.next = new scheduleItemView('next');
this.update = function(type,args){
var myshow=args[0];
// problem is below. I have to use the global name to access the update method.
myNowNextView.now.update(myshow.now);
myNowNextView.next.update(myshow.next);
// whereas what I want to do is reference them using the "this" command like below.
// this.now.update(myshow.now);
// this.next.update(myshow.next);
// the above doesnt work. The update method in scheduleItemView is not seen unless referenced globally
// BUT even more infuriating, this.now.id does return "now" so it can access the object, just not the method
// any ideas?
};
}
object is then instantiated with
var myNowNextView = new nowNextView();
and then I run the method:
myNowNextView.update(stuff);
I tried to describe the problem within the body of the program. No error in the code was thrown, and I had to do a try/catch before it grudgingly told me that it couldn't find the method.
Is the design flawed somehow? can I not do this?
Many thanks in advance,
Steve
function scheduleItemView(myId){
this.update = function(show){
document.getElementById(this.id+'-title').innerHTML = show.title +": "+ show.startDate;
document.getElementById(this.id+'-title-overlay').innerHTML = show.title +": "+ show.startDate;
document.getElementById(this.id+'-description').innerHTML = truncate(show.description,190);
document.getElementById(this.id+'-time-start').innerHTML = show.startTime;
document.getElementById(this.id+'-time-end').innerHTML = show.endTime;
};
this.id=myId;
}
function nowNextView(){
var myshow=args[0];
var scope = this;
this.now = new scheduleItemView('now');
this.next = new scheduleItemView('next');
this.update = function(type,args){
scope.now.update(myshow.now);
scope.next.update(myshow.next);
};
}
I think you could really benefit from studying closures a bit in javascript. It seems like you are trying to apply a traditional OO approach to js objects, and that won't give you the results you are expecting.
I would recommend reading over this post for an easy way to use closures:
http://howtonode.org/why-use-closure
Something like this:
<html>
<head>
<script type="text/javascript">
function createScheduleItemView(myId){
var _show = false
return {
setShow : function setShow(show) {
_show = show
},
update : function update(){
document.getElementById( myId +'-title').innerHTML = _show.title;
}
}
}
function createNowNextView(){
var _now = createScheduleItemView('now');
var _next = createScheduleItemView('next');
return {
publicVar : "Example",
update : function update(args) {
var myshow=args[0];
_now.setShow(myshow.now)
_now.update();
_next.setShow(myshow.next)
_next.update();
}
};
}
function runIt() {
nowNextView = createNowNextView()
args = []
showArgs = {
now : {title : "Beauty and the Beast"},
next : {title: "I did it myyyyyy way"}
}
args.push(showArgs)
nowNextView.update(args)
//Private variables can not be accessed
//console.log(nowNextView._now)
//undefined
//
//But anything you return in the object is public
//console.log(nowNextView.publicVar)
//Example
}
</script>
</head>
<body onload="runIt()">
<h3>Now Showing:</h3>
<p id="now-title"></p>
<h3>Up Next:</h3>
<p id="next-title"></p>
</body>
</html>