2015-02-23 279 views
33

我使用JavaScript和得到一个问题的声明这句话有什么作用? console.log.bind(控制台)

console.log.bind(console) 

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

+4

https://developer.mozilla.org/ en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind – zerkms 2015-02-23 07:29:08

+0

http://stackoverflow.com/questions/20723602/bind-event-handler-to-console-log-javascript-event – 2015-02-23 07:29:35

+0

Function.bind( )从IE8中丢失,但应该在实际情况下正常工作owsers。如果有疑问,请张贴破碎的代码。 – dandavis 2015-02-23 07:32:52

回答

59

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

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

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

...但如果log功能依赖于this在通话过程中参照console对象,然后调用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函数(虽然在现代的浏览器,他们往往是,或至少非常接近),以及AREN要求具备所有功能,包括bind。因此,如果您在该行发生错误,可能是因为您使用该行的引擎不支持console.log函数上的bind

那么“主机提供的功能”是什么?任何在规范中没有明确定义的作为JavaScript的一部分的语言。所以再次,在浏览器相关的功能,如alertconsole.log等等。

我能想到的原因有二该行可能给你的麻烦:

  1. 以上:你正在使用的JavaScript引擎,这并不使console.log真正的功能。

  2. 在开发工具关闭的情况下,您正在使用IE上面的行。在IE上,当开发工具未打开时,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,它会调用foothis设置为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; 
    } 
}); 
+0

哇!人们显然喜欢这个答案,但我不明白它是如何回答OP问题的?也许我只是很愚蠢,但它似乎是对一堆外围的实际问题产生影响(就像其他答案一样)。 – geoidesic 2016-10-25 12:07:00

+3

@geoidesic:它直接回答以下问题:*“So'var f = console.log.bind(console);'理论上应该给你一个函数'f',你可以调用它来登录到控制台。“它也解释了为什么它这么做,为什么你需要这样做,而不是仅仅是'var f = console.log'(这是'this'进入它的地方),以及它是如何工作的,具体取决于主机实现。 – 2016-10-25 12:11:01

+0

@ T.J.Crowder谢谢你的回答。我正在使用Typescript/Angular中的'console.log.bind'作为记录器,在控制台中打印一些东西,并且链接到记录器被调用的类的链接,而不是在Logger类本身中,就像没有'bind'一样。不幸的是,我不能传递第二个参数来绑定,例如'console.log.bind(console,'background:#222; color:#bada55');'只会将第二个参数作为字符串打印出来,而不是将其应用于控制台。我该如何解决? – Phil 2017-05-18 12:22:32

4

T.J.克劳德的回答帮助我解释并解决了重定向console.log输出时遇到的一个问题,但是他对于“no Function#apply”案例的解决方案对于许多使用案例似乎是任意限制的。

我改写了他的代码,这样这是一个小更清洁,更功能:

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用空格分隔参数,所以我复制的,在这里为好。对此的主要限制是它不处理作为对象的参数。如果需要,你可以将这些字符串串联起来

0

我不敢推测,这是许多人可能会寻找什么:

通常你可以看到这个Promise错误处理(例如,从角2快速入门):

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

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

的offtopic部分:

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

创建自定义处理程序,以解开:

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

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

无需.bind(),并且会给你Error最初抛出,如:

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

+2

这似乎没有试图回答这个问题。它没有描述“console.error.bind(console)”的含义,它只提供了一个替代方案(其行为在几个重要方面有所不同),用于一个非常具体的用例(这个问题根本没有提到)。 – Quentin 2016-10-07 14:15:05

+0

这就是你对这个问题的看法,这本身就很模糊。重复其他答案没有意义。虽然改为更一般。 – 2016-10-07 16:10:59