javascript eval function




전화와 신청의 차이점은 무엇입니까? (14)

개요:

call()apply() 는 모두 Function.prototype 에있는 메소드입니다. 따라서 프로토 타입 체인을 통해 모든 함수 객체에서 사용할 수 있습니다. call()apply()this 의 지정된 값을 가진 함수를 실행할 수있다.

call()apply() 가장 큰 차이점은 인수를 인자로 전달해야한다는 것입니다. call()apply() 당신은 첫 번째 인자로 당신이 원하는 값으로 객체를 넘깁니다. 다른 인수는 다음과 같이 다릅니다.

  • 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 값은 자바 스크립트에서 까다로울 수 있습니다. 이 값은 함수가 정의 될 때가 아니라 함수가 실행될 때 결정 됩니다. 우리의 함수 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

함수를 호출하기 위해 callapply 을 사용하는 것의 차이점은 무엇입니까?

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

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

앞서 언급 한 두 가지 방법간에 성능 차이가 있습니까? call 오버 apply 을 사용하는 것이 가장 좋으며 그 반대의 경우는 언제입니까?


'valueForThis'인수를 사용하는 예제를 보여 드리겠습니다.

Array.prototype.push = function(element) {
   /*
   Native code*, that uses 'this'       
   this.put(element);
   */
}
var array = [];
array.push(1);
array.push.apply(array,[2,3]);
Array.prototype.push.apply(array,[4,5]);
array.push.call(array,6,7);
Array.prototype.push.call(array,8,9);
//[1, 2, 3, 4, 5, 6, 7, 8, 9] 

** 세부 정보 : http://es5.github.io/#x15.4.4.7 *


K. Scott Allen 은이 문제에 대해 좋은 글남겼 습니다.

기본적으로 함수 인수를 처리하는 방법이 다릅니다.

apply () 메서드는 call ()과 동일하지만 apply ()는 두 번째 매개 변수로 배열을 필요로합니다. 배열은 대상 메서드에 대한 인수를 나타냅니다. "

그래서:

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

가장 큰 차이점은 호출을 사용하여 범위를 변경하고 인수를 정상적으로 전달할 수 있지만 적용하면 인수를 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]);

근본적인 차이점은 call()인수 목록을 허용한다는 것입니다. apply()단일 인수 배열을 허용합니다.


메소드와 메소드의 차이점은 매개 변수를 전달하는 방법입니다.

"배열을위한 A와 쉼표를위한 C"는 편리한 니모 닉입니다.


여기에 좋은 니모닉이 있습니다. pply는 A rrays를 사용하고 A lways는 하나 또는 두 개의 인수를 사용합니다. C 를 사용할 때 인자의 수를 알아 내야 만한다.


이것은 오래된 주제이지만, .call은 .apply보다 약간 빠르다는 것을 지적하고 싶었습니다. 정확히 이유는 말할 수 없습니다.

jsPerf, http://jsperf.com/test-call-vs-apply/3 참조

[ UPDATE! ]

Douglas Crockford는 성능 차이를 설명하는 데 도움이 될 수있는 두 가지 차이점에 대해 간략하게 설명합니다 ... http://youtu.be/ya4UHuXNygM?t=15m52s

Call은 0 개 이상의 개별 매개 변수를 사용하지만 Apply는 인수 배열을 사용합니다. 아하!

.apply(this, [...])

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


차이점은 apply 사용하면 arguments 있는 함수를 배열로 호출 apply 수 있습니다. call 에는 매개 변수가 명시 적으로 나열되어야합니다. 유용한 니모닉은 " A for a rray and C for c omma"입니다.

applycall 에 관한 MDN의 문서를 참조하십시오.

의사 구문 :

theFunction.apply(valueForThis, arrayOfArgs)

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

또한 ES6의 경우 call 함수와 함께 사용하기 위해 배열을 spread 할 수있는 가능성이 here . 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() 는 배열에서 함수 인수를 취합니다.


호출 및 적용은 함수가 실행될 this 값을 강제하는 데 사용됩니다. 유일한 차이점은 call n+1 인수가 필요하며 1 this 'n' arguments'n' arguments 입니다. apply 는 두 개의 인수 만 사용하며, 다른 하나는 인수 배열입니다.

오버 callapply 의 장점은 많은 노력없이 다른 함수에 쉽게 함수 호출을 위임 할 수 있다는 것입니다.

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

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

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

우리가 얼마나 쉽게 sayHello 에게 위임했는지 관찰하십시오. apply 사용하는 데 사용 apply . 그러나 call 이것을 달성하는 것은 매우 어렵습니다.


호출, 적용 및 바인딩의 또 다른 예입니다. 호출과 적용의 차이는 분명하지만 바인딩 은 다음과 같이 작동합니다.

  1. Bind는 실행할 수있는 함수의 인스턴스를 반환합니다.
  2. 첫 번째 매개 변수는 ' this '입니다.
  3. 두 번째 매개 변수는 쉼표로 구분 된 인수 목록 (예 : 호출 )입니다.

}

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
*/

Function.prototype.apply ()의 MDN 문서에서 :

apply () 메소드는 this 값과 인자 (array-like 객체)를 인자로 가지는 함수를 호출한다.

통사론

fun.apply(thisArg, [argsArray])

Function.prototype.call ()에 대한 MDN 문서에서 :

call () 메소드는 this 값과 인수가 개별적으로 제공되는 함수를 호출합니다.

통사론

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 해도 똑같은 일이 생기지 만, call 사용할 수없는 곳이 하나 있지만 신청서 만 사용할 수 있다고 생각 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




dynamic