我使用JavaScript并在语句中遇到问题
console.log.bind(console)
Run Code Online (Sandbox Code Playgroud)
请告诉我这个陈述实际上做了什么.我已经应用了好几次,但没有做任何事情.
T.J*_*der 82
在JavaScript中,this
函数调用中被确定如何被调用的函数(正常功能,见*下文).如果它作为检索对象属性的表达式的一部分被foo.bar()
调用(例如,调用bar()
作为从中获取它的属性检索操作的一部分foo
),this
则将其设置为在调用函数期间属性所来自的对象.
假设你想要一个较短的形式console.log
,比如f
.你可以这样做:
var f = console.log; // <== Suspect!
Run Code Online (Sandbox Code Playgroud)
...但是如果log
函数依赖于在调用期间this
引用console
对象,则调用f("Message here")
将不起作用,因为this
不会引用console
.
Function#bind
就是这种情况:它允许你创建一个新函数,当被调用时,它将调用原始this
设置为你给出的值.所以
var f = console.log.bind(console); // Still suspect, for a different reason
Run Code Online (Sandbox Code Playgroud)
... 理论上,应该为您提供一个函数,f
您可以调用它来登录控制台.
除:像主机提供的功能console.log
(和alert
和getElementById
)不必须是"真正"的JavaScript函数(虽然在现代的浏览器,他们往往是,或至少非常接近),并且不要求有所有功能,包容bind
.因此,如果您在该行上收到错误,那么您使用该行的引擎可能不支持bind
该console.log
功能.
那么什么是"主机提供的功能"?未在规范中明确定义为JavaScript的一部分的任何函数,即语言.再次,在浏览器上,与浏览器相关的功能如同alert
等等console.log
.
我可以想到线路可能会给你带来麻烦的两个原因:
以上:您使用的JavaScript引擎无法发挥console.log
作用.
您正在IE上使用上面的行,并关闭了Dev Tools.在IE上,当dev工具未打开时,console
对象未定义,因此该行将抛出一个ReferenceError
.
如果最终目标是让你可以打电话,说一个函数f("Message here")
,对console.log
,这里是你如何能做到这一点对付上述两种#1和#2:
function f(item) {
if (typeof console != "undefined" && console.log) {
console.log(item);
}
}
Run Code Online (Sandbox Code Playgroud)
这只允许你给一个项目,而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";
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
......那太难看了.
*ES5添加了绑定函数,这些函数this
通过绑定附加到它们的值:
// Normal function
function foo() {
console.log(this.name);
}
// Create a bound function:
var f = foo.bind(someObject);
Run Code Online (Sandbox Code Playgroud)
你怎么打电话都没关系f
,它会foo
用this
set来调用someObject
.
*ES2015(又名ES6)增加了箭头功能.随着箭头的功能,this
是不是通过这个函数是如何调用的设置; 相反,该函数继承this
自创建它的上下文:
// Whatever `this` is here...
var f = () => { // <== Creates an arrow function
// Is what `this` will be here
};
Run Code Online (Sandbox Code Playgroud)
当您在Array#forEach
对象方法中执行某些操作时,箭头函数非常方便:
this.counter = 0;
this.someArray.forEach(entry => {
if (entry.has(/* some relevant something */)) {
++this.counter;
}
});
Run Code Online (Sandbox Code Playgroud)
关于这件事的快速更新,似乎您不再需要将控制台绑定到自己了。
Chromium 开始对console
对象进行一些深入的更改,该对象现在已经绑定到自身。https://chromium.googlesource.com/chromium/src.git/+/807ec9550e8a31517966636e6a5b506474ab4ea9
似乎所有其他浏览器都遵循了这条路径(在最新版本的 Firefox 和 Node 中进行了测试)。
我想,如果您需要与旧浏览器兼容,您仍然需要手动绑定控制台,但出于调试目的,您现在可以省略.bind(console)
:)
TJ Crowder的回答帮助我解释并解决了重定向console.log
输出的问题,但他对"无函数#应用"案例的解决方案似乎是对许多用例的任意限制.
我重写了这样的代码,它更干净,更实用:
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
console.log
用空格分隔参数,所以我也在这里复制了.这方面的主要限制是它不处理作为对象的参数.如果需要,您可以将这些字符串化.
归档时间: |
|
查看次数: |
19862 次 |
最近记录: |