32

我在理解这个函数时遇到了一些麻烦:

var toStr = Function.prototype.call.bind( Object.prototype.toString );
toStr([]) // [object Array]​​​​​​​​​​​​​​​​​​​​​​​​​​​

这个函数如何接受第 2 行中的参数?

4

7 回答 7

31

出色地,

  • Function.prototype.call引用“call”函数,该函数用于调用具有选定this值的函数;
  • 随后.bind指的是函数原型上的“绑定”函数(请记住:“调用”也是一个函数),它返回一个始终this设置为传入参数的新函数。
  • 传递给“bind”的参数是对象原型上的“toString”函数,因此整个表达式的结果是一个新函数,它将运行“call”函数并this设置为“toString”函数。

因此,结果类似于以下代码:Object.prototype.toString.call( param ). 然后,“console.log”调用将该函数传递给一个数组,然后就可以了。

编辑请注意,当“param”是一个对象时,这Object.prototype.toString.call( param )就像param.toString()真的一样。如果不是,则“调用”函数的语义是以 JavaScript 的正常方式(数字 -> 数字,字符串 -> 字符串等)将其转换为一个。

编辑,2016 年 5 月 24 日— 上面的最后一句话在 ES2015 中不准确。当函数调用作为值涉及时,新的 JavaScript 运行时不会“自动装箱”原始类型。this

于 2012-06-20T14:20:02.003 回答
10

我假设你已经知道做什么.call.bind做什么

toStr现在是一个基本上可以做到的功能:

function toStr( obj ) {
    return Function.prototype.call.call( Object.prototype.toString, obj );
}

即它.call.call函数,其上下文参数设置为.toString函数。通常,该部分已被处理,因为您通常将.call其用作某些函数的属性,该函数将函数设置为.call.

于 2012-06-20T14:20:18.650 回答
3

这两行代码是一个函数定义,然后是该定义的执行调用,其中传递了一个空数组。复杂性在于解释“这”将指向什么以及为什么。

为了帮助推断这个值,我将下面两个链接中的内容复制到 MDN 的调用和绑定定义。

bind () 函数创建一个新函数(绑定函数),其函数体与调用它的函数(绑定函数的目标函数)相同,并且 this 值绑定到 bind() 的第一个参数。您的代码看起来类似于绑定页面上描述的“快捷方式功能”。

var unboundSlice = Array.prototype.slice; // same as "slice" in the previous example
var slice = Function.prototype.call.bind(unboundSlice);

// ...

切片(参数);

使用call,您可以在调用现有函数时分配不同的 this 对象。this 指的是当前对象,即调用对象。通过 call,你可以编写一次方法,然后在另一个对象中继承它,而不必为新对象重写方法。

当 toStr 被调用时,它传入一个要绑定的数组,其中 this 指针被绑定。使用 bind(),这可以简化。

toStr() is a bound function to the call() function of Function.prototype, with the this value set to the toStr() function of Array.prototype. This means that additional call() calls can be eliminated.

本质上,它看起来像是 toString 方法的快捷函数覆盖。

于 2012-06-20T14:33:51.080 回答
2

bind() - 创建一个新函数,当被调用时,它本身在提供的 this 值的上下文中调用这个函数,在调用新函数时,给定的参数序列在任何提供的参数之前。

阅读此文档以获取有关 JavaScript 中的 bind() 的更多信息

角度示例:

我们定义了函数并将其绑定到对象的父组件:

public callback: object;

constructor() {
    this.callback= this.myFunction.bind(this);
}

public myFunction($event: any) {
    // Do something with $event ...
}

(父 html)将绑定的对象传递给子组件:

<child-component (callbackFunction)="callback($event)"></child-component>

接收绑定到父函数的对象的子组件:

@Output() callbackFunction: EventEmitter<object> = new EventEmitter<object>();

public childFunction() {
    ...
    this.callbackFunction.emit({ message: 'Hello!' });
    ...
}
于 2012-06-20T14:22:32.517 回答
2

JS到英文翻译——

var toStr = Function.prototype.call.bind(Object.prototype.toString);

bind创建 的新call函数Object.prototype.toString

现在您可以使用任何将应用于Object.prototype.toString.

像这样:

toStr([]) // [object Array]​​​​​​​​​​​​​​​​​​​​​​​​​

为什么不直接打电话Object.prototype.toString.call([])??

回答:

当然,你可以。但是 OPs 方法为此目的创建了一个专用的和去方法化的函数。

这真的被称为去方法化。

于 2018-04-05T16:13:14.963 回答
1

你可以这样做:

var toStr = Object.prototype.toString.call([]);

问题是:调用立即执行。你想要的是延迟调用的执行。

*由于函数在 Javascript 中也是一个对象,您可以使用任何函数作为“调用”中的第一个参数,而不是将对象作为第一个参数传递。*此外,您可以像在任何对象上一样使用调用点。

Function.prototype.call.bind( Object.prototype.toString ),复制调用函数,并将其“ this ”设置为Object.prototype.toString。您在“toStr”中保存了这个新的调用函数副本。

var toStr = Function.prototype.call.bind( Object.prototype.toString );

现在,您可以随时执行这个新的调用副本,而无需设置 'this',因为它的 'this' 已经绑定到 Object.prototype.toString 。

于 2018-06-15T11:40:34.983 回答
1
  1. 这应该对你有意义
Object.prototype.toString.call([]) //work well
  1. 你觉得这个表格太长太麻烦,你想简化吗?这使得以后使用起来更容易:
const toStr = Object.prototype.toString.call
toStr([]) // unfortunately, this does not work
  1. 您需要使用bind来更正this指向的位置。
const toStr = Object.prototype.toString.call.bind(Object.prototype.toString)
toStr([]) //work well
  1. Object.prototype.toString.callFunction.prototype.call
const toStr = Function.prototype.call.bind(Object.prototype.toString)
toStr([]) //done

概括

function f(){console.log(this, arguments)}

f.callFunction.prototype.call.bind(f)

f.call(1,2,3)Function.prototype.call.bind(f,1)(2,3)

于 2021-04-28T12:15:28.993 回答