Javascript 这个声明有什么作用?console.log.bind(控制台)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28668759/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 02:13:14  来源:igfitidea点击:

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

javascript

提问by shubham

I am using JavaScript and getting a problem with the statement

我正在使用 JavaScript 并且语句出现问题

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.

请告诉我这个声明实际上是做什么的。我已经应用了几次,但它没有做任何事情。

回答by T.J. Crowder

In JavaScript, thiswithin a function call is determined by howthe 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), thisis set to the object that the property came from during the call to the function.

在JavaScript中,this函数调用中被确定如何被调用的函数(正常功能,见*下文)。如果它作为检索对象属性的表达式的一部分被foo.bar()调用(例如,bar()作为从 获取它的属性检索操作的一部分调用foo),this则设置为在调用函数期间该属性来自的对象。

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

假设你想要一个更短的形式console.log,比如f。你可以这样做:

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

...but if the logfunction relies on thisreferring to the consoleobject during the call, then calling f("Message here")won't work, because thiswon't refer to console.

...但是如果log函数在调用期间依赖于this引用console对象,那么调用f("Message here")将不起作用,因为this不会引用console.

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

Function#bind仅适用于这种情况:它允许您创建一个新函数,该函数在调用时将调用原始函数并this设置为您提供的值。所以

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.

...理论上,应该给你一个函数,f,你可以调用它来登录到控制台。

Except: Host-provided functions like console.log(and alertand 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 bindon the console.logfunction.

除了:主机提供的函数console.log(和alertgetElementById)不需要是“真正的”JavaScript 函数(尽管在现代浏览器上它们往往是,或者至少非常接近),并且不需要具有它们的所有功能,包括bind。因此,如果您在该行上遇到错误,则可能是您在该行上使用的引擎不支持bindconsole.log功能。

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 alertor console.logand such.

那么什么是“主机提供的功能”?规范中未明确定义为JavaScript一部分的任何函数,该语言。再说一次,在浏览器上有浏览器相关的功能,比如alert或者console.log等等。

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.loga 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 consoleobject isn't defined, and so that line will throw a ReferenceError.

  1. 上图:您使用的 JavaScript 引擎无法实现console.log真正的功能。

  2. 您在关闭开发工具的情况下在 IE 上使用上面的行。在 IE 上,当开发工具未打开时,console对象未定义,因此该行将抛出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:

如果最终目标是获得一个您可以调用的函数,例如f("Message here"), for console.log,那么您可以如何处理上面的 #1 和 #2:

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

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

这只能让你给出一个项目,而console.log让你给出多个项目 ( console.log("this", "that", "and the other")),但如果它console.log可能不是一个真正的 JavaScript 函数,那么它可能没有Function#apply,这使得包装它变得非常困难。

Now, if you don't care about getting the sameoutput 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);(argumentsis 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:

现在,如果您不关心获得相同的输出console.log("this", "that", "and the other"),只要您能看到那里的内容,只需使用console.log(arguments);(arguments是传递给函数的所有参数的内置标识符)。但是如果你想复制确切的输出,你最终会做这样的事情:

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 thisvalue attached to them via binding:

* ES5 添加了绑定函数,这些函数是this通过绑定将其值附加到它们的函数:

// 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 foowith thisset to someObject.

这不要紧,你怎么称呼f,它会调用foothis设置为someObject

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

* ES2015(又名 ES6)添加了箭头函数。随着箭头的功能,this不是通过这个函数是如何调用的设置; 相反,该函数this从创建它的上下文继承:

// 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#forEachwithin an object method:

当您在Array#forEach对象方法中执行类似操作时,箭头函数非常方便:

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

回答by Mordred

T.J. Crowder's answer helped me explain and solve a problem I had with redirecting console.logoutput, but his solution for the "no Function#apply" case seemed arbitrarily limiting for many use-cases.

TJ Crowder 的回答帮助我解释并解决了我在重定向console.log输出时遇到的问题,但他对“无函数#apply”案例的解决方案似乎对许多用例有任意限制。

I rewrote his code like this which is a little cleaner and more functional:

我像这样重写了他的代码,它更简洁,功能更强大:

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
            var output = '';
            for (i=0;i<arguments.length;i++) {
                output += arguments[i] + ' ';
            }
            console.log(output);
        }
    }
}

console.logseparates arguments with a space, so I replicated that here as well. The primary limitation for this is that it does not handle arguments that are objects. You can stringify those if needed.

console.log用空格分隔参数,所以我也在这里复制了它。对此的主要限制是它不处理作为对象的参数。如果需要,您可以将这些字符串化。

回答by atomrc

Quick update on this matter, it seems that you don't need to bind the console to itself anymore.

关于这件事的快速更新,似乎您不再需要将控制台绑定到自己了。

Chromium started rolling out some deep changes on the consoleobject, which is now already bound to itself. https://chromium.googlesource.com/chromium/src.git/+/807ec9550e8a31517966636e6a5b506474ab4ea9

Chromium 开始对console对象进行一些深入的更改,该对象现在已经绑定到自身。https://chromium.googlesource.com/chromium/src.git/+/807ec9550e8a31517966636e6a5b506474ab4ea9

It also seems that all the other browsers have followed this path (tested on recent version of Firefox and in Node).

似乎所有其他浏览器都遵循了这条路径(在最新版本的 Firefox 和 Node 中进行了测试)。

I guess, if you need to be compatible with old browsers, you would still need to manually bind the console, but for debug purposes, you can now omit the .bind(console):)

我想,如果您需要与旧浏览器兼容,您仍然需要手动绑定控制台,但出于调试目的,您现在可以省略.bind(console):)

回答by Ondra ?i?ka

As stated in other answers, it gives the console.errorfunction as the error handler, and bind(console)makes it use the consoleas the value of thiswithin it's body. Otherwise, thiswould be set to a global object (windowin browsers) and the call would fail. Well explained here.

正如其他答案中所述,它将console.error函数作为错误处理程序,并bind(console)使其console用作this其主体内的值。否则,this将设置为全局对象(window在浏览器中)并且调用将失败。在这里解释得很好。

Often you can see this in Promiseerror handling (for example, from the Angular 2 quickstart):

通常您可以在Promise错误处理中看到这一点(例如,从 Angular 2 快速入门):

System.import("unmarshaller/Unmarshaller.js").then(null, console.error.bind(console));

The offtopic part:

题外话部分:

You may want to create your own handler to pre-process the error. In the above example, console.errorprints ugly Errorin the console because SystemJSonly tells that "Error loading Unmarshaller.js". And the other error is hidden in originalErr.

您可能希望创建自己的处理程序来预处理错误。在上面的例子中,在控制台console.error打印丑陋Error,因为SystemJS只告诉“错误加载 Unmarshaller.js”。另一个错误隐藏在originalErr.

Make a custom handler to unwrap:

制作一个自定义处理程序来解包:

function handleError(e) {
    if (e.originalErr)
        throw e.originalErr;
    throw e;
}

System.import("unmarshaller/Unmarshaller.js").then(null, handleError);

No need for .bind(), and will give you the Errororiginally thrown, like:

不需要.bind(),并且会给你Error最初抛出的,比如:

Error: Given object doesn't specify "w:winduptype" and no target class given:
[{"w:winduptype":["FileResource","ArchiveModel:","WarArchiveModel"], ...

错误:给定对象未指定“w:winduptype”且未给出目标类:
[{"w:winduptype":["FileResource","ArchiveModel:","WarArchiveModel"], ...