简体   繁体   English

为什么我们需要Function.prototype.call,在这里我们可以通过将功能附加到javascript中的对象来实现相同的目的

[英]why we need Function.prototype.call , where we can achieve same thing by appending the function to object in javascript

i have seen these examples for call,apply and bind 我看过这些示例进行调用,应用和绑定

 var fruit = { name: 'Strawberry' } function showDetails(size, price) { console.log(this.name + ' ' + size + ': $' + price + '/lb') } showDetails.apply(fruit, ['small', 10]) // Strawberry small: $10/lb showDetails.call(fruit, 'small', 10) // Strawberry small: $10/lb var bound = showDetails.bind(fruit, 'small', 10) bound() //Strawberry small: $10/lb showDetails.bind(fruit, 'small', 10)() // Strawberry small: $10/lb 

here all functions do the same thing and check the below code with out using any of these(call,apply and bind) 在这里,所有函数都做同样的事情,并使用以下任何代码(调用,应用和绑定)检查以下代码

 var fruit = { name: 'Strawberry' }; function showDetails(size, price) { console.log(this.name + ' ' + size + ': $' + price + '/lb') } fruit.show =showDetails; fruit.show(small,10); //Strawberry small: $10/lb 

it worked same as expected so why ,when do we need call,apply and bind. 它的工作原理与预期的相同,所以为什么我们什么时候需要调用,应用和绑定。

how to use these functions in ES6 ? 如何在ES6中使用这些功能?

  • we need (want) call and apply because they are much simpler than the alternative (depending on the use case, obviously) 我们需要(希望) callapply因为它们比替代方法要简单得多(显然,取决于用例)
  • we need call and apply because the alternative does not work on objects to which we cannot assign a property (frozen or sealed) 我们需要callapply因为替代方案不适用于我们无法分配属性(冻结或密封)的对象
  • we need call and apply when the method is not supposed to be a property of the object during the evaluation of the function 在函数求值期间不应将方法视为对象的属性时,我们需要callapply

Also we need apply because call cannot work with a dynamic number of arguments (ignoring new spread syntax), see What is the difference between call and apply? 另外,我们还需要apply因为call不能与动态数量的参数一起使用(忽略新的扩展语法),请参阅调用和应用之间有什么区别? . And bind is a completely different beast, see Javascript call() & apply() vs bind()? 而且bind是完全不同的野兽,请参见Javascript call()&apply()vs bind()? .

Indeed, defining the method on the object will be viable alternative in many cases. 实际上,在许多情况下,在对象上定义方法将是可行的选择。 However, sometimes it is not an option: 但是,有时不是一种选择:

1. The object does not allow the method to be defined: 1.对象不允许定义方法:

 "use strict"; function showDetails() { console.log(this.name); } var obj = Object.seal({ name: 'Strawberry' }); showDetails.call(obj); // Strawberry obj.showDetails = showDetails; // fails 

2. Object already has a property with that name 2.对象已经具有该名称的属性

 function name() { console.log(this.name) } var obj = Object.seal({ name: 'Strawberry' }); name.call(obj); // Strawberry obj.name = name; obj.name(); // does not show 'Strawberry', but the function 

It could also fail if the said property is read-only (with defineProperty and writable: false ). 如果所述属性为只读(具有definePropertywritable: false ),它也可能会失败。

3. Adding the property influences the return value 3.添加属性会影响返回值

Suppose the function performs self inspection, eg it counts the number of properties it has: 假设该函数执行自我检查,例如,它计算其具有的属性数量:

 function memberCount() { return Object.keys(this).length; }; var obj = { name: 'Strawberry' }; console.log(memberCount.call(obj)); // 1 obj.count = memberCount; console.log(obj.count()); // 2 

4. Adding the property influences the remaining code 4.添加属性会影响其余代码

This is especially a problem with objects of which you expect a certain behaviour, like arrays: 对于您期望某些行为的对象(例如数组),这尤其是一个问题:

 function first() { return this[0]; }; var arr = ['Strawberry', 'Banana']; console.log(first.call(arr)); // Strawberry arr.first = first; // ... for (var i in arr) { // Iterate through array if (arr.hasOwnProperty(i)) { console.log(arr[i]); // Oops, the function appears also. } } 

Other examples for apply and bind applybind其他示例

There are other examples where the use of apply or bind is useful in case the target object already has the method: 还有其他一些示例,如果目标对象已经具有该方法,则可以使用applybind

apply may be used with methods that require separate arguments, while you just have an array of values. apply可以与需要单独参数的方法一起使用,而您只有一组值。 In ES6 you can use the spread syntax to overcome this, but traditionally, apply was the solution for this. 在ES6中,您可以使用传播语法来克服此问题,但是传统上, apply是解决此问题的方法。

For example, to get the minimum value in an array: 例如,要获取数组中的最小值:

 var arr = [5,3,1,6,2]; console.log(Math.min.apply(Math, arr)); 

The bind method is often used to pass a method as a callback, but you need it to be bound to your object: bind方法通常用于将方法作为回调传递,但是您需要将其绑定到对象:

 var obj = { flavour: 'Strawberry', smell: function () { console.log(this.flavour) } }; window.addEventListener('load', obj.smell); // ......> undefined window.addEventListener('load', obj.smell.bind(obj)); // .....>Strawberry 

ES6 Considerations ES6注意事项

Where this must be bound, there can still be use for these methods. this必须绑定,仍然可以使用这些方法。 But with the arrow function syntax, this keeps its lexical value, and passing the this argument to apply , call or bind on such function has no effect. 但是,使用arrow函数语法时, this保持其词法值,并且this参数传递给applycallbind对该函数无效。 Often it also becomes unnecessary, as that lexical this is often exactly what is needed. 通常,它也变得没有必要,因为这词汇this往往正是所需要的。

Take the example of getting the minimum value of an array. 以获取数组的最小值为例。 With ES6 it can be written as follows: 使用ES6可以编写如下:

 const arr = [5,3,1,6,2,4]; console.log(Math.min(...arr)); 

Or take an example where a method (using this ) is passed as callback: 或举一个方法(使用this )作为回调传递的示例:

 class Cls { constructor() { this.flavour = 'Strawberry' this.smell = () => console.log(this.flavour) } }; window.addEventListener('load', (new Cls).smell); // ......> Strawberry 

we can achieve same thing by appending the function to object in javascript 我们可以通过将函数附加到javascript中的对象来实现相同的目的

You are right as per your example. 按照你的例子,你是对的。 But in javascript we need to pass functions as callbacks to browser-event-loop-queue to execute async. 但是在javascript中,我们需要将函数作为回调传递给浏览器事件循环队列以执行异步。 In such cases the object will be lost. 在这种情况下,物体将丢失。 Check below example 检查下面的例子

var fruit = { name: 'Strawberry' };
function showDetails(size, price) {
  console.log(this.name + ' ' + size + ': $' + price + '/lb')
}
fruit.show =showDetails;

setTimeout(fruit.show, 100);

Here output will be undefined, so to attach the arguments and context object, we need "bind" 在这里输出将是不确定的,因此要附加参数和上下文对象,我们需要“绑定”

and now we can make above work with 现在我们可以使用

setTimeout(fruit.show.bind(fruit, size, price), 100);

Use for apply/call is to execute a function, by dynamically supplying its context and arguments. 用于apply / call的方法是通过动态提供其上下文和参数来执行一个函数。 Check follwoing usage of call. 检查呼叫的使用情况。

var Array.protoype.forEach = function(cb /*, thisArg*/){
  var T;
  if (arguments.length > 1) {
      T = arguments[1];
    }
  for(var i =0; i<this.length; i++){
    cb.call(T, this[i], i, this);
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Javascript Function.prototype.call() - Javascript Function.prototype.call() 有人可以向我解释function.prototype.call()和function.prototype = Object.create()吗? - can someone explain function.prototype.call() and function.prototype=Object.create() to me? Javascript:为什么我能在不提及原型的情况下访问Function.prototype.call? - Javascript: Why am I able to access Function.prototype.call without mentioning the prototype? 强制Javascript函数调用以调用Function.prototype.call方法 - Force Javascript function invocations to call the Function.prototype.call method 可以重载Function.prototype.call来记录所有函数调用吗? - Can Function.prototype.call be overloaded to log all function calls? 如果我们不需要JS或php的序列化方法来访问JS中的php数组,为什么还要实现它们呢? - Why do we need json or php's serialization method to access php array in JS , if we can achieve the same thing without them? Function.prototype.call在严格模式之外改变了typeof;为什么? - Function.prototype.call alters typeof this, outside strict mode; why? Javascript Function.prototype.call()传递原始值 - Javascript Function.prototype.call() pass primitive value 不能直接使用Function.prototype.call - Can't use Function.prototype.call directly 为什么我不能在带有forEach的函数数组上使用Function.prototype.call? - Why I can't use Function.prototype.call on an array of functions with forEach?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM