For a previous question I answered here on SO, I made the following library.
(function(){
var LS = function(){
return new LS.fn.init();
};
LS.fn = LS.prototype ={
//Check to see if the browser suports LocalStorage
init : function(){
this.ls = (typeof(Storage)!=="undefined") ? false : true;
return this;
}
}
LS.fn.init.prototype = LS.fn;
LS.fn.init.prototype = {
set : function(name, val){
if(this.ls) localStorage.setItem(name, val);
},
get : function (name){
if(this.ls) return localStorage.getItem(name);
},
remove : function(name){
if(this.ls) localStorage.removeItem(name);
},
test: function(){
alert("hi")
}
}
window.LS = window.ls = LS;
})();
This was working fine until recently.
I am getting errors like:
LS.set("foo", "bar"); // Error: undefined is not a function...
Even the following code gives an error:
LS.test();
Why has this stopped working?
Thank you.
NOTE: Previously, I had a typo, but now I have fixed that and it still doesn't work.
Your window.LS is initialized to a function, and you seem to use it as if you expect it to be initialized to the return value of that function.
Change this line:
window.LS = window.ls = LS;
to:
window.LS = window.ls = LS();
Also, try to simplify your library code. It seems very convoluted. At the very least comment it out a bit to indicate what the various parts do/are used for. The part with the typo (LS.protorype) isn't used anywhere for example.
Related
I have the following code.
function Test() {
this.myTest = "Test";
}
Test.prototype.toString = function testToString() {
return this.myTest;
};
var test = new Test();
console.log(test);
I expect this to print Test, but it prints Test { myTest: 'Test' }. I thought that overriding toString should use that new function whenever it tries to convert to a string. Any ideas why this isn't working?
According to the specifications (console.log --> Logger --> Printer) the implementation of console.log is ultimately up to the implementation.
So, it is likely that in the environment you are working in the implementation of console.log(obj) is not simply Printer("log", obj.toString()).
function Test() {
this.myTest = "Test";
}
Test.prototype.toString = function testToString() {
return this.myTest;
};
var test = new Test();
console.log(test.toString());
Based on some of the answers here I was able to solve this by using the following code. Although it's similar to some existing answers it is slightly different so decided to post it here.
function Test() {
this.myTest = "Test";
}
Test.prototype.toString = function testToString() {
return this.myTest;
};
var test = new Test();
console.log(test + "");
So just adding + "" to the end of the console.log works perfectly and will run the toString function.
I'm trying to override some functions from a lib called log4javascript.
I tried the following:
var _logFatal = log.fatal;
var _logError = log.error;
var _logWarn = log.warn;
var _logDebug = log.debug;
log.fatal = function(message){
return _logFatal(stackTrace(message));
};
log.error = function(message){
return _logError(stackTrace(message));
};
log.warn = function(message){
return _logWarn(stackTrace(message));
};
log.debug = function(message){
return _logDebug(stackTrace(message));
};
But it doesn't work, when I call log.warn('test') for instance, it fails with Uncaught TypeError: object is not a function. But it works fine if I remove that part of the code.
What did I do wrong?
What you are trying to do is what I've seen called "monkey-patching".
I believe the problem you are having is that you are not invoking the functions you are trying to extend with the correct scope.
Try this pattern:
var fnPreviousFatal = log.fatal;
log.fatal = function(message) {
fnPreviousFatal.apply(this, [message]);
}
I've been working on writing a custom jquery plugin for one of my web applications but I've been running into a strange error, I think it's due to my unfamiliarity with object-oriented programming.
The bug that I've been running into comes when I try to run the $(".list-group").updateList('template', 'some template') twice, the first time it works just fine, but the second time I run the same command, I get an object is not a function error. Here's the plugin code:
(function($){
defaultOptions = {
defaultId: 'selective_update_',
listSelector: 'li'
};
function UpdateList(item, options) {
this.options = $.extend(defaultOptions, options);
this.item = $(item);
this.init();
console.log(this.options);
}
UpdateList.prototype = {
init: function() {
console.log('initiation');
},
template: function(template) {
// this line is where the errors come
this.template = template;
},
update: function(newArray) {
//update code is here
// I can run this multiple times in a row without it breaking
}
}
// jQuery plugin interface
$.fn.updateList = function(opt) {
// slice arguments to leave only arguments after function name
var args = Array.prototype.slice.call(arguments, 1);
return this.each(function() {
var item = $(this), instance = item.data('UpdateList');
if(!instance) {
// create plugin instance and save it in data
item.data('UpdateList', new UpdateList(this, opt));
} else {
// if instance already created call method
if(typeof opt === 'string') {
instance[opt](args);
}
}
});
}
}(jQuery));
One thing I did notice when I went to access this.template - It was in an array so I had to call this.template[0] to get the string...I don't know why it's doing that, but I suspect it has to do with the error I'm getting. Maybe it can assign the string the first time, but not the next? Any help would be appreciated!
Thanks :)
this.template = template
Is in fact your problem, as you are overwriting the function that is set on the instance. You end up overwriting it to your args array as you pass that as your argument to the initial template function. It basically will do this:
this.template = ["some template"];
Thus the next time instance[opt](args) runs it will try to execute that array as if it were a function and hence get the not a function error.
JSFiddle
I have this code:
var history = {
stack : [],
counter : -1,
add : function(item){
this.stack[++this.counter] = item;
this.doSomethingWith(item);
// delete anything forward of the counter
this.stack.splice(this.counter+1);
},
undo : function(){
this.doSomethingWith(this.stack[--this.counter]);
},
redo : function(){
this.doSomethingWith(this.stack[++this.counter]);
},
doSomethingWith : function(item){
// show item
}
};
When I try use that on this way it's not working;
var item = $('#myDiv');
history.add(item);
I have this error:
Uncaught TypeError: undefined is not a function
How can I solve the problem? Thanks!
The problem is that you picked a bad name for your object. There is build in History object available as window.history. So rename yours to something else and it should work. For example:
var appHistory = {
stack : [],
counter : -1,
...
};
You could also fix it by wrapping your code into IIFE for example, so that history would become a local variable. But I would still recommend picking less confusing name.
It works well if you put this behind the other code:
var item = $('myDiv');
history.add(item);
If you put it in front the function is not yet defined.
Working example: http://jsfiddle.net/LqrpW/
$('myDiv') replace with $('.myDiv') or $('#myDiv')
I am trying to use the demo items on the Kendo page in my Angular app. Most work fine, but a few of them are throwing JSHINT errors of "undefined" objects, for example:
function MyCtrl($scope) {
$scope.showInContainer = function() {
var date = new Date();
date = kendo.toString(date, "HH:MM:ss.") + kendo.toString(date.getMilliseconds(), "000");
$scope.notf2.show(date, "info");
};
$scope.dismissAll = function() {
$scope.notf1.hide();
$scope.notf2.hide();
};
}
This says that "kendo" is undefined (as in kendo.tostring())
This leads me to believe some code is missing somewhere.
I have included kendo.core.min.js, kendo.ui.core.min.js, angular-kendo.js as directed
Please try this code to verify your kendo.version is correct in your global namespace object, "kendo".
https://jsbin.com/hakufipici/edit?html,js,output
$(function(){
if(kendo === "undefined"){
alert('no kendo');
}else{
alert(kendo.version);
}
});