console.log.apply not working in IE9 - javascript

Looks like I've re-invented the wheel, but somehow this isn't working in Internet Explorer 9, but does in IE6.
function debug()
if(!window.console) {
window.console = { log: function() { /* do something */ } };
}
console.log.apply(console, arguments);
}
Related:
Apply() question for javascript
F12 Debugger tells me that this "object" (console.log) does not support method 'apply'.
Is it not even recognized as a function?
Any other pointers or ideas?

The second part of an answer I gave recently answers this question too. I don't consider this a duplicate of that one so, for convenience, I'll paste it here:
The console object is not part of any standard and is an extension to the Document Object Model. Like other DOM objects, it is considered a host object and is not required to inherit from Object, nor its methods from Function, like native ECMAScript functions and objects do. This is the reason apply and call are undefined on those methods. In IE 9, most DOM objects were improved to inherit from native ECMAScript types. As the developer tools are considered an extension to IE (albeit, a built-in extension), they clearly didn't receive the same improvements as the rest of the DOM.
For what it's worth, you can still use some Function.prototype methods on console methods with a little bind() magic:
var log = Function.prototype.bind.call(console.log, console);
log.apply(console, ["this", "is", "a", "test"]);
//-> "thisisatest"
So you could fix up all the console methods for IE 9 in the same manner:
if (Function.prototype.bind && window.console && typeof console.log == "object"){
[
"log","info","warn","error","assert","dir","clear","profile","profileEnd"
].forEach(function (method) {
console[method] = this.bind(console[method], console);
}, Function.prototype.call);
}
This replaces the "host" functions with native functions that call the "host" functions. You can get it working in Internet Explorer 8 by including the compatibility implementations for Function.prototype.bind and Array.prototype.forEach in your code, or rewriting the above snippet to incorporate the techniques used by those methods.
See also
console.log typeof is "object" instead of "function" - Microsoft Connect (Live account required)

There is also Paul Irish's way of doing it. It is simpler than some of the answers above, but makes log always output an array (even if only one argument was passed in):
// usage: log('inside coolFunc',this,arguments);
// http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
window.log = function(){
log.history = log.history || []; // store logs to an array for reference
log.history.push(arguments);
if(this.console){
console.log( Array.prototype.slice.call(arguments) );
}
};

Several of IE's host object functions aren't really JavaScript functions and so don't have apply or call. (alert, for example.)
So you'll have to do it the hard way:
function debug()
var index;
if(!window.console) {
window.console = { log: function() { /* do something */ } };
}
for (index = 0; index < arguments.length; ++index) {
console.log(arguments[index]);
}
}

I came across the same IE trouble and made a routine for it.
It is not as fancy as all the above implementations, but it works in ALL modern browsers.
I tested it with Firefox (Firebug), IE 7,8,9 Chrome and Opera.
It makes use of the evil EVAL, but you will only want to debug in development.
Afterwards you will replace the code with debug = function () {};
So here it is.
Regards, Hans
(function(ns) {
var msgs = [];
// IE compatiblity
function argtoarr (args,from) {
var a = [];
for (var i = from || 0; i<args.length; i++) a.push(args[i]);
return a;
}
function log(arg) {
var params = "", format = "", type , output,
types = {
"number" : "%d",
"object" : "{%o}",
"array" : "[%o]"
};
for (var i=0; i<arg.length; i++) {
params += (params ? "," : "")+"arg["+i+"]";
type = types[toType(arg[i])] || "%s";
if (type === "%d" && parseFloat(arg[i]) == parseInt(arg[i], 10)) type = "%f";
format += (format ? "," : "")+type;
}
// opera does not support string format, so leave it out
output = "console.log("+(window.opera ? "" : "'%f',".replace("%f",format))+"%p);".replace("%p",params);
eval(output);
}
ns.debug = function () {
msgs.push(argtoarr(arguments));
if (console !== undefined) while (msgs.length>0) log(msgs.shift());
}
})(window);
Oops forgot my toType function, here it is.
function toType(obj) {
if (obj === undefined) return "undefined";
if (obj === null) return "null";
var m = obj.constructor;
if (!m) return "window";
m = m.toString().match(/(?:function|\[object)\s*([a-z|A-Z|0-9|_|#]*)/);
return m[1].toLowerCase();
}

Ok, it works when you write it this way:
function debug()
if(!window.console) {
window.console = {};
console.log = function() { /* do something */ };
}
console.log.apply(console, arguments);
}
Odd behaviour... but if you write it this way 'console.log' gets recognized as a function.

The reason I came to this question was that I as trying to 'spicy' the console.log function for a specific module, so I'd have more localized and insightful debug info by playing a bit with the arguments, IE 9 broke it.
#Andy E answer is great and helped me with lots of insight about apply. I just don't take the same approach to support IE9, so my solution is running the console only on "modern browsers" (being that modern means whatever browsers that behave the way I expect =)
var C = function() {
var args = Array.prototype.slice.call(arguments);
var console = window.console;
args[0] = "Module X: "+args[0];
if( typeof console == 'object' && console.log && console.log.apply ){
console.log.apply(console, args);
}
};

Try:
function log(type) {
if (typeof console !== 'undefined' && typeof console.log !== 'undefined' &&
console[type] && Function.prototype.bind) {
var log = Function.prototype.bind.call(console[type], console);
log.apply(console, Array.prototype.slice.call(arguments, 1));
}
}
log('info', 'test', 'pass');
log('error', 'test', 'fail');
Works for log, debug, info, warn, error, group or groupEnd.

Related

Javascript Conflict In Two Files

I use a prototype in my project:
NodeParser.prototype.getChildren = function(parentContainer) {
return flatten([].filter.call(parentContainer.node.childNodes, renderableNode).map(function(node) {
var container = [node.nodeType === Node.TEXT_NODE && !(node.parentNode instanceof SVGElement) ? new TextContainer(node, parentContainer) : new NodeContainer(node, parentContainer)].filter(nonIgnoredElement);
return node.nodeType === Node.ELEMENT_NODE && container.length && node.tagName !== "TEXTAREA" ? (container[0].isElementVisible() ? container.concat(this.getChildren(container[0])) : []) : container;
}, this));
};
We have to add our client javascript file to our project. They have a code like this:
Array.prototype.map = function(fnc) {
//code block
}
map in our code, return to them Array.prototype.map . How could I prevent such conflict?
This conflict happens in local only. In production there is no any conflict problem.
The only bullet proof solution would be to ask them not to monkeypatch prototypes of native object. Or at least do it in spec conformant way if they were doing it to polyfill native methods in older browsers.
if(typeof Array.prototype.map !== 'function') {
Array.prototype.map = function mapPolyfil() {
};
}
If this is not an option due to some contract obligations. You have the following options:
You can save native versions of monkeypatched methods before they did it.
var safeMap = Function.bind.call([].map);
// usage
safeMap(myArray, callback, thisArg)
If they "only" missed thisArg in their map implementation you can make sure you always pass prebinded functions
array.map(function(){}.bind(this))
Or even monkeypatch their implementation to start Eternal Monkeypatchers War
if(Array.prototype.map.length === 1) { //was patched
var theirMap = Array.prototype.map;
Array.prototype.map = function(fn, thisArg) {
if(arguments.length === 2) {
fn = fn.bind(thisArg)
}
return theirMap.call(this, fn);
}
}

Site behaves differently when developer tools are open IE11

Im using the following template in IE11 and can not figure out why the sidebar sings in every time navigation is happening. When developer tools are open it behaves as I would like it to. It is easily demoed by clicking on any one of the tabs under UI element in the tree while running IE11. However you will notice if F12 developer tools are open the side bar does not slide in every time navigation happens. This is not an issue in chrome. There is an error with fastclick that may show up however I have ran without fastclick and it still happens. Any help would be great. Thanks.
https://almsaeedstudio.com/themes/AdminLTE/pages/UI/general.html
Try removing any console.log() from your code.
console.log() which is to help out when debugging Javascript can cause IE to completely stop processing scripts on the page. To add to the mystery, if you keep watching your page in IE with devtools open - you won’t notice an issue at all.
Explanation
The reason for this is the console object is not instantiated unless devtools is open in IE. Otherwise, you will see one of two things:
Javascript won’t execute correctly
Console has cryptic errors, such as ‘object is undefined’ or others of that nature
Nine times out of ten, you have an errant console.log in the code somewhere. This does not affect any browser other than IE.
Another potential cause, especially if you are performing ajax calls, is the ajax response may be cached when dev tools are closed, but refreshed from the server when dev tools are open.
In IE, open the Network tab of Developer Tools, click the play icon, and un-set the Always refresh from server button. Then watch to see if any of your ajax calls are coming back with a response code of 304 (Not modified). If they are, then you are not getting fresh data from the server and you need to update the cacheability settings on the page that is being called via ajax.
Adding onto the already great answers (since I can't comment - requires 50 rep points), agreeing with the answer from #sam100rav and the comment from #storsoc, I discovered that in IE11 version 11.1387.15063.0 with updated version 11.0.90 (KB4462949), that window.console indeed exists as an empty object (window.console = {}). Hence, I used a variation of the polyfill from #storsoc as shown below.
if (!window.console || Object.keys(window.console).length === 0) {
window.console = {
log: function() {},
info: function() {},
error: function() {},
warn: function() {}
};
}
As pointed out already it's because IE11 + Edge<=16 is so stupid that it doesn't support console unless developer tools is opened... So if you open that to disable caching you won't see any issues and you might think that the issue was just due to browser cache... but nope.. :#
I made this "polyfill" for it (doesn't really polyfill, but makes IE not throw any errors). Add it as early as possible on your site as any js might be using console.log or console.warn etc.
window.console = typeof window.console !== 'object' || {};
console.warn = typeof console.warn === 'function' || function () {
return this;
};
console.log = typeof console.log === 'function' || function () {
return this;
};
console.info = typeof console.info === 'function' || function () {
return this;
};
console.error = typeof console.error === 'function' || function () {
return this;
};
console.assert = typeof console.assert === 'function' || function () {
return this;
};
console.dir = typeof console.dir === 'function' || function () {
return this;
};
console.table = typeof console.table === 'function' || function () {
return this;
};
console.group = typeof console.group === 'function' || function () {
return this;
};
console.groupEnd = typeof console.groupEnd === 'function' || function () {
return this;
};
console.time = typeof console.time === 'function' || function () {
return this;
};
console.timeEnd = typeof console.timeEnd === 'function' || function () {
return this;
};
console.timeLog = typeof console.timeLog === 'function' || function () {
return this;
};
console.trace = typeof console.trace === 'function' || function () {
return this;
};
console.clear = typeof console.clear === 'function' || function () {
return this;
};
console.count = typeof console.count === 'function' || function () {
return this;
};
console.debug = typeof console.debug === 'function' || function () {
return this;
};
console.dirxml = typeof console.dirxml === 'function' || function () {
return this;
};
console.groupCollapsed = typeof console.groupCollapsed === 'function' || function () {
return this;
};
I'm assuming you've fixed this since you posted it as I can not see the behavior you describe in your link.
However, I have recently run into a similar issue where the dev tools being open changed the behavior not because of console issues, but because opening the tools changed the width of the window. It was the window width difference that triggered an underlying bug in my case.
Related post here.
It's possible you've got the compatibility mode set to a later version of IE in your developer console (see the highlighted section)

is there a way to call this javascript function in this way?

I'd like be able to call a function like item_edit.say hello passed as a string on the window object (like the last line of the following):
var arc={ view: { item_edit: {} } };
arc.view.item_edit={
say_hello: function(){
alert('hello there');
}
}
var f_name='say_hello';
var g_name='item_edit.say_hello';
var str=window.arc.view.item_edit[f_name](); // <- this works
var str2=window.arc.view[g_name](); // <- this is what I'm interested in; curently doesn't work
any ideas on how to get this to work?
thx in advance
edit #1
I guess I should add that probably don't want to be doing eval although the more I look at it, that might be what makes sense (and is in fact what eval was made to do).
Sure. The Google closure library does something like this in its goog.provide function when not optimized by the compiler.
function callDotted(obj, path, args) {
var parts = path ? path.split('.') : [];
var i, n = parts.length;
for (i = 0; i < n - 1; ++i) {
obj = obj[parts[i]];
}
var fn = i < n ? obj[parts[i]] : obj;
return fn.apply(obj, args);
}
and then on browsers where Date.now returns the current timestamp,
callDotted(window, 'Date.now', [])
returns the current timestamp.
Here's one way using .reduce().
var str2 = g_name.split('.').reduce(function(obj, key) {
return obj[key];
}, window.arc.view);
You'll need to shim it for older browsers, and introduce safety checks if you want.
If you do this a lot, I'd add the function to your library so you can reuse it.
function keyToObj(obj, key) {
return obj[key];
}
Then use it like this:
var str2 = g_name.split('.').reduce(keyToObj, window.arc.view);
As #MikeSamuel pointed out, there's an issue with the this value of the executed function when using this approach.
To resolve this, we could make another version that's suited specifically for method invocations.
function keyToMethod(obj, key, i, arr) {
return i === arr.length - 1 && typeof obj[key] === "function"
? function() {
return obj[key].apply(obj, arguments);
}
: obj[key];
}
Now our function returns a function that invokes the method from the proper object.
var str2 = g_name.split('.').reduce(keyToMethod, window.arc.view)();
We could further enhance the returned function to check to see if the this value is the default value, and use the provided value if not.
How about this:
var str2 = eval('window.arc.view.' + g_name + '()');

How to proxying functions on a function in javascript?

I am newbie about javascript.So I do not know what is the name of I looking for and How do I do it?
After you read question if you thing question title is wrong, you should change title.
I am using console.log for debugging but this is causing error if browser IE. I made below function for this problem.
var mylog=function(){
if (devmode && window.console){
console.log(arguments);
}
};
mylog("debugging");
Now I want to use all console functions without error and I can do that as below.
var myconsole={
log:function(){
if (devmode && window.console){
console.log(arguments);
}
}
,error:function(){
if (devmode && window.console){
console.error(arguments);
}
}
...
...
...
};
But I do not want to add all console functions to myconsole object severally.
I can do that in PHP with below code.
class MyConsole
{
function __call($func,$args)
{
if ($devmode && function_exists('Console')){
Console::$func($args); // Suppose that there is Console class.
}
}
}
MyConsole::warn("name",$name);
MyConsole::error("lastname",$lastname);
This is possible with __noSuchMethod__ method but this is specific to only firefox.
Thanks for helping.
Unfortunately, you can't do that in JavaScript, the language doesn't have support for the "no such method" concept.
Two options for you:
Option 1:
Use strings for your method name, e.g.:
function myconsole(method) {
var args;
if (devmode && window.console) {
args = Array.prototype.slice.apply(arguments, 1);
window.console[method].apply(window.console, args);
}
}
Usage:
myconsole("log", "message");
myconsole("error", "errormessage");
The meat of myconsole is here:
args = Array.prototype.slice.apply(arguments, 1);
window.console[method].apply(window.console, args);
The first line copies all of the arguments supplied to myconsole except the first one (which is the name of the method we want to use). The second line retrieves the function object for the property named by the string in method from the console object and then calls it via the JavaScript apply function, giving it those arguments.
Option 2:
A second alternative came to me which is best expressed directly in code:
var myconsole = (function() {
var methods = "log debug info warn error assert clear dir dirxml trace group groupCollapsed groupEnd time timeEnd profile profileEnd count exception table".split(' '),
index,
myconsole = {},
realconsole = window.console;
for (index = 0; index < methods.length; ++index) {
proxy(methods[index]);
}
function proxy(method) {
if (!devmode || !realconsole || typeof realconsole[method] !== 'function') {
myconsole[method] = noop;
}
else {
myconsole[method] = function() {
return realconsole[method].apply(realconsole, arguments);
};
}
}
function noop() {
}
return myconsole;
})();
Then you just call log, warn, etc., on myconsole as normal.

What's the simplest approach to check existence of deeply-nested object property in JavaScript? [duplicate]

This question already has answers here:
Test for existence of nested JavaScript object key
(64 answers)
Closed 8 years ago.
I have to check deeply-nested object property such as YAHOO.Foo.Bar.xyz.
The code I'm currently using is
if (YAHOO && YAHOO.Foo && YAHOO.Foo.Bar && YAHOO.Foo.Bar.xyz) {
// operate on YAHOO.Foo.Bar.xyz
}
This works, but looks clumsy.
Is there any better way to check such deeply nested property?
If you expect YAHOO.Foo.Bar to be a valid object, but want to make your code bulletproof just in case it isn't, then it can be cleanest to just put a try catch around it and let one error handler catch any missing segment. Then, you can just use one if condition instead of four that will detect if the terminal property exists and a catch handler to catch things if the intermediate objects don't exist:
try {
if (YAHOO.Foo.Bar.xyz) {
// operate on YAHOO.Foo.Bar.xyz
} catch(e) {
// handle error here
}
or, depending upon how your code works, it might even just be this:
try {
// operate on YAHOO.Foo.Bar.xyz
} catch(e) {
// do whatever you want to do when YAHOO.Foo.Bar.xyz doesn't exist
}
I particularly use these when dealing with foreign input that is supposed to be of a particular format, but invalid input is a possibility that I want to catch and handle myself rather than just letting an exception propagate upwards.
In general, some javascript developers under-use try/catch. I find that I can sometimes replace 5-10 if statements checking input with a single try/catch around a larger function block and make the code a lot simpler and more readable at the same time. Obviously, when this is appropriate depends upon the particular code, but it's definitely worth considering.
FYI, if the usual operation is to not throw an exception with the try/catch, it can be a lot faster than a bunch of if statements too.
If you don't want to use the exception handler, you can create a function to test any arbitrary path for you:
function checkPath(base, path) {
var current = base;
var components = path.split(".");
for (var i = 0; i < components.length; i++) {
if ((typeof current !== "object") || (!current.hasOwnProperty(components[i]))) {
return false;
}
current = current[components[i]];
}
return true;
}
Example usage:
var a = {b: {c: {d: 5}}};
if (checkPath(a, "b.c.d")) {
// a.b.c.d exists and can be safely accessed
}
var _ = {};
var x = ((YAHOO.Foo || _).Bar || _).xyz;
Consider this utility function:
function defined(ref, strNames) {
var name;
var arrNames = strNames.split('.');
while (name = arrNames.shift()) {
if (!ref.hasOwnProperty(name)) return false;
ref = ref[name];
}
return true;
}
Usage:
if (defined(YAHOO, 'Foo.Bar.xyz')) {
// operate on YAHOO.Foo.Bar.xyz
}
Live demo: http://jsfiddle.net/DWefK/5/
If you need to check the correctness of the path, rather than the existance of the "xyz" member on the "YAHOO.Foo.Bar" object, it will probably be easiest to wrap the call in a try catch:
var xyz;
try {
xyz = YAHOO.Foo.Bar.xyz;
} catch (e) {
// fail;
};
Alternately, you can do some string-kong-fu-magicTM:
function checkExists (key, obj) {
obj = obj || window;
key = key.split(".");
if (typeof obj !== "object") {
return false;
}
while (key.length && (obj = obj[key.shift()]) && typeof obj == "object" && obj !== null) ;
return (!key.length && typeof obj !== "undefined");
}
The use as follows:
if (checkExists("YAHOO.Foo.Bar.xyz")) {
// Woo!
};
This problem is solved quite beautifully by coffeescript (which compiles down to javascript):
if YAHOO.Foo?.Bar?.xyz
// operate on YAHOO.Foo.Bar.xyz
use a try catch.
a={
b:{}
};
//a.b.c.d?true:false; Errors and stops the program.
try{
a.b.c.d;
}
catch(e){
console.log(e);//Log the error
console.log(a.b);//This will run
}
I actually voted to close the question as duplicate of javascript convert dotnotation string into objects.
However, I guess it's a different topic, but the answer there might still be helpful if you don't want to try-catch all the time.

Categories

Resources