javascript - 設定 - ソネット 電話 回線




通話と申し込みの違いは何ですか? (14)

関数を呼び出すためにcallapplyを使用することの違いは何ですか?

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

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

前述の2つの方法のパフォーマンスに違いはありますか? callオーバーをapply最善で、その逆の場合はいつですか?


概要:

call()apply()Function.prototypeあるメソッドです。 したがって、プロトタイプチェーンを介してすべての関数オブジェクトで使用できます。 call()apply()両方で、 this指定された値を持つ関数を実行できapply()

call()apply()の主な違いは、引数を渡す必要があることです。 call()apply()両方で、 this同じ値にしたいオブジェクトを最初の引数として渡します。 他の引数は次のように異なります。

  • call()使うと、引数を通常通りに入れる必要があります(2番目の引数から始まります)
  • 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()を使ってこの振る舞いを強制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


1つのオブジェクトが別のオブジェクトの機能を借用することは時には有益です。つまり、借用オブジェクトは、あたかも自身が所有するかのように貸し出し機能を実行するだけです。

小さなコード例:

var friend = {
    car: false,
    lendCar: function ( canLend ){
      this.car = canLend;
 }

}; 

var me = {
    car: false,
    gotCar: function(){
      return this.car === true;
  }
};

console.log(me.gotCar()); // false

friend.lendCar.call(me, true); 

console.log(me.gotCar()); // true

friend.lendCar.apply(me, [false]);

console.log(me.gotCar()); // false

これらのメソッドは、オブジェクトに一時的な機能を与えるために非常に便利です。



K. Scott Allenはこの問題について素晴らしい書きかけをしています。

基本的には、関数引数の扱い方が異なります。

apply()メソッドはcall()と同じですが、apply()は配列を2番目のパラメータとして必要とします。 配列は、ターゲットメソッドの引数を表します。

そう:

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

Function.prototype.apply()のMDNドキュメントから:

apply()メソッドは、与えられthis値と引数が配列(または配列のようなオブジェクト)として提供された関数を呼び出します。

構文

fun.apply(thisArg, [argsArray])

Function.prototype.call()のMDNドキュメントから:

call()メソッドは、与えられthis値と引数を個別に提供する関数を呼び出します。

構文

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

JavaScriptのFunction.applyとFunction.callから:

apply()メソッドはcall()と同じですが、apply()は配列を2番目のパラメータとして必要とします。 配列は、ターゲットメソッドの引数を表します。

コード例:

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'
));

このフィドルも見てください。


callapplyが同じことを達成するにもかかわらず、私はあなたがcall使用applyことができないが、 apply使用applyことができる少なくとも一つの場所があると思う。 つまり、継承をサポートしてコンストラクタを呼びたい場合です。

ここで関数を使用すると、他のクラスを拡張してクラスを作成することもできます。

function makeClass( properties ) {
    var ctor = properties['constructor'] || function(){}
    var Super = properties['extends'];
    var Class = function () {
                 // Here 'call' cannot work, only 'apply' can!!!
                 if(Super)
                    Super.apply(this,arguments);  
                 ctor.apply(this,arguments);
                }
     if(Super){
        Class.prototype = Object.create( Super.prototype );
        Class.prototype.constructor = Class;
     }
     Object.keys(properties).forEach( function(prop) {
           if(prop!=='constructor' && prop!=='extends')
            Class.prototype[prop] = properties[prop];
     });
   return Class; 
}

//Usage
var Car = makeClass({
             constructor: function(name){
                         this.name=name;
                        },
             yourName: function() {
                     return this.name;
                   }
          });
//We have a Car class now
 var carInstance=new Car('Fiat');
carInstance.youName();// ReturnsFiat

var SuperCar = makeClass({
               constructor: function(ignore,power){
                     this.power=power;
                  },
               extends:Car,
               yourPower: function() {
                    return this.power;
                  }
              });
//We have a SuperCar class now, which is subclass of Car
var superCar=new SuperCar('BMW xy',2.6);
superCar.yourName();//Returns BMW xy
superCar.yourPower();// Returns 2.6

ここには良いニーモニックがあります。 pplyはA rraysを使用し、 A lwaysは1つまたは2つの引数をとります。 Cを使うときは、引数の数を調べなければなりません。


ここに小規模のポストがあります、私はこれについて書いています:

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"

メソッドとメソッドの違いは、どのようにパラメータを渡すかです。

「配列の場合はA、カンマの場合はC」は便利なニーモニックです。


主な違いは、呼び出しを使用してスコープを変更し、引数を通常通り渡すことができますが、適用すると引数をArrayとして呼び出すことができます(配列として渡す)。 しかし、あなたのコードで何をすべきかという点では、かなり似ています。

この関数の構文はapply()とほとんど同じですが、基本的な違いはcall()が引数リストを受け入れることです。apply()は単一の引数配列を受け入れます。

あなたが見るように、大きな違いはありませんが、依然としてcall()またはapply()を使用するほうが好都合なケースがあります。 たとえば、以下のコードを見てください。これは、MDNの配列内で最小のものと最大のものを見つけ、applyメソッドを使用しています。

// 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]);

呼び出しと適用の両方は、関数が実行されるときにthis値を強制するために使用されます。 唯一の違いは、 calln+1引数をとり、1はthis'n' argumentsです。 applyは2つの引数だけを取り、もう1つは引数配列です。

オーバー・callapplyするcallわかる利点は、あまり努力することなく他の関数に関数呼び出しを簡単に委譲できることです。

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

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

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

私たちがどのように簡単に言ってくれたかを見てください。 applyを使用していapplyが、これを達成するのは非常に難しいです。


基本的な相違点は、 call()引数リストを受け入れる一方、 apply()単一の引数配列を受け入れることです。


違いは、 apply使用すると、 argumentsargumentsとして配列を呼び出すことapplyできます。 callは、パラメータを明示的にリストする必要があります。 有用なニーモニックは、 Aのため rrayとCのためのc omma」です。

applycallに関するMDNの文書を参照してください。

擬似構文:

theFunction.apply(valueForThis, arrayOfArgs)

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

また、ES6のように、 call関数で使用するために配列をspread可能性spreadある場合、 here互換性を見ることができ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


違いは、 call()は関数の引数を別々に取り、 apply()は関数の引数を配列で取りapply()





dynamic