在下面的代码中function.apply.bind是如何工作的

How does function.apply.bind work in the following code?

本文关键字:何工作 工作 bind 代码 function apply 在下面      更新时间:2023-09-26

所以我得到一个数组[200,599]是从承诺返回的,并且内部的回调函数被传递给function .apply。但现在我迷路了。数组[200,599]是如何分成x和y的?具体如何应用。绑定的工作吗?

function getY(x) {
        return new Promise( function(resolve,reject){
            setTimeout( function(){
                resolve( (3 * x) - 1 );
            }, 100 );
        } );
    }
function foo(bar,baz) {
    var x = bar * baz;
    // return both promises
    return [
        Promise.resolve( x ),
        getY( x )
    ];
}
function spread(fn) {
    return Function.apply.bind( fn, null );
}
Promise.all(
    foo( 10, 20 )
)
.then(
    spread( function(x,y){
        console.log( x, y );    // 200 599
    } )
)

.apply()是函数对象的方法。像这样:

console.log(Math.max.apply(null, [1, 2, 3])); // 3

.apply()接受两个参数,上下文(将成为目标函数中的this)和参数的可迭代对象(通常是数组,但arguments数组也可以)。


.bind()是函数对象的方法。像这样:

const x = {
  foo: function() {
    console.log(this.x);
  },
  x: 42
}
var myFoo = x.foo.bind({x: 5});
x.foo(); // 42
myFoo(); // 5

.bind()接受上下文(即后来的this)和可选的附加参数,并返回一个新的函数,上下文被绑定,附加参数被锁定


由于.apply()本身是一个函数,因此它可以与.bind()绑定,如下所示:

Function.prototype.apply.bind(fn, null);

意味着.apply()this将是fn, .apply()的第一个参数将是null。这意味着它看起来像这样:

fn.apply(null, args)

Spread接受一个函数并绑定apply方法,部分应用null参数。总之,

spread(fn)

转换为

args => fn.apply(null, args)

与使用ES6扩展语法

相同
args => fn(...args)

函数名的来源


如果你想要一个长答案,记住bind是怎么做的:

method.bind(context, ...args1)

返回一个类似于

的函数
(...args2) => method.call(context, ...args1, ...args2)

在本例中,methodapply, contextfn,第一个参数是null,所以调用

Function.apply.bind( fn, null )

将创建一个类似于

的函数
(...args2) => (Function.apply).call(fn, null, ...args2)

,这相当于上面的fn.apply(…)调用,因为apply是在两次访问中继承自Function.prototype的方法。

扩展函数只是一个实用函数,用于将数组转换为传递给函数的参数。apply进行转换,bind将其绑定到调用函数,以便"this"上下文连接到相同的函数。

以更简单的形式查看spread是如何工作的->

spread(function (x,y){console.log(x,y);})([1,2])

你将得到答案,1 2,因为1被传递给x, 2被传递给y。

在你的例子中,你的承诺。All返回一个已解决的承诺数组。然后将它们映射为函数(x,y)的参数。

它工作的原因是apply的"解构"性质(如果给定一个值数组,它们将被提供给您使用apply on的函数)。

现在回到你的代码时调用绑定应用,返回的值是一个函数,它返回相同的函数提供给bind,唯一不同的是,当执行它将使用apply调用(与数组作为thisArg在你的情况下),但它不会被执行,直到你调用它。在您的示例中,当promise被解析后,提供给then的函数将与Promise解析提供的参数数组一起执行。

function spread(fn){
   let boundedFn = fn.bind(fn)
   return function(arg){
      return boundedFn.apply(null,arg)
   }
}
   
spread((x, y, c) => console.log(x, y, c))([1,2,3])
// or
Promise.resolve([6, 5]).then(spread((a, b) => console.log(a, b)))

bind提供(在您的代码中)null作为第二个参数的原因是为了防止调用者提供的数组被提供给apply作为其第一个参数,它保留给this