[英]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中使用这些功能?
call
and apply
because they are much simpler than the alternative (depending on the use case, obviously) call
并apply
因为它们比替代方法要简单得多(显然,取决于用例) call
and apply
because the alternative does not work on objects to which we cannot assign a property (frozen or sealed) call
并apply
因为替代方案不适用于我们无法分配属性(冻结或密封)的对象 call
and apply
when the method is not supposed to be a property of the object during the evaluation of the function call
并apply
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:
但是,有时不是一种选择:
"use strict"; function showDetails() { console.log(this.name); } var obj = Object.seal({ name: 'Strawberry' }); showDetails.call(obj); // Strawberry obj.showDetails = showDetails; // fails
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
). 如果所述属性为只读(具有
defineProperty
和writable: false
),它也可能会失败。
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
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. } }
apply
and bind
apply
和bind
其他示例 There are other examples where the use of apply
or bind
is useful in case the target object already has the method: 还有其他一些示例,如果目标对象已经具有该方法,则可以使用
apply
或bind
:
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
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
参数传递给apply
, call
或bind
对该函数无效。 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.