122

I'm really confused how I can get console.log is not a function on line 1091. If I remove the closure below, line 1091 doesn't complain such error. Chrome Version 43.0.2357.130 (64-bit).

enter image description here

Here is the code:

$scope.columnNameChanged = function (tableColumn) {
    setDirtyColumn(tableColumn);
    //propagate changes to the key fields
    for (var i = 0; i < $scope.tableIndexes.length; ++i) {
        for (var j = 0; j < $scope.tableIndexes[i].columnName.length; ++j) {
            if ($scope.tableIndexes[i].columnName[j] === tableColumn.previousName) {
                console.log('xxx', $scope.tableIndexes[i].columnName[j])
                (function (i, j) {
                    $timeout(function () {
                        console.log($scope.tableIndexes[i].columnName[j])
                        $scope.tableIndexes[i].columnName[j] = tableColumn.name.toUpperCase();
                        console.log($scope.tableIndexes[i].columnName[j])
                    });
                })(i, j);
            }
        }
    }
};
Qian Chen
  • 12,930
  • 14
  • 54
  • 81

6 Answers6

255

Solution

Simply put a semicolon (;) after console.log().


Explanation

The error is easily reproducible like this:

console.log()
(function(){})

It’s trying to pass function(){} as an argument to the return value of console.log() which itself is not a function but actually undefined (check typeof console.log();). This is because JavaScript interprets this as console.log()(function(){}). console.log however is a function.

If you didn’t have the console object you’d see

ReferenceError: console is not defined

If you had the console object but not the log method you’d see

TypeError: console.log is not a function

What you have, however, is

TypeError: console.log(...) is not a function

Note the (...) after the function name. With those it’s referring to the return value of the function.

The line break doesn’t separate these two expressions as separate statements because of JavaScript’s rules for automatic semicolon insertion (ASI).


Respect the ;

All these code snippets result in all sorts of unexpected errors if no semicolons are present:

console.log() // As covered before
() // TypeError: console.log(...) is not a function
console.log() // Accessing property 0 of property 1 of the return value…
[1][0] // TypeError: console.log(...) is undefined
console.log() // Like undefined-3
-3 // NaN
let a, b;
const array = Array.from({ length: 2 })

// Now, let’s use destructuring:
[a, b] = array; // ReferenceError: can't access lexical declaration 'array' before initialization
let a, b;
const array = Array.from({ length: 2 }).fill(1),
  array2 = Array.from({ length: 2 })

// Now, let’s use destructuring. Attempt to get the two 1’s from `array` as `a` and `b`:
[a, b] = array;
console.log(a, b); // undefined undefined

Another Example

You see the (...) oftentimes with the use of chained methods or chained property accessors:

string.match(/someRegEx/)[0]

If that RegEx isn’t found, the method will return null and the property accessor on null will cause a TypeError: string.match(...) is null — the return value is null. In the case of console.log(...) the return value was undefined.

Sebastian Simon
  • 14,320
  • 6
  • 42
  • 61
  • 12
    Thanks. Problem solved by adding a semicolon. What a dark corner in the javascript. – Qian Chen Jun 23 '15 at 20:59
  • 5
    @ElgsQianChen: One reason to always use semicolons. – Felix Kling Jun 23 '15 at 21:00
  • But a very interesting question spawned from the “stylistic choice” to never use semicolons… – Sebastian Simon Jun 23 '15 at 21:00
  • 2
    so is it because `console.log()()` its `console.log(...)` 3 dots not a function error, otherwise it should been just `console.log` is not function (only if it wasnt but actually it is) – vinayakj Jun 23 '15 at 21:01
  • 2
    @vinayakj Exactly. If something’s not a function then that function is always referd to by its function name, e. g. `object.method`, if you’re using the return value, especially in a chained method, it’ll be `object.method(...)`. It kinda takes the experience to know why you should always use semicolons, _and_ how to interpret JavaScript error messages correctly. – Sebastian Simon Jun 23 '15 at 21:04
  • @Xufox `typeof console.log` returns `"function"` while `typeof console.anyFunctionYouCanImagineAtThisPointWillAlsoReturn` returns `"undefined"` as expected – jcoig Oct 05 '16 at 09:55
  • @jcoig The code in the answer should actually throw an error. When I test it again, it actually does. I think an earlier Firefox version actually behaved differently. – Sebastian Simon Oct 05 '16 at 10:02
  • legend. Was banging my head for ages for this, yet it's obvious when you understand what's going on, cheers – thatOneGuy Jul 20 '18 at 14:38
  • 2
    Because of issues like this it is sometimes recommended to always prefix IIFEs with a semicolon. That way if you move it around it wont risk breaking a missing semicolon elsewhere. Additionally if things get weird during minification/bundling it would be safer. – Marie Jun 12 '19 at 14:19
  • 1
    it is a bit amazing it is reporting `console.log(...) is not a function`. In some language it'd report `undefined is not a function` – nonopolarity Sep 10 '19 at 13:02
  • Prefixing iifes with a semicolon is sound advice (better then "postfixing" everything else with one, imo). An even better one is not using iifes when you don't need them. – isacvale Jan 05 '20 at 11:35
6

2020 Update

One possible cause can be the declaration of var console somewhere in your script.

Use:

window.console.log(...);

instead. Worked for me.

I hope it helps

Community
  • 1
  • 1
Learner
  • 9,004
  • 6
  • 35
  • 55
  • I have the same problem and global.console.log works, why is this happening? How do I fix it and use the consol.log – Gutyn Apr 18 '19 at 23:27
5

The error means that the return value of console.log() is not a function. You are missing a semicolon:

console.log('xxx', $scope.tableIndexes[i].columnName[j]);
//                                                      ^

which makes the following (...) of the IIFE to be interpreted as a function call.


Compare the error messages of

> var foo = {bar: undefined};
> foo.bar();
Uncaught TypeError: foo.bar is not a function

and

> var foo = {bar: function(){}};
> foo.bar()();
Uncaught TypeError: foo.bar(...) is not a function
Felix Kling
  • 705,106
  • 160
  • 1,004
  • 1,072
1

There is another way to encounter this error. console.log is not immutable and it is possible to accidentally overwrite the value.

console.log = 'hi';

In this case just reload the page to undo the damage.

Craig Pemberton
  • 314
  • 2
  • 8
-1

I know this is not "THE" answer, but thought I would toss in the following

 var console = $( data.message_target );
 console.val( console.val() + data.message); 
 console.scrollTop(console[0].scrollHeight - console.height());

I had a textarea on the page I was calling "console". suddenly all my console.log() scripts gave the error "Uncaught TypeError: console.log is not a function at Object"

... and rightly so, because I used a reserved namespace for my object/var. I realized what I had done after reading his post, and for the sake of posterity: double check naming conventions.

cheers

"its always human error"

-1

In react-native at least, the console seems to work without any import, so, removing import console = require('console'); or import console from 'console'; from the begin of my file fixed it for me. (the VS Code IDE seems to add that automatically sometimes )

piet.t
  • 11,035
  • 20
  • 40
  • 49
Top-Master
  • 2,934
  • 1
  • 17
  • 34