这个语句是做什么的? console.log.bind (游戏控制台)

我正在使用 JavaScript,这个语句出现了问题

console.log.bind(console)

请告诉我这句话实际上是什么意思。我已经申请这几次,但它没有做任何事情。

32434 次浏览

在 JavaScript 中,函数调用中的 this由调用函数的 怎么做决定(对于普通函数,参见 * 下面)。如果它作为检索对象属性的表达式的一部分被调用(例如,foo.bar()调用 bar()作为从 foo获取属性的属性检索操作的一部分) ,则 this被设置为在调用函数期间属性来自的对象。

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

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

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

Function#bind只适用于这种情况: 它允许您创建一个新函数,当调用该函数时,它将调用原始函数,并将 this设置为您给出的值。那么

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

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

除了 : 主机提供的像 console.log(以及 alertgetElementById)这样的函数不需要是“真正的”JavaScript 函数(尽管在现代浏览器上它们往往是,或者至少非常接近) ,也不需要具备它们的所有特性,包括 bind。因此,如果在这一行中出现错误,可能是因为使用这一行的引擎在 console.log函数中不支持 bind

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

我能想到这句台词给你带来麻烦的两个原因:

  1. 以上内容: 您使用的 JavaScript 引擎不会使 console.log成为一个真正的函数。

  2. 你在 IE 上使用上面的代码,开发工具关闭。在 IE 上,当 dev 工具没有打开时,没有定义 console对象,因此该行将抛出一个 ReferenceError

如果最终目标是得到一个你可以调用的函数,比如说 f("Message here"),对于 console.log,你可以这样处理上面的 # 1和 # 2:

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

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

现在,如果您不关心从 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";
}
}
}
}

这太丑陋了。


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

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


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

无论你如何调用 f,它都会调用 foo,并且 this设置为 someObject

* ES2015(又名 ES6)添加了 箭头函数。对于箭头函数,this是由函数调用方式设置的 没有; 相反,函数从创建它的上下文继承 this:

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

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

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

T.J。 Crowder 的回答帮助我解释和解决了我在重定向 console.log输出时遇到的一个问题,但是他对“ no Function # application”情况的解决方案似乎武断地限制了许多用例。

我像这样重写了他的代码,这样更干净,更实用:

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.log用一个空格分隔参数,所以我在这里也复制了它。这样做的主要限制是它不处理作为对象的参数。如果需要,你可以把它们串起来。

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

通常你可以在 Promise错误处理中看到这一点(例如,从角度2快速启动) :

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

偏题部分:

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

制作一个要展开的自定义处理程序:

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


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

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

错误: 给定对象没有指定“ w: winduptype”,也没有给定目标类:
[{“ w: winduptype”: [“ FileResource”,“ ArchiveModel:”,“ WarArchiveModel”] ,... ..。

这件事的最新进展,看起来你不再需要把控制台绑定到它自己了。

Chromium 开始对 console对象进行一些深入的更改,现在它已经绑定到自己了

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

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