Chrome의 '미 발견 TypeError : 잘못된 호출'


137

requestAnimationFrame아래 코드를 사용 하여 기본 지원 애니메이션을 수행 할 때 :

var support = {
    animationFrame: window.requestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.msRequestAnimationFrame ||
        window.oRequestAnimationFrame
};

support.animationFrame(function() {}); //error

support.animationFrame.call(window, function() {}); //right

support.animationFrame의지를 직접 부르면 ...

잡히지 않은 TypeError : 잘못된 호출

Chrome에서. 왜?

답변:


195

코드에서 사용자 정의 객체의 속성에 기본 메소드를 할당합니다. 를 호출하면 support.animationFrame(function () {})현재 객체의 컨텍스트 (즉, 지원)에서 실행됩니다. 기본 requestAnimationFrame 함수가 제대로 작동하려면의 컨텍스트에서 실행되어야합니다 window.

올바른 사용법은 support.animationFrame.call(window, function() {});입니다.

경고도 마찬가지입니다.

var myObj = {
  myAlert : alert //copying native alert to an object
};

myObj.myAlert('this is an alert'); //is illegal
myObj.myAlert.call(window, 'this is an alert'); // executing in context of window 

또 다른 옵션은 ES5 표준의 일부이며 모든 최신 브라우저에서 사용할 수있는 Function.prototype.bind () 를 사용 하는 것입니다.

var _raf = window.requestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.msRequestAnimationFrame ||
        window.oRequestAnimationFrame;

var support = {
   animationFrame: _raf ? _raf.bind(window) : null
};

1
Chrome 33부터 두 번째 호출은 "잘못된 호출"과 함께 실패합니다. 답변이 업데이트 되면 downvote를 제거하게되어 기쁩니다 !
Dan Dascalescu

@ DanDascalescu : 크롬 33을 사용하고 있으며 나를 위해 일하고 있습니다.
Nemoy

1
방금 코드를 복사하여 붙여 넣고 잘못된 호출 오류가 발생합니다. 스크린 캐스트입니다.
Dan Dascalescu

24
첫 번째 stamtement myObj.myAlert('this is an alert');가 불법 이기 때문에 불법 호출 오류가 발생 합니다. 올바른 사용법은 myObj.myAlert.call(window, 'this is an alert')입니다. 답변을 올바르게 읽고 이해하십시오.
Nemoy

3
내가 여기서 유일한 방법으로 console.log.apply를 같은 방식으로 작동 시키려고한다면 "이것은"창이 아닌 콘솔이어야합니다 : stackoverflow.com/questions/8159233/…
Alex

17

다음을 사용할 수도 있습니다.

var obj = {
    alert: alert.bind(window)
};
obj.alert('I´m an alert!!');

2
이것은 질문에 완전히 대답하지 않습니다. 나는 그것이 대답이 아니라 의견이어야한다고 생각합니다.
Michał Perłakowski

2
또한 history.replaceState로 작업 할 때 적절한 객체에 바인딩하는 것이 중요합니다. var realReplaceState = history.replaceState.bind(history);
DeeY

@ DeyY : 내 질문에 대답 해 주셔서 감사합니다! 미래의 사람들을 위해, localStorage.clear는 당신을 필요로 .bind(localStorage)하지 .bind(window).
삼육 네팔

13

메소드 (예 : 객체에 할당 된 함수)를 실행할 때 내부에서 this변수를 사용 하여이 객체를 참조 할 수 있습니다 .

var obj = {
  someProperty: true,
  someMethod: function() {
    console.log(this.someProperty);
  }
};
obj.someMethod(); // logs true

한 객체에서 다른 객체로 메소드를 할당하면 해당 this변수는 새 객체를 참조합니다. 예를 들면 다음과 같습니다.

var obj = {
  someProperty: true,
  someMethod: function() {
    console.log(this.someProperty);
  }
};

var anotherObj = {
  someProperty: false,
  someMethod: obj.someMethod
};

anotherObj.someMethod(); // logs false

requestAnimationFrame방법 window을 다른 객체에 할당 할 때도 마찬가지 입니다. 이와 같은 기본 기능은 다른 컨텍스트에서 실행되지 않도록 기본 제공 보호 기능을 갖추고 있습니다.

Function.prototype.call()다른 상황에서 함수를 호출 할 수 있도록 기능. 이 메소드의 첫 번째 매개 변수로 컨텍스트 (컨텍스트로 사용될 오브젝트)를 전달하면됩니다. 예를 들어 alert.call({})제공합니다 TypeError: Illegal invocation. 그러나 alert.call(window)이제는 alert원래 범위에서 실행 되기 때문에 제대로 작동합니다 .

.call()당신이 그런 식으로 물건 을 사용한다면 :

support.animationFrame.call(window, function() {});

객체 대신 requestAnimationFrame범위에서 실행 되기 때문에 제대로 작동 window합니다.

그러나이 .call()방법을 호출 할 때마다 사용 하는 것이 매우 우아한 해결책은 아닙니다. 대신을 사용할 수 있습니다 Function.prototype.bind(). 와 비슷한 효과가 .call()있지만 함수를 호출하는 대신 지정된 컨텍스트에서 항상 호출되는 새 함수를 만듭니다. 예를 들면 다음과 같습니다.

window.someProperty = true;
var obj = {
  someProperty: false,
  someMethod: function() {
    console.log(this.someProperty);
  }
};

var someMethodInWindowContext = obj.someMethod.bind(window);
someMethodInWindowContext(); // logs true

유일한 단점은 IE <= 8에서 지원되지 않는Function.prototype.bind() ECMAScript 5의 일부라는 것 입니다. 입니다. 다행스럽게도 MDN에는 폴리 필이 있습니다 .

아마 이미 알았 듯이 .bind()항상 requestAnimationFrame컨텍스트에서 실행 하는 데 사용할 수 있습니다.window . 코드는 다음과 같습니다.

var support = {
    animationFrame: (window.requestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.msRequestAnimationFrame ||
        window.oRequestAnimationFrame).bind(window)
};

그런 다음 간단히 사용할 수 있습니다 support.animationFrame(function() {});.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.