我正在使用JavaScript并且语句
出现问题console.log.bind(console)
请告诉我这个陈述实际上做了什么。我已经应用了几次,但没有做任何事情。
答案 0 :(得分:77)
在JavaScript中,函数调用中的this
由如何调用函数决定(对于普通函数,请参阅下面的*)。如果它作为检索对象属性的表达式的一部分被调用(例如,foo.bar()
调用bar()
作为从foo
获取它的属性检索操作的一部分,则设置this
在调用函数期间,属性所来自的对象。
假设您需要console.log
的缩写形式,例如f
。你可以这样做:
var f = console.log; // <== Suspect!
...但如果log
函数在调用期间依赖于this
引用console
对象,则调用f("Message here")
将无效,因为{{ 1}}不会引用this
。
console
适用于这种情况:它允许您创建一个新函数,在调用时,将调用原始函数,并将Function#bind
设置为您提供的值。所以
this
理论上, ... 应该为您提供一个函数var f = console.log.bind(console); // Still suspect, for a different reason
,您可以调用它来登录控制台。
除外:主机提供的功能如f
(以及console.log
和alert
)不需要是“真正的”JavaScript功能(尽管在现代浏览器往往是,或者至少非常接近,并且不需要具有所有功能,包括getElementById
。因此,如果您在该行上收到错误,那么您使用该行的引擎可能不支持bind
函数上的bind
。
那么“主机提供的功能”是什么?任何未在规范中明确定义为 JavaScript (语言)一部分的函数。同样,在浏览器上使用与console.log
或alert
等浏览器相关的功能。
我可以想到线路可能给你带来麻烦的两个原因:
上述内容:您正在使用的JavaScript引擎不会使console.log
成为真正的功能。
您正在IE上使用上面的行并关闭了Dev Tools。在IE上,当dev工具未打开时,console.log
对象未定义,因此该行将抛出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;
}
});
答案 1 :(得分:5)
T.J。 Crowder的回答帮助我解释并解决了重定向console.log
输出时遇到的问题,但他的解决方案是#34; no Function#apply&#34;案件似乎是对许多用例的任意限制。
我重写了他的代码,这个代码更清洁,更实用:
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
用空格分隔参数,所以我也在这里复制了。这方面的主要限制是它不处理作为对象的参数。如果需要,您可以将这些字符串化。
答案 2 :(得分:2)
关于此问题的快速更新,您似乎不再需要将控制台绑定到自身。
Chromium开始在console
对象上进行一些深层次的更改,现在已经绑定了它。 https://chromium.googlesource.com/chromium/src.git/+/807ec9550e8a31517966636e6a5b506474ab4ea9
似乎所有其他浏览器都遵循此路径(在最新版本的Firefox和Node中测试过)。
我想,如果您需要与旧浏览器兼容,您仍然需要手动绑定控制台,但出于调试目的,您现在可以省略.bind(console)
:)
答案 3 :(得分:0)
我敢于推测,这是许多人可能想要的:
通常你可以在Promise
错误处理中看到这一点(例如,从Angular 2快速入门):
System.import("unmarshaller/Unmarshaller.js").then(null, console.error.bind(console));
正如其他答案中所述,它将console.error
函数作为错误处理程序,而bind(console)
使其使用console
作为其中this
的值&# 39;身体。否则,this
将被设置为全局对象(浏览器中为window
),并且调用将失败。很好地解释了here。
offtopic部分:
您可能想要创建自己的处理程序来预处理错误。在上面的示例中,console.error
在控制台中打印丑陋的Error
,因为SystemJS
仅告诉&#34;加载Unmarshaller.js&#34; 时出错。另一个错误隐藏在originalErr
。
制作一个自定义处理程序来解包:
function handleError(e) {
if (e.originalErr)
throw e.originalErr;
throw e;
}
System.import("unmarshaller/Unmarshaller.js").then(null, handleError);
不需要.bind()
,并会为您提供最初抛出的Error
,例如:
错误:给定对象没有指定&#34; w:winduptype&#34;并且没有给出目标类:
[{&#34; w:winduptype&#34;:[&#34; FileResource&#34;,&#34; ArchiveModel:&#34;,&#34; WarArchiveModel&#34;],...