javascript type 電話和申請有什麼區別?




js function prototype (16)

使用callapply來調用函數有什麼區別?

var func = function() {
  alert('hello!');
};

func.apply(); vs func.call();

上述兩種方法之間是否存在性能差異? 什麼時候最好使用call over apply ,反之亦然?


不同之處在於apply允許您使用arguments作為數組調用函數; call需要顯式列出參數。 一個有用的助記符是A for a rray and C for c omma。”

有關applycall請參閱MDN的文檔。

偽語法:

theFunction.apply(valueForThis, arrayOfArgs)

theFunction.call(valueForThis, arg1, arg2, ...)

從ES6開始,還可以spread陣列以便與call函數一起使用,您可以在here看到兼容性。

示例代碼:

function theFunction(name, profession) {
    console.log("My name is " + name + " and I am a " + profession +".");
}
theFunction("John", "fireman");
theFunction.apply(undefined, ["Susan", "school teacher"]);
theFunction.call(undefined, "Claude", "mathematician");
theFunction.call(undefined, ...["Matthew", "physicist"]); // used with the spread operator


這是一篇小帖子,我寫道:

http://sizeableidea.com/call-versus-apply-javascript/

var obj1 = { which : "obj1" },
obj2 = { which : "obj2" };

function execute(arg1, arg2){
    console.log(this.which, arg1, arg2);
}

//using call
execute.call(obj1, "dan", "stanhope");
//output: obj1 dan stanhope

//using apply
execute.apply(obj2, ["dan", "stanhope"]);
//output: obj2 dan stanhope

//using old school
execute("dan", "stanhope");
//output: undefined "dan" "stanhope"

我們可以區分呼叫和應用方法如下

CALL:具有參數的函數單獨提供。 如果你知道要傳遞的參數或者沒有傳遞參數,你可以使用call。

APPLY:使用作為數組提供的參數調用函數。 如果您不知道有多少參數將傳遞給函數,則可以使用apply。

使用apply over call有一個優點,我們不需要更改參數的數量,只有我們可以更改傳遞的數組。

性能沒有太大差異。 但是我們可以說調用比應用更快一點,因為數組需要在apply方法中進行評估。


這些方法之間的區別在於,您希望如何傳遞參數。

“A for array和C for comma”是一個方便的助記符。


雖然這是一個古老的話題,但我只想指出.call比.apply略快。 我無法確切地告訴你原因。

請參閱jsPerf, http://jsperf.com/test-call-vs-apply/3 //jsperf.com/test-call-vs-apply/3

[ UPDATE! ]

Douglas Crockford簡要提到了兩者之間的差異,這可能有助於解釋性能差異...... http://youtu.be/ya4UHuXNygM?t=15m52s

Apply接受一組參數,而Call接受零個或多個單獨的參數! 啊哈!

.apply(this, [...])

.call(this, param1, param2, param3, param4...)


主要區別在於,使用call,我們可以正常更改範圍和傳遞參數,但apply允許您使用參數作為Array調用它(將它們作為數組傳遞)。 但就他們在你的代碼中做什麼而言,它們非常相似。

雖然這個函數的語法幾乎與apply()的語法相同,但根本區別在於call()接受一個參數列表,而apply()接受一個參數數組。

如你所見,沒有太大的區別,但仍有一些情況我們更喜歡使用call()或apply()。 例如,查看下面的代碼,使用apply方法從MDN中查找數組中的最小和最大數字:

// min/max number in an array
var numbers = [5, 6, 2, 3, 7];

// using Math.min/Math.max apply
var max = Math.max.apply(null, numbers); 
// This about equal to Math.max(numbers[0], ...)
// or Math.max(5, 6, ...)

var min = Math.min.apply(null, numbers)

所以主要區別在於我們傳遞參數的方式:

呼叫:

function.call(thisArg, arg1, arg2, ...);

應用:

function.apply(thisArg, [argsArray]);

Call,Apply和Bind的另一個例子。 Call和Apply之間的區別很明顯,但Bind的工作方式如下:

  1. 綁定返回可以執行的函數的實例
  2. 第一個參數是' this '
  3. 第二個參數是以逗號分隔的參數列表(如Call

}

function Person(name) {
    this.name = name; 
}
Person.prototype.getName = function(a,b) { 
     return this.name + " " + a + " " + b; 
}

var reader = new Person('John Smith');

reader.getName = function() {
   // Apply and Call executes the function and returns value

   // Also notice the different ways of extracting 'getName' prototype
   var baseName = Object.getPrototypeOf(this).getName.apply(this,["is a", "boy"]);
   console.log("Apply: " + baseName);

   var baseName = Object.getPrototypeOf(reader).getName.call(this, "is a", "boy"); 
   console.log("Call: " + baseName);

   // Bind returns function which can be invoked
   var baseName = Person.prototype.getName.bind(this, "is a", "boy"); 
   console.log("Bind: " + baseName());
}

reader.getName();
/* Output
Apply: John Smith is a boy
Call: John Smith is a boy
Bind: John Smith is a boy
*/

摘要:

call()apply()都是位於Function.prototype 。 因此,它們可以通過原型鏈在每個功能對像上使用。 call()apply()都可以執行具有指定值的函數。

call()apply()之間的主要區別在於您必須將參數傳入其中。 在call()apply() ,作為第一個參數傳遞要作為this值的對象。 其他參數在以下方面有所不同:

  • 使用call()您必須正常放入參數(從第二個參數開始)
  • 使用apply()您必須傳遞參數數組。

例:

let obj = {
  val1: 5,
  val2: 10
}

const summation = function (val3, val4) {
  return  this.val1 + this.val2 + val3 + val4;
}

console.log(summation.apply(obj, [2 ,3]));
// first we assign we value of this in the first arg
// with apply we have to pass in an array


console.log(summation.call(obj, 2, 3));
// with call we can pass in each arg individually

為什麼我需要使用這些功能?

this值有時候在javascript中很棘手。 執行函數時確定的值不是在定義函數時確定的。 如果我們的函數依賴this綁定,我們可以使用call()apply()來強制執行此行為。 例如:

var name = 'unwantedGlobalName';

const obj =  {
  name: 'Willem',
  sayName () { console.log(this.name);}
}


let copiedMethod = obj.sayName;
// we store the function in the copiedmethod variable



copiedMethod();
// this is now window, unwantedGlobalName gets logged

copiedMethod.call(obj);
// we enforce this to be obj, Willem gets logged


調用和應用兩者用於在執行函數時強制this值。 唯一的區別是call需要n+1參數,其中1是this'n' argumentsapply只接受兩個參數,一個是另一個是參數數組。

我在apply over call看到的優點是我們可以輕鬆地將函數調用委託給其他函數;

function sayHello() {
  console.log(this, arguments);
}

function hello() {
  sayHello.apply(this, arguments);
}

var obj = {name: 'my name'}
hello.call(obj, 'some', 'arguments');

觀察我們如何輕鬆地將hello委託給sayHello使用apply ,但是通過call很難實現。


要回答關於何時使用每個函數的部分,如果您不知道要傳遞的參數的數量,或者它們是否已經在數組或類似數組的對像中(如arguments轉發自己的對象),請使用apply參數。否則使用call ,因為不需要將參數包裝在數組中。

f.call(thisObject, a, b, c); // Fixed number of arguments

f.apply(thisObject, arguments); // Forward this function's arguments

var args = [];
while (...) {
    args.push(some_value());
}
f.apply(thisObject, args); // Unknown number of arguments

當我沒有傳遞任何參數時(比如你的例子),我更喜歡call因為我正在調用函數。 apply意味著你函數應用於(不存在的)參數。

應該沒有任何性能差異,除非您使用apply並將參數包裝在數組中(例如f.apply(thisObject, [a, b, c])而不是f.call(thisObject, a, b, c) )。 我沒有測試它,所以可能會有差異,但它將是非常瀏覽器特定的。 如果你沒有數組中的參數,那麼call可能會更快,如果你這樣做,則apply更快。


根本區別在於call()接受一個參數列表 ,而apply()接受一個參數數組


K. 斯科特艾倫在這件事上寫得很好

基本上,他們在處理函數參數方面有所不同。

apply()方法與call()相同,但apply()需要數組作為第二個參數。 該數組表示目標方法的參數。“

所以:

// assuming you have f
function f(message) { ... }
f.call(receiver, "test");
f.apply(receiver, ["test"]);

遵循Michael Bolin的Closure:The Definitive Guide的摘錄。 它可能看起來有點冗長,但它充滿了很多洞察力。 從“附錄B.經常誤解的JavaScript概念”:

調用函數時this意味著什麼

當調用foo.bar.baz()形式的函數時,對象foo.bar被稱為接收器。 調用該函數時,接收器用作以下值:

var obj = {};
obj.value = 10;
/** @param {...number} additionalValues */
obj.addValues = function(additionalValues) {
  for (var i = 0; i < arguments.length; i++) {
    this.value += arguments[i];
  }
  return this.value;
};
// Evaluates to 30 because obj is used as the value for 'this' when
// obj.addValues() is called, so obj.value becomes 10 + 20.
obj.addValues(20);

如果在調用函數時沒有顯式接收器,則全局對象成為接收器。 如第47頁的“goog.global”中所述,窗口是在Web瀏覽器中執行JavaScript時的全局對象。 這會導致一些令人驚訝的行為:

var f = obj.addValues;
// Evaluates to NaN because window is used as the value for 'this' when
// f() is called. Because and window.value is undefined, adding a number to
// it results in NaN.
f(20);
// This also has the unintentional side effect of adding a value to window:
alert(window.value); // Alerts NaN

即使obj.addValuesf引用相同的函數,它們在調用時的行為也不同,因為每次調用時接收器的值都不同。 因此,在調用引用this函數的函數時,確保在調用它時具有正確的值非常重要。 要清楚,如果函數體中沒有引用它,那麼f(20)obj.addValues(20)將是相同的。

因為函數是JavaScript中的第一類對象,所以它們可以有自己的方法。 所有函數都有方法call()apply() ,這使得在調用函數時可以重新定義接收器(即,它所引用的對象)。 方法簽名如下:

/**
* @param {*=} receiver to substitute for 'this'
* @param {...} parameters to use as arguments to the function
*/
Function.prototype.call;
/**
* @param {*=} receiver to substitute for 'this'
* @param {Array} parameters to use as arguments to the function
*/
Function.prototype.apply;

請注意, call()apply()之間的唯一區別是call()接收函數參數作為單獨的參數,而apply()它們作為單個數組接收:

// When f is called with obj as its receiver, it behaves the same as calling
// obj.addValues(). Both of the following increase obj.value by 60:
f.call(obj, 10, 20, 30);
f.apply(obj, [10, 20, 30]);

以下調用是等效的,因為fobj.addValues引用相同的函數:

obj.addValues.call(obj, 10, 20, 30);
obj.addValues.apply(obj, [10, 20, 30]);

但是,由於call()apply()使用其自己的接收器的值來替換未指定的接收器參數,因此以下方法不起作用:

// Both statements evaluate to NaN
obj.addValues.call(undefined, 10, 20, 30);
obj.addValues.apply(undefined, [10, 20, 30]);

調用函數時, this的值永遠不能為nullundefined 。 當nullundefined作為接收器提供給call()apply() ,全局對象將被用作接收器的值。 因此,前面的代碼具有向全局對象添加名為value的屬性的相同的不良副作用。

將函數視為不知道分配給它的變量可能會有所幫助。 這有助於強化這樣一種觀點,即在調用函數時,而不是在定義函數時,它的值將被約束。

提取物結束。


這是一個很好的助記符。 一個 pply使用A rrays和A lways需要一個或兩個參數。 當你使用C時,你必須計算參數的數量。


Function.prototype.apply()上的MDN文檔

apply()方法調用一個給定this值的函數,並將參數作為數組(或類數組對象)提供。

句法

fun.apply(thisArg, [argsArray])

Function.prototype.call()上的MDN文檔

call()方法調用一個具有給定值的函數和單獨提供的參數。

句法

fun.call(thisArg[, arg1[, arg2[, ...]]])

來自JavaScript中的Function.apply和Function.call

apply()方法與call()相同,但apply()需要數組作為第二個參數。 該數組表示目標方法的參數。

代碼示例:

var doSomething = function() {
    var arr = [];
    for(i in arguments) {
        if(typeof this[arguments[i]] !== 'undefined') {
            arr.push(this[arguments[i]]);
        }
    }
    return arr;
}

var output = function(position, obj) {
    document.body.innerHTML += '<h3>output ' + position + '</h3>' + JSON.stringify(obj) + '\n<br>\n<br><hr>';
}

output(1, doSomething(
    'one',
    'two',
    'two',
    'one'
));

output(2, doSomething.apply({one : 'Steven', two : 'Jane'}, [
    'one',
    'two',
    'two',
    'one'
]));

output(3, doSomething.call({one : 'Steven', two : 'Jane'},
    'one',
    'two',
    'two',
    'one'
));

另見這個小提琴


區別在於call()獲取函數參數,而apply()接受數組中的函數參數。







dynamic