Javascript 在.bind和.apply中重写'this'

Javascript 在.bind和.apply中重写'this',javascript,Javascript,我读书只是为了温习一下。应用语法,我意识到我在JS知识方面存在差距: 通过使用.bind和.apply(我假设.call遵循与.apply相同的规则),可以在函数中更改this的值。所以我想知道,如果我使用.bind,然后用调用它。apply,哪个优先 所以我刚刚从w3schools中引用了这个例子并对其进行了修改: var-person={ 全名:功能(城市、国家){ 返回this.firstName+“”+this.lastName+”、“+city+”、“+country; } } 变量

我读书只是为了温习一下
。应用
语法,我意识到我在JS知识方面存在差距:

通过使用
.bind
.apply
(我假设
.call
遵循与
.apply
相同的规则),可以在函数中更改
this
的值。所以我想知道,如果我使用
.bind
,然后用
调用它。apply
,哪个优先

所以我刚刚从w3schools中引用了这个例子并对其进行了修改:

var-person={
全名:功能(城市、国家){
返回this.firstName+“”+this.lastName+”、“+city+”、“+country;
}
}
变量person1={
名字:“约翰”,
姓:“Doe”
}
变量person2={
名字:“玛丽”,
姓氏:“安妮”
}
fn=person.fullName.bind(person2);

console.log(fn.apply(person1,[“奥斯陆”,“挪威])除了实现
Function.prototype.bind
的方式外,没有任何东西可以阻止重新绑定。您是对的,调用bind后,
这个值是固定的,
函数.prototype.apply不能覆盖它

不使用
Function.prototype.bind
,您可以使用它来绑定参数:

Function.prototype.create = function(){
  const args = arguments;
  const original = this;
  return function() {
    return original.call(this, ...args, ...arguments);
  }
};
然而,修改原型可能会有问题,所以我会避免并创建一个助手函数。我相信像lodash或ramda这样的实用程序库可以做到这一点

您可以这样使用它:

const fn = function (one, two, three) {
    return this + one + two + three;
};


const boundfn = fn.create(1, 2);
const val = boundfn.call(-6, 3);

console.log({val});
没错,我们传递了
-6
作为
this
的值:)


注意:避免这样做!玩弄上下文是错误的方法,而且肯定不起作用。我会避免传递
这个
,因为它是一个不可见的参数,“更难推理”。

。bind
返回一个绑定函数。绑定函数和箭头函数将永远不会再次更改其上下文,因此您不能重新
。绑定它们或
。应用另一个上下文

如果我们假设
.bind
是用JavaScript本身编写的,这一点可能会变得更加清楚。。。然后写成:

  function bind(context, ...args) {
    const fn = this;
    return function(...args2) {
      // Note: "this" does not get accessed inside this function, so .bind ing it or .apply ing another context doesnt change anything
      return fn.call(context, ...args, ...args2);
    }
 }
根据规范:

注2:如果func是箭头函数或绑定函数,则步骤X中的函数[[Call]]将忽略thisArg

这适用于所有三个绑定函数

bind
创建一个绑定函数,该函数不是普通函数(它是一个函数),并且不包含原型


.bind
使用添加的
上下文和您想要使用的任何参数创建一个新函数,并且不可能用
应用
覆盖
调用
(除非您的
bind
方法不是本机的)已经提到了一个答案

bind()方法创建一个新函数,在调用该函数时,将其this关键字设置为提供的值,并在调用新函数时在任何提供的参数之前提供给定的参数序列

.apply
.call
允许您在调用函数时覆盖该函数的
值,但不适用于中写入的箭头或绑定函数

如果func是箭头函数或绑定函数,则函数将忽略thisArg


看起来很宽。但是是的,
.call
.apply
是相同的,除了它们如何处理thisArg后面的参数。我的意思是,我们怎么知道你做了什么和不理解什么?我们可以讨论箭头函数和使用
new
操作符调用。但也许你已经意识到了?你的问题是什么?你已经问过他们三个人了。。。声明arrow函数后是否可以重新绑定它<代码>fn=()=>{};绑定(某物)
;--这行得通吗?这些都是你可以测试或可能从文档中找到的东西。Arrow函数在其可变环境中没有
标识符。是的
函数.prototype.bind
也在使用中,但它只是预绑定
值,而此技术不预绑定
。您的助手函数很好,但它也预绑定了上下文,而我的则不,这就是OP所看到的for@mrCholo不确定他是否真的需要。本例旨在说明.bind.的可观察行为,包括OP在内的许多理性人士正在寻找一种稍后而不是更早传递上下文的方法。我知道解决方案b/c,很明显,我在两年前或其他时候遇到过同样的问题。@Cholo先生,这与许多理性的人使用什么无关。OP要求解释该行为。在纯JavaScript中写出
bind
的功能可能有助于实现这一目标;我不认为call/apply可以创建任何函数,不管是否有异国情调。
  function bind(context, ...args) {
    const fn = this;
    return function(...args2) {
      // Note: "this" does not get accessed inside this function, so .bind ing it or .apply ing another context doesnt change anything
      return fn.call(context, ...args, ...args2);
    }
 }