首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在Javascript中绑定已绑定函数的更多参数

在Javascript中绑定已绑定函数的更多参数
EN

Stack Overflow用户
提问于 2014-01-05 02:44:50
回答 3查看 29.2K关注 0票数 31

我试着整理一下我对javascript的bind()如何工作的想法。

我知道如果我这样做的话

代码语言:javascript
复制
var f = function (a) { ... }
var g = f.bind(obj);
g(1)

然后调用f,其中obj作为this1作为a

我认为g是f的一个包装函数。

但当我这么做的时候

代码语言:javascript
复制
var f = function (a) { ... }
var g = f.bind(obj);
g.call(1)

然后调用f,并将1作为this,而a未定义。

因此,似乎g不仅仅是一个简单的包装器,而是call以某种方式区分了正常函数和绑定函数。

还有一件事是,我不能多次局部应用一个函数。

代码语言:javascript
复制
var f = function (a) { ... }
var g = f.bind(obj);
var h = g.bind(1);
h();

然后调用f,并将obj作为this,而a未定义。

此行为的原因是什么?

编辑

这个问题中的构造实际上是错误的,关于它们应该是什么样子,请参阅公认的答案(一般来说,我没有注意到callbind总是需要上下文参数作为第一个参数)。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-01-05 02:55:09

一旦使用bind将对象绑定到函数,就不能覆盖它。正如您在MDN documentation中看到的,它在规范中写得很清楚

“bind()函数创建一个新函数(绑定函数),其函数体( ECMAScript 5术语中的内部调用属性)与它要调用的函数(绑定函数的目标函数)具有相同的函数体,并将this值绑定到bind()的第一个参数,该值不能被重写。__”

这也意味着,如果你这样做了:

代码语言:javascript
复制
g.call(1);

在遵循规范的浏览器上,你会得到this格式的obj,而不是1格式的。

当然,您可以绑定多个参数,因此:

代码语言:javascript
复制
var sum = function(a, b, c) { return a + b + c };
var sumAB = sum.bind(null, 1, 5);
var sumC = sumAB.bind(null, 2);

console.log(sumC());

但是context对象将始终是使用第一个bind指定的对象,因为它不能被覆盖。

为了避免混淆,call的第一个参数是上下文对象(this),然后您将拥有其余的参数。

这意味着:

代码语言:javascript
复制
var obj = { foo: function(bar) { console.log(bar) } };

obj.foo('hello');

// equivalent to:
var foo = obj.foo;

foo.call(obj, 'hello');

希望能有所帮助。

票数 51
EN

Stack Overflow用户

发布于 2014-01-05 02:52:04

您从未传递过任何参数-您只设置了上下文。call的第一个参数作为上下文(this)接收,参数2之后的参数作为被调用函数的参数1和更高的参数接收。同时,bind创建一个具有新上下文的新函数-参数在被调用时被传递。

下面是将1作为函数f的参数a传递给第一个代码块的方法:

代码语言:javascript
复制
f( 1 );
g( 1 );
g.call( this, 1 );
g.apply( this, [ 1 ] );
票数 3
EN

Stack Overflow用户

发布于 2021-10-27 19:53:41

Function.prototype.call()

使用call()方法,您可以编写可在不同对象上使用的方法。换句话说,通过call(),一个对象可以使用属于另一个对象的方法。More information

代码语言:javascript
复制
const person = {
  fullName: function() {
    return this.firstName + " " + this.lastName;
  }
}
const person1 = {
  firstName:"John",
  lastName: "Doe"
}
const person2 = {
  firstName:"Mary",
  lastName: "Doe"
}

// This will return "John Doe":
console.log(person.fullName.call(person1));

call()允许为另一个对象分配和调用属于一个对象的函数/方法。

call()为函数/方法提供了一个新的值。使用call(),您可以只编写一次方法,然后在另一个对象中继承它,而不必为新对象重写该方法。

>使用调用来链接对象的构造函数

您可以使用call来链接对象的构造函数(类似于Java)。

在下面的示例中,使用两个参数定义Product对象的构造函数: name和price。

另外两个函数,食品和玩具,调用Product,传递this、name和price。Product初始化属性名称和价格,这两个专门的函数定义类别。

代码语言:javascript
复制
function Product(name, price) {
  this.name = name;
  this.price = price;
}

function Food(name, price) {
  Product.call(this, name, price);
  this.category = 'food';
}

function Toy(name, price) {
  Product.call(this, name, price);
  this.category = 'toy';
}

const cheese = new Food('feta', 5);
const fun = new Toy('robot', 40);
console.log(cheese);
console.log(fun);

>使用call调用匿名函数

在这个例子中,我们创建了一个匿名函数,并使用call在数组中的每个对象上调用它。

这里的匿名函数的主要目的是向每个对象添加一个print函数,该函数能够打印数组中对象的正确索引。

代码语言:javascript
复制
const animals = [
  { species: 'Lion', name: 'King' },
  { species: 'Whale', name: 'Fail' }
];

for (let i = 0; i < animals.length; i++) {
  (function(i) {
    this.print = function() {
      console.log('#' + i + ' ' + this.species
                  + ': ' + this.name);
    }
    this.print();
  }).call(animals[i], i);
}

>使用call调用函数并指定'this‘的上下文

在下面的示例中,当我们调用greet时,它的值将被绑定到对象obj。

代码语言:javascript
复制
function greet() {
  const reply = [this.animal, 'typically sleep between', this.sleepDuration].join(' ');
  console.log(reply);
}

const obj = {
  animal: 'cats', sleepDuration: '12 and 16 hours'
};

greet.call(obj);  // cats typically sleep between 12 and 16 hours

>使用call调用函数,而不指定第一个参数

在下面的示例中,我们在不传递第一个参数的情况下调用display函数。如果没有传递第一个参数,则该参数的值将绑定到全局对象。

代码语言:javascript
复制
var sData = 'Wisen';

function display() {
  console.log('sData value is %s ', this.sData);
}

display.call();  // sData value is Wisen

注意:在严格模式下,它的值是未定义的。见下文。

代码语言:javascript
复制
'use strict';

var sData = 'Wisen';

function display() {
  console.log('sData value is %s ', this.sData);
}

display.call(); // Cannot read the property of 'sData' of undefined

欲了解更多信息,请访问reference

Function.prototype.bind()

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

代码语言:javascript
复制
const module = {
  x: 42,
  getX: function() {
    return this.x;
  }
};

const unboundGetX = module.getX;
console.log(unboundGetX()); // The function gets invoked at the global scope
// expected output: undefined

const boundGetX = unboundGetX.bind(module);
console.log(boundGetX());
// expected output: 42

>创建绑定函数

bind()最简单的用法是创建一个函数,无论它是如何调用的,都可以使用特定的this值进行调用。

对于新的JavaScript程序员来说,一个常见的错误是从对象中提取一个方法,然后调用该函数,并期望它使用原始对象作为它的this (例如,通过在基于回调的代码中使用该方法)。

然而,如果没有特别的注意,原始对象通常会丢失。使用原始对象从函数创建绑定函数,巧妙地解决了这个问题:

代码语言:javascript
复制
this.x = 9;    // 'this' refers to global 'window' object here in a browser
const module = {
  x: 81,
  getX: function() { return this.x; }
};

module.getX();
//  returns 81

const retrieveX = module.getX;
retrieveX();
//  returns 9; the function gets invoked at the global scope

//  Create a new function with 'this' bound to module
//  New programmers might confuse the
//  global variable 'x' with module's property 'x'
const boundGetX = retrieveX.bind(module);
console.log(boundGetX());
//  returns 81

>部分应用的函数

bind()的下一个最简单的用法是创建一个具有预先指定的初始参数的函数。

这些参数(如果有)跟在提供的this值之后,然后插入到传递给目标函数的参数的开头,后面是调用时传递给绑定函数的任何参数。

代码语言:javascript
复制
function list() {
  return Array.prototype.slice.call(arguments);
}

function addArguments(arg1, arg2) {
  return arg1 + arg2;
}

const list1 = list(1, 2, 3);
//  [1, 2, 3]

const result1 = addArguments(1, 2);
//  3

// Create a function with a preset leading argument
const leadingThirtysevenList = list.bind(null, 37);

// Create a function with a preset first argument.
const addThirtySeven = addArguments.bind(null, 37);

const list2 = leadingThirtysevenList();
//  [37]

const list3 = leadingThirtysevenList(1, 2, 3);
//  [37, 1, 2, 3]

const result2 = addThirtySeven(5);
//  37 + 5 = 42

const result3 = addThirtySeven(5, 10);
//  37 + 5 = 42
//  (the second argument is ignored)

>使用setTimeout()

默认情况下,在setTimeout()中,this关键字将被设置为window (或全局)对象。当使用需要它来引用类实例的类方法时,您可以显式地将它绑定到回调函数,以便维护实例。

代码语言:javascript
复制
function LateBloomer() {
  this.petalCount = Math.floor(Math.random() * 12) + 1;
}

// Declare bloom after a delay of 1 second
LateBloomer.prototype.bloom = function() {
  window.setTimeout(this.declare.bind(this), 1000);
};

LateBloomer.prototype.declare = function() {
  console.log(`I am a beautiful flower with ${this.petalCount} petals!`);
};

const flower = new LateBloomer();
flower.bloom();
//  after 1 second, calls 'flower.declare()'

如果您想了解有关绑定方法的更多信息,请阅读this resource

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20925138

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档