It looks like "$smth is not a function" is a very common problem with JavaScript, yet after looking through quite a few threads I still cannot understand what is causing it in my case.
I have a custom object, defined as:
function Scorm_API_12() {
var Initialized = false;
function LMSInitialize(param) {
errorCode = "0";
if (param == "") {
if (!Initialized) {
Initialized = true;
errorCode = "0";
return "true";
} else {
errorCode = "101";
}
} else {
errorCode = "201";
}
return "false";
}
// some more functions, omitted.
}
var API = new Scorm_API_12();
Then in a different script I am trying to use this API in the following way:
var API = null;
function ScormProcessInitialize(){
var result;
API = getAPI();
if (API == null){
alert("ERROR - Could not establish a connection with the API.");
return;
}
// and here the dreaded error pops up
result = API.LMSInitialize("");
// more code, omitted
initialized = true;
}
The getAPI() stuff, looks like this:
var findAPITries = 0;
function findAPI(win)
{
// Check to see if the window (win) contains the API
// if the window (win) does not contain the API and
// the window (win) has a parent window and the parent window
// is not the same as the window (win)
while ( (win.API == null) &&
(win.parent != null) &&
(win.parent != win) )
{
// increment the number of findAPITries
findAPITries++;
// Note: 7 is an arbitrary number, but should be more than sufficient
if (findAPITries > 7)
{
alert("Error finding API -- too deeply nested.");
return null;
}
// set the variable that represents the window being
// being searched to be the parent of the current window
// then search for the API again
win = win.parent;
}
return win.API;
}
function getAPI()
{
// start by looking for the API in the current window
var theAPI = findAPI(window);
// if the API is null (could not be found in the current window)
// and the current window has an opener window
if ( (theAPI == null) &&
(window.opener != null) &&
(typeof(window.opener) != "undefined") )
{
// try to find the API in the current window�s opener
theAPI = findAPI(window.opener);
}
// if the API has not been found
if (theAPI == null)
{
// Alert the user that the API Adapter could not be found
alert("Unable to find an API adapter");
}
return theAPI;
}
Now, the API is probably found, because I do not get the "Unable to find..." message, the code proceeds to try to initialize it. But firebug tells me API.LMSInitialize is not a function, and if I try to debug it with alert(Object.getOwnPropertyNames(API));, it gives me a blank alert.
What am I missing?
For more generic advice on debugging this kind of problem MDN have a good article TypeError: "x" is not a function:
It was attempted to call a value like a function, but the value is not
actually a function. Some code expects you to provide a function, but
that didn't happen.
Maybe there is a typo in the function name? Maybe the object you are
calling the method on does not have this function? For example,
JavaScript objects have no map function, but JavaScript Array object
do.
Basically the object (all functions in js are also objects) does not exist where you think it does. This could be for numerous reasons including(not an extensive list):
Missing script library
Typo
The function is within a scope that you currently do not have access to, e.g.:
var x = function(){
var y = function() {
alert('fired y');
}
};
//the global scope can't access y because it is closed over in x and not exposed
//y is not a function err triggered
x.y();
Your object/function does not have the function your calling:
var x = function(){
var y = function() {
alert('fired y');
}
};
//z is not a function error (as above) triggered
x.z();
Your LMSInitialize function is declared inside Scorm_API_12 function. So it can be seen only in Scorm_API_12 function's scope.
If you want to use this function like API.LMSInitialize(""), declare Scorm_API_12 function like this:
function Scorm_API_12() {
var Initialized = false;
this.LMSInitialize = function(param) {
errorCode = "0";
if (param == "") {
if (!Initialized) {
Initialized = true;
errorCode = "0";
return "true";
} else {
errorCode = "101";
}
} else {
errorCode = "201";
}
return "false";
}
// some more functions, omitted.
}
var API = new Scorm_API_12();
I also hit this error. In my case the root cause was async related (during a codebase refactor): An asynchronous function that builds the object to which the "not a function" function belongs was not awaited, and the subsequent attempt to invoke the function throws the error, example below:
const car = carFactory.getCar();
car.drive() //throws TypeError: drive is not a function
The fix was:
const car = await carFactory.getCar();
car.drive()
Posting this incase it helps anyone else facing this error.
In addition to the popular answers above, if you are using a services or helper functions file and doing an export on the functions that you will later import in your project.
Make sure that the function name you are importing matches the exact name of the function being exported from the services, helper, or utils file - and that the function actually exists in the right file! I got stuck on this error and was debugging for a few hours, getting nowhere until I found this out.
Had the same issue on Next.js. On _app.tsx I forgot to wrap the Component with the AuthProvider where I had all the Authentication functions.
In my case after a ton of stackoverflowing I saw what a function thing would go with here... it was merely a silly typo , I forgot to put $ in start of the next line's instruction:
function o_chir(id,nom) {
_id_ochirish = id
_nom= nom
//here it threw that "Uncaught TypeError: nom is not a function"
('#nom').val(s_)
$('#o_chir').modal('show')
}
and PHPStorm didnt give any warning
I received this error when I copied a class object incorrectly using JSON.parse and JSON.stringify() which removed the function like:
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
// Method
calcArea() {
return this.height * this.width;
}
}
const square = new Rectangle(10, 10);
console.log('area of square: ', square.calcArea());
const squareCopy = JSON.parse(JSON.stringify(square));
// Will throw an exception since calcArea() is no longer function
console.log('area of square copy: ', squareCopy.calcArea());
Related
This question already has answers here:
How does variable scope work within the Mocha test framework?
(2 answers)
Closed 6 years ago.
I want to use mocha/chai to test code related to binary search trees. Here, I am testing the public insert method. I want to use beforeEach() and/or afterEach() hooks to reset the test environment prior to each it() statement so that I don't have to completely repeat the basics. However, I keep getting various errors.
Spec
describe("BinarySearchTree insert function", function() {
beforeEach(function() {
var binarySearchTree = new BinarySearchTree();
binarySearchTree.insert(5);
});
it("creates a root node with value equal to the first inserted value", function () {
expect(binarySearchTree.root.value).to.equal(5);
});
it("has a size equal to the amount of inserted values", function () {
binarySearchTree.insert(3);
expect(binarySearchTree.size).to.equal(2);
});
it("returns an error for non-unique values", function () {
binarySearchTree.insert(3);
expect(binarySearchTree.insert(3)).to.throw(String);
});
it("if inserted value is larger than current node, make or descend to rightChild", function () {
binarySearchTree.insert(3);
binarySearchTree.insert(10);
binarySearchTree.insert(7);
expect(binarySearchTree.root.rightChild.value).to.equal(10);
});
});
Error: ReferenceError: binarySearchTree is not defined
In truth, I expected errors before there is no afterEach() resetting the test environment, not because binarySearchTree is not defined. I'd like to accomplish this, if at all possible, with only Mocha and Chai (and not other packages like Sinon, etc).
Tested Code
exports.Node = Node;
function Node(value) {
this.value = value;
this.leftChild = null;
this.rightChild = null;
}
exports.BinarySearchTree = BinarySearchTree;
function BinarySearchTree() {
this.root = null;
this.size = 0;
}
BinarySearchTree.prototype.insert = function(value) {
// 1) when root node is already instantiated
if (this.root === null) {
// tree is empty
this.root = new Node(value);
this.size++;
} else {
// 2) nodes are already inserted
var findAndInsert = function (currentNode) {
if (value === currentNode.value) {
throw new Error('must be a unique value');
}
// base case
if (value > currentNode.value) {
// belongs in rightChild
if (currentNode.rightChild === null) {
currentNode.rightChild = new Node(value);
} else {
findAndInsert(currentNode.rightChild);
}
} else if (value < currentNode.value) {
// belongs in leftChild
if (currentNode.leftChild === null) {
currentNode.leftChild = new Node(value);
} else {
findAndInsert(currentNode.leftChild);
}
}
};
findAndInsert(this.root);
this.size++;
}
};
Bonus question... I'm not sure if I am properly testing for the thrown error (when a non-unique value is inserted)?
It is undefined because it is not in test function scope. Define it one step before in describe scope. For reference, look at the Angular docs. https://docs.angularjs.org/guide/unit-testing
describe("BinarySearchTree insert function", function() {
var binarySearchTree;
beforeEach(function() {
binarySearchTree = new BinarySearchTree();
binarySearchTree.insert(5);
});
it("creates a root node with value equal to the first inserted value", function () {
expect(binarySearchTree.root.value).to.equal(5);
});
it("has a size equal to the amount of inserted values", function () {
binarySearchTree.insert(3);
expect(binarySearchTree.size).to.equal(2);
});
it("returns an error for non-unique values", function () {
binarySearchTree.insert(3);
expect(binarySearchTree.insert(3)).to.throw(String);
});
it("if inserted value is larger than current node, make or descend to rightChild", function () {
binarySearchTree.insert(3);
binarySearchTree.insert(10);
binarySearchTree.insert(7);
expect(binarySearchTree.root.rightChild.value).to.equal(10);
});
});
The reason you are getting binarySearchTree is undefined is explained already.
I would like to talk about beforeEach and afterEach functions.
In beforeEach function we generally do basic setup for test things like variables initialization, stubbing out external calls etc.
and 'afterEach' method works like destroy functions where generally we write memory releases stuff.
I have some JavaScript functions in each page that I call them after jQuery is loaded.
The function in Questions.aspx page is afterQuestions(), the function in Default.aspx is afterDefault() and so on ....
In my master page I am calling them like:
if(typeof(afterQuestion) == 'function') afterQuestions();
if(typeof(afterDefault) == 'function') afterDefault();
As the number of functions grew, I tried something like:
var _fs = [After, AfterDefault, afterSettings, afterQuestions];
for (var i = 0; i < _fs.length; i++) if (typeof (_fs[i]) == "function") _fs[i]();
But it doesn't work this way. Can you please help me how can I create an Array of functions and call them?
Edit: I think nobody had read the question well to see that the all functions won't exist at the same time and that was the problem creating the array. I solved it by adding created functions to a global array and the looping and excuting functions in that array
If the function is not defined, you will get a JavaScript error since you are trying to reference a variable that is not defined. The type of check in your original code gets around that issue.
Your best bet is to namespace the functions into an object and use dot notation.
var methods = {
After : function () {console.log("After"); },
AfterDefault : function () {console.log("AfterDefault"); },
afterSettings : function () {console.log("afterSettings"); }
};
var _fs = [methods.After, methods.AfterDefault, methods.afterSettings, methods.afterQuestions];
for (var i = 0; i < _fs.length; i++) {
if (typeof (_fs[i]) == "function") {
_fs[i]();
}
}
Now when you want to register the methods you can just add to the methods object.
methods = methods || {};
methods.afterSettings = function () { console.log("added this in"); };
Now if the method is not defined the namespace will return undefined and the check will not error out.
Recently I have been trying to bind my application to CEF, the process was slow but I made some progress over the last days. However there is one thing I just can't get to work.
What I want to achieve is:
1. Registering a callback function within Javascript (These functions will be called when an event happens in my application)
2. Save the callback.
3. When the event occurs, execute the registered callback.
Now I got step 1 and 2 to work, but step 3 is where the problem is.
I tested it first by registering a callback and then calling it with an executeCallback() function in Javascript and it worked. But whenever I try to execute the callback from within C++ it doesn't work.
I create the setEventCallback in the onContextCread()
CefRefPtr<CefV8Value> object = context->GetGlobal();
CefRefPtr<CefV8Value> simplixObj = CefV8Value::CreateObject(NULL);
object->SetValue("simplix", simplixObj, V8_PROPERTY_ATTRIBUTE_NONE);
func = CefV8Value::CreateFunction("setEventCallback", $simplixHandler);
simplixObj->SetValue("setEventCallback", func, V8_PROPERTY_ATTRIBUTE_NONE);
With $simplixHandler being an instance of my own handler.
Here is the setEventCallback in my handler:
bool SimplixHandler::setEventCallback(CefRefPtr<CefV8Value> object, const CefV8ValueList& arguments, CefRefPtr<CefV8Value>& retval, CefString& exception)
if (arguments.size() == 2 && arguments[0]->IsString() && arguments[1]->IsFunction()) {
//Get name of callback
std::string callbackName = arguments[0]->GetStringValue();
//Get the current context
CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
//Insert into callbacks
$callbacks[callbackName] = std::make_pair(context, arguments[1]);
return true;
}
else if(arguments.size() != 2) {
exception = CefString("Invalid amount of parameters. Expected 2, received " + arguments.size());
return false;
}
else {
exception = CefString("Incompatible parameter types, expected (string, function).");
return false;
}
I then try to execute the callbacks by calling executeCallback:
bool SimplixHandler::executeCallback(std::string name, CefRefPtr<CefListValue> list) {
bool handled = false;
if (!$callbacks.empty() && $callbacks.count(name) != 0) {
std::pair<CefRefPtr<CefV8Context>, CefRefPtr<CefV8Value>> pair = $callbacks[name];
CefRefPtr<CefV8Context> context = pair.first;
CefRefPtr<CefV8Value> func = pair.second;
context->Enter();
CefV8ValueList callArgs;
//First argument is function name
CefRefPtr<CefV8Value> args = CefV8Value::CreateArray(list->GetSize());
setList(list, args);
callArgs.push_back(args);
CefRefPtr<CefV8Value> retval = func->ExecuteFunction(NULL, callArgs);
if (retval.get()) {
if (retval->IsBool())
handled = retval->GetBoolValue();
}
context->Exit();
}
return handled;
}
I call this function from within my SimplixHandler, however I call callbacks by calling the specific event function, example:
bool SimplixHandler::notifyDirectoryChanged(std::string directory) {
CefRefPtr<CefListValue> list = CefListValue::Create();
list->SetSize(1);
list->SetString(0, directory);
return executeCallback("onDirectoryChange", list);
}
And finally my Javascript:
function dirChange(dir) {
document.getElementById("filename").innerHTML = "It's something";
}
simplix.setEventCallback("onDirectoryChange", dirChange);
I know the event gets called (because I first had nullpointer exception due to wrong linking of classes, that's fixed now), but the Javascript Callback does not get called.
Does anyone know what I am doing wrong?
Thanks in advance.
you can use any function in html code for callback.
Renderer:
bool SimpleApp::OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
CefProcessId source_process,
CefRefPtr<CefProcessMessage> message)
{
std::string message_name = message->GetName();
if( message_name == "FUNC")
{
//AfxMessageBox("stop");
//browser->GetMainFrame()->ExecuteJavaScript("super_test('works!');", browser->GetMainFrame()->->GetURL(), 0);
CefRefPtr<CefV8Value> object = m_context->GetGlobal();
CefRefPtr<CefV8Context> v8context = browser->GetMainFrame()->GetV8Context();
v8context->Enter();
CefRefPtr<CefV8Value> func_test = object->GetValue("super_test");
if(func_test == NULL)
{
v8context->Exit();
return false;
}
CefV8ValueList arguments;
CefRefPtr<CefV8Value> test = CefV8Value::CreateString("hello from c++");
arguments.push_back(test);
CefRefPtr<CefV8Value> retval = func_test->ExecuteFunction(NULL, arguments);
v8context->Exit();
return true;
}
return false;
}
jScript:
<script>
function super_test(resp)
{
alert(resp);
return "7777";
}
browser:
CefRefPtr<CefProcessMessage> message = CefProcessMessage::Create("FUNC");
SimpleHandler::GetInstance()->GetBrowser()->SendProcessMessage(PID_RENDERER, message);
Maybe some of you know about AOP, in some languages using AOP can lead you to be able to inject code after, before, or while a method is executing,etc.
What I want is to apply the same in Javascript, I am currently working on a massive app which has more than 300 ajax calls, and every time I need to do some change on the catch statement on them, I have to modify them one by one which is very tedious.
What I want to do is something like :
functionName.before("try {")
functionName.after("} catch(ex){
//dostuff
}")
Is it possible? I know there are things like .call, or the arguments object inside every function..which seem pretty meta-function (AOP) functionalities.
Not with before and after, but a wrap will work:
Function.prototype.wrapTry = function(handle) {
var fn = this;
return function() {
try {
return fn.apply(this, arguments);
} catch(e) {
return handle(e);
}
};
};
Then use it like
var safeFunction = functionName.wrapTry(doStuff);
In JavaScript, functions are first-class objects. That means you can manipulate or redeclare them.
Assuming that there is a "foo" function:
var originalFoo = foo;
foo = function()
{
// "before" code.
// Call the original function.
originalFoo.apply(this, arguments);
// "after" code.
};
After that, any call to foo() will call the new function: even with parameters.
Old question but you may take a look over this https://github.com/k1r0s/kaop-ts/blob/master/docs/api.md#available-join-points
import { onException } from "kaop-ts"
import handlingException from "./somewhere"
class Something {
#onException(handlingException)
method() {
// stuff that may throw an error
}
}
I also will give a late answer in order to shed some light onto this special case that every then and now pops up as JavaScript and AOP.
Firstly, cases like the very one presented by the OP always ask for modifying already existing functionality, thus targeting closed code that sometimes is not even owned by the party that sees itself challenged from modifying the control flow of such code.
Why then, not just name it like that ... JavaScript method modification or JavaScript method modifiers.
Secondly, because of already riding the horse of terminology, altering closed functionality in JavaScript has nothing to do with Aspect-oriented Programming unless an implementation that claims to be AO provides abstraction and code-reuse levels for at least Aspect, Advice and Pointcut.
Last, for what the OP is going to achieve and what also has been the accepted answer, there does exist a a whole bunch of before, after around / wrap solutions, almost always unfortunately mentioning AO(P), and in far too many cases not taking care of the context or target which is essential to method modification.
The example I do provide uses a prototypal implementation of afterThrowing. Because JavaScript already features a standardized bind, I'm firmly convinced that Function.prototype is the right place as well for some other method-modifiers
like before, after, around, afterThrowing
and afterFinally.
// OP's example pseudo code
//
// functionName.before("try {")
//
// functionName.after("} catch(ex){
// dostuff
// }")
function doStuffAfterThrowing(exception, originalArguments) {
"use strict";
var context = this;
console.log('context : ', context);
console.log('String(exception) : ', String(exception));
console.log('originalArguments : ', originalArguments);
return "safely handled exception";
}
function doFail() {
throw (new ReferenceError);
}
function oneOutOfManyAjaxCallbacks(payload) {
doFail();
}
var jsonData = {
"foo": "foo",
"bar": "bar"
};
var someModifiedAjaxCallback = oneOutOfManyAjaxCallbacks.afterThrowing(doStuffAfterThrowing, { x: 'y' });
// does fail controlled/handled.
console.log('someModifiedAjaxCallback(jsonData) : ', someModifiedAjaxCallback(jsonData));
// does fail "Uncaught".
console.log('oneOutOfManyAjaxCallbacks(jsonData) : ', oneOutOfManyAjaxCallbacks(jsonData));
.as-console-wrapper { min-height: 100%!important; top: 0; }
<script>
(function (Function) {
var
isFunction = function (type) {
return (
(typeof type == "function")
&& (typeof type.call == "function")
&& (typeof type.apply == "function")
);
},
getSanitizedTarget = function (target) {
return ((target != null) && target) || null;
}
;
Function.prototype.afterThrowing = function (handler, target) { // afterThrowing
target = getSanitizedTarget(target);
var proceed = this ;
return (isFunction(handler) && isFunction(proceed) && function () {
var ret, args = arguments;
try {
ret = proceed.apply(target, args);
} catch (exc) {
ret = handler.call(target, exc, args);
//throw exc;
}
return ret;
}) || proceed;
};
}(Function));
</script>
Having come that far one might also consider reading ...
sandwich pattern in javascript code
Can you alter a Javascript function after declaring it?
I'd like to create a generic debugging routine using try / catch, within the catch segment I'd like a piece of code which will log the function name and all params passed (name => value).
Is this possible?
try{
// code
} catch(e) {
var function_name = ''; // how can I get this?
var function_params = ''; // how can I get this?
var errorText = 'UNEXPECTED ERROR: \n\n Error Details: '+e.toString();
errorText = errorText+' Called:'+function_name+'('+function_params+')';
}
In Chrome and Firefox you can use e.stack but no such luck in Internet Explorer.
The stack property is an array that you can loop over. It might differ a bit from browser to browser but it shouldn't be too hard to make a readable stacktrace.
You currently can't catch the arguments in all browsers.
In Chrome you might need to use:
Error.prepareStackTrace = function (error, stack) {
return stack;
}; // augments Chrome's Error.stack property with context data
Try using arguments.callee for the function name
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/arguments/callee
This isn't an exact answer because I don't give the function Name but this returns the entire function body...
Working sample: http://jsfiddle.net/sS6sY/
Object.prototype.getArgs = function(){
//returns the arguments passed to a function.
var els = [];
for(i=0; i< this.arguments.length; i++){
els.push(this.arguments[i]);
}
return els.join(',')
}
Object.prototype.getMethod = function(){
//returns the function as a string.
return this.constructor;
}
var Foo = function(){
this.arguments = arguments;
try{
throw {
name: 'Oops',
message: 'Didn\'t mean to make a Foo!'
}
}
catch(e){
console.log(this.getArgs());
console.log(this.getMethod());
}
}