Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
252 views
in Technique[技术] by (71.8m points)

javascript - What does this statement do? console.log.bind(console)

I am using JavaScript and getting a problem with the statement

console.log.bind(console)

Please tell me what does this statement actually do. I have applied this several times but it did not do anything.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

In JavaScript, this within a function call is determined by how the function is called (for normal functions, see * below). If it's called as part of an expression retrieving an object property (e.g., foo.bar() calls bar() as part of a property retrieval operation getting it from foo), this is set to the object that the property came from during the call to the function.

Suppose you wanted a shorter form of console.log, like f. You might do this:

var f = console.log; // <== Suspect!

...but if the log function relies on this referring to the console object during the call, then calling f("Message here") won't work, because this won't refer to console.

Function#bind is for just that situation: It lets you create a new function that, when called, will call the original with this set to the value you give. So

var f = console.log.bind(console); // Still suspect, for a different reason

...should, in theory, give you a function, f, that you can call to log to the console.

Except: Host-provided functions like console.log (and alert and getElementById) aren't required to be "real" JavaScript functions (although on modern browsers they tend to be, or at least very close), and aren't required to have all of their features, inculding bind. So if you're getting an error on that line, it may be that the engine you're using that line on doesn't support bind on the console.log function.

So what are "host-provided functions"? Any function not explicitly defined in the specification as being part of JavaScript, the language. So again, on a browser that's browser-related functions like alert or console.log and such.

I can think of two reasons that line might be giving you trouble:

  1. The above: You're using a JavaScript engine that doesn't make console.log a real function.

  2. You're using the line above on IE with the Dev Tools closed. On IE when the dev tools aren't open, the console object isn't defined, and so that line will throw a ReferenceError.

If the end goal is to get a function you can call, say f("Message here"), for console.log, here's how you can do that dealing with both #1 and #2 above:

function f(item) {
    if (typeof console != "undefined" && console.log) {
        console.log(item);
    }
}

That only lets you give one item, whereas console.log lets you give multiple items (console.log("this", "that", "and the other")), but if console.log may not be a real JavaScript function, then it may not have Function#apply, which makes it very hard to wrap it.

Now, if you don't care about getting the same output you'd get from console.log("this", "that", "and the other") so long as you can see what's there, simply use console.log(arguments); (arguments is the built-in identifier for all arguments passed into a function). But if you want to replicate the exact output, you end up doing something like this:

function f() {
    var a = arguments;

    if (typeof console != "undefined" && console.log) {
        if (console.log.apply) {
            // It has Function#apply, use it
            console.log.apply(console, arguments);
        } else {
            // Ugh, no Function#apply
            switch (a.length) {
                case 0: console.log(); break;
                case 1: console.log(a[0]); break;
                case 2: console.log(a[0], a[1]); break;
                case 3: console.log(a[0], a[1], a[2]); break;
                case 4: console.log(a[0], a[1], a[2], a[3]); break;
                case 5: console.log(a[0], a[1], a[2], a[3], a[4]); break;
                default:
                    throw "f() only supports up to 5 arguments";
            }
        }
    }
}

...and that's just ugly.


* ES5 added bound functions, which are functions that have their this value attached to them via binding:

// Normal function
function foo() {
    console.log(this.name);
}

// Create a bound function:
var f = foo.bind(someObject);

It doesn't matter how you call f, it will call foo with this set to someObject.

* ES2015 (aka ES6) added arrow functions. With arrow functions, this is not set by how the function is called; instead, the function inherits this from the context in which it was created:

// Whatever `this` is here...
var f = () => {                             // <== Creates an arrow function
    // Is what `this` will be here
};

Arrow functions are really handy when you're doing something like Array#forEach within an object method:

this.counter = 0;
this.someArray.forEach(entry => {
    if (entry.has(/* some relevant something */)) {
        ++this.counter;
    }
});

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...