I have a fundamental misunderstanding of one of my numerous errors. I use jquery.
I have an object defined as:
var terms = {};
terms.clear_history = function(a, b)
{ /* DO SOMETHING */ }
I can call the terms.clear_history(1,2) function in my main js file, no problem. But when I try to call it from the "click" of a <a/> element:
$(document).on('click', '#clearterms', function(){
terms.clear_history(1, 2);
});
it gives me the following error:
Uncaught TypeError: Object # has no method 'clear_history'
I understand that I don't understand something fundamental here...
Thank you!
It sounds like a scope issue. Maybe the terms in the global scope the same as the one assigned clear_history given the method.
also, you don't want to name your param as this which is a reserved keyword in JS.
try this:
window.terms = {};
window.terms.clear_history = function(foo,bar){console.log(foo,bar);};
//then later:
$(document).on('click', '#clearterms', function(){
window.terms.clear_history(1, 2);
});
Related
I'm trying to clean my code a bit, so I create some small objects or libraries (call it how you want) like:
function myLib() {
this.get = function() { ... };
...
};
Problem is when I try to call it like myLib.get(). It throws the following error:
Uncaught TypeError: myLib.get is not a function
I've tried to encapsulate the call into $(document).ready(), but it did not help.
Can you help me, please?
Thanks!
myLib is used for "libary", and you want to call this "get" method of libary.
Static instance is better in your case.
const myLib = {
get:function(){},
get2:function(){}
...
};
myLib.get();
myLib.get2();
so I create some small objects or libraries (call it how you want)
In your case you are creating a constructor, myLib is a constructor and not just a function, and you can't access a function's properties and methods directly that's why you got the Exception.
So you need to get an instance of myLib in order to call the get method or to access any of its members(methods).
function myLib() {
this.get = function() { console.log("get called!!"); };
};
let lib = new myLib();
lib.get();
Note:
And from the MDN Reference for Functions you can see that:
The this keyword does not refer to the currently executing function, so you must refer to Function objects by name, even within the function body.
You should use myLib as a constructor ie:
var lib = new myLib();
lib.get();
I wonder if somebody could please help me understand something that seems odd with JS?
The below code works. The function inlineEditEvent.init() is called, and then t.copy() is called correctly (where var t = this;).
However, if I was to replace that with this.copy(), I get the error this.copy is not a function.
What's the difference here? Why does the below work, but not the way as described in the last paragraph? Thanks.
jQuery(function($){
$(document).ready(function(){inlineEditEvent.init();});
inlineEditEvent = {
init : function(){
var t = this;
/** Copy the row on click */
$('#the-list').on('click', '.row-actions a.single-copy', function(){
return t.copy();
});
}, // init
copy : function(){
// Do stuff here
}
} // inlineEditEvent
});
You're setting t as a context variable of this (of your init function). Once inside your click handler, this is now referring to the click handler, no longer the init function. Therefore, this.copy() is not a function.
this refers to this within the functions scope. That's why you need to set a self variable, so it's accessible within the scope of the function. Considering you're using jQuery, you could use $.proxy:
$.proxy(function(){
return this.copy();
},this)
t.copy(); appears in a different function to var t = this;. The value of this changes inside each function.
When you say var t= this; it refers to what this meant in that context. Later on when you are trying to refer to this, it is referring to a.single-copy instead since that is the new context it is in.
I'm not a newbie to JavaScript, but often I find its flexible ways (like defining anonymous function as callbacks and their scope) quite confusing. One thing I'm still struggling with are closures and scopes.
Take this example (from a Backbone model):
'handleRemove': function() {
var thisModel = this;
this.view.$el.slideUp(400, function() { thisModel.view.remove(); });
},
After the model is removed/deleted, this will animate its view and finally remove it from the DOM. This works just fine - but initially I tried the following code:
'handleRemove': function() {
var thisModel = this;
this.view.$el.slideUp(400, thisModel.view.remove );
},
Which is basically the same, but without the function() {} wrapper for the remove() call.
Can someone explain why the latter code does not work? I get the following exception/backtrace:
Uncaught TypeError: Cannot call method 'remove' of undefined backbone-min.js:1272
_.extend.remove backbone-min.js:1272
jQuery.speed.opt.complete jquery-1.8.3.js:9154
jQuery.Callbacks.fire jquery-1.8.3.js:974
jQuery.Callbacks.self.fireWith jquery-1.8.3.js:1084
tick jquery-1.8.3.js:8653
jQuery.fx.tick
Thank you!
That's because the context (this) of the callback function changes to the element being animated by jQuery.
var obj = { fn: function() { // Used as below, the following will print:
alert(this === obj); // false
alert(this.tagName); // "DIV"
}};
$('<div>').slideUp(400, obj.fn);
Furthermore, Backbone's view.remove function looks like this (source code):
remove: function() {
this.$el.remove();
this.stopListening();
return this;
},
Because this is not the Backbone view object any more, $el is not defined. Hence you get the "Cannot call method 'remove' of undefined" error.
Another way to avoid the error is to use Underscore's _.bind method:
this.view.$el.slideUp(400, _.bind(thisModel.view.remove, this) );
i was exploring in the last few days how big frameworks works , how they assign their function name and it can't(?) be override , i pretty much know how framework work with anonymous function , for example they do it this way or similar version :
(function(){
var Sizzle = function (){
var x;
};
Sizzle.f = function(){
alert("!");
};
window.Sizzle = Sizzle;
})();
i still don't get few things about those huge frameworks and i hope i can find answer :
how do they assign function name and the name can't be override?
in the code above to call the function i need to write Sizzle.f() to get the function to work , but when i use jquery i don't write Jquery.show() , just show() , how do they vanish the "jquery" from "jquery.show()" function call?
by saying the name can't be override i mean , if i create function with one of the jquery functions names , the jquery function will work.
thanks in advance.
As has been shown for #2, it's really easy for BIG_NAMESPACE.Functions.doStuff to be added to anything you want.
var _ = BIG_NAMESPACE.Functions.doStuff;
_(); // runs BIG_NAMESPACE.Functions.doStuff;
As for #1:
Most libraries DO let their functions be overwritten.
It's the values that are inside of the framework's closure which are preserved, for safety reasons.
So you could do something like:
BIG_NAMESPACE.Functions.doStuff = function StealEverything() {};
(BIG_NAMESPACE.Functions.doStuff === StealEverything) // true;
But doStuff would have NO access to any of the variables hidden inside of the framework's closure.
It would also mean that until the page was reloaded, doStuff would also not work the way you want it to.
HOWEVER, in newer versions of JavaScript (ECMA5-compatible browsers), it WILL be possible to do something like what you're suggesting.
BIG_NAMESPACE = (function () {
var do_stuff = function () { console.log("doin' stuff"); },
functions = {
set doStuff (overwrite) { }
get doStuff () { return do_stuff; }
};
return { Functions : functions };
}());
Then, this will work:
BIG_NAMESPACE.Functions.doStuff(); // "doin' stuff"
BIG_NAMESPACE.Functions.doStuff = function () { console.log("ain't doin' jack"); };
BIG_NAMESPACE.Functions.doStuff(); // "doin' stuff"
However, Frameworks aren't going to use this for a LONG time.
This is not even remotely backwards compatible. Maybe in 2016...
There were defineGetter and defineSetter methods as well, but they aren't a formal part of the JavaScript language. Like innerHTML, they're things that the browser vendors put in, to make life better... ...as such, there's no real guarantee that they're going to be in any/all browsers your users have. Plus, they're deprecated, now that new browsers use the get and set constructs that other languages have.
(function(){
var jqueree = {};
jqueree.someval = 22;
jqueree.somefunc = function(){ alert(this.someval); };
window.jqueree = jqueree;
window.somefunc = function(){ jqueree.somefunc.call(jqueree); };
window.$$$ = jqueree;
})();
// all equivalent
window.somefunc();
window.jqueree.somefunc();
$$$.somefunc();
somefunc();
Answering your Questions
At the top of jQuery you'll see: var jQuery = (function() {, which creates the local function (its incomplete; the }); occurs elsewhere).
At the very end of jQuery you'll notice the following, which is how it attaches it to the global namespace:
// Expose jQuery to the global object
window.jQuery = window.$ = jQuery;
I have never seen a jQuery function called without referencing the jQuery object. I think you always need to use jQuery.show() or $.show(); however maybe you're saying you don't have to call window.jQuery.show(), which you are permitted to drop the window, since that is the default.
Using your example
(function(){
/* This is where Sizzle is defined locally, but not exposed globally */
var Sizzle = function (){
var x;
};
/* If you put "window.f = Sizzle.f = function(){" then you could *
* call f() w/o typing Sizzle.f() */
Sizzle.f = function(){
alert("!");
};
/* The following line is what makes it so you can use Sizzle elsewhere *
* on your page (it exposes it globally here) */
window.Sizzle = Sizzle;
})();
use function _name_() {} and the name is static
the simply use var $ = jQuery; to create an alias.
jQuery works this way:
Supposed you have this jQuery code:
$("#title").show();
You have three elements to that line.
$ is a javascript function
"#title" is an argument to that function
.show() is a method call
Here's how it works.
Javascript executes the function named $ and passed it an argument of "#title".
That function does it's business, finds the #title object in the DOM, creates a jQuery object, puts that DOM element into the array in the jQuery object and returns the jQuery object.
The Javascript execution engine then takes the return value from that function call (which is now a jQuery object) and looks for and executes the .show() method on that object.
The .show() method then looks at the array of DOM elements in the jQuery object and does the show operation for each DOM element.
In answer to your question, there is no .show() all by itself. It's a method on a jQuery object and, in this example, that jQuery object is returned from the $("#title") function call.
Hi I don't know whether this is my mistake in understanding Javascript prototype object ..
Well to be clear I'm new to the Javascript singleton concept and lack clear cut knowledge in that but going through some referral sites I made a sample code for my system but it's giving out some errors which I couldn't find why so I'm asking for your help. My code is:
referrelSystem = function(){
//Some code here
}();
Prototype function:
referrelSystem.prototype.postToFb = function(){
//Some Code here
};
I get an error saying prototype is undefined!
Excuse me i thought of this right now
EDIT
I have used like this:
referrelSystem = function(){
return{
login:getSignedIn,
initTwitter:initTw
}
};
Is this causing an issue?
A typical way to define a JavaScript class with prototypes would be:
function ReferrelSystem() {
// this is your constructor
// use this.foo = bar to assign properties
}
ReferrelSystem.prototype.postToFb = function () {
// this is a class method
};
You might have been confused with the self-executing function syntax (closures). That is used when you would like to have "private" members in your class. Anything you declare in this closure will only be visible within the closure itself:
var ReferrelSystem = (function () {
function doSomething() {
// this is a "private" function
// make sure you call it with doSomething.call(this)
// to be able to access class members
}
var cnt; // this is a "private" property
function RS() {
// this is your constructor
}
RS.prototype.postToFb = function () {
// this is a class method
};
return RS;
})();
I would recommend that you study common module patterns if you're looking into creating a library.
Update: Seeing your updated code, the return from referrelSystem won't work as expected, since return values are discarded when calling new referrelSystem().
Rather than returning an object, set those properties to this (the instance of referrelSystem that gets constructed):
var referrelSystem = function () {
// I assume you have other code here
this.login = getSignedIn;
this.initTwitter = initTw;
};
I don't think you intend to immediately execute the functions, change them to this:
var referrelSystem = function(){
//Some code here
};
(+var, -())
Same with the prototype function:
referrelSystem.prototype.postToFb = function(){
//Some Code here
};
(Here you don't need the var, because you're assigning to something that already exists.)
A function should return to work as
prototype
property.
Take a look at this example here