팁
우선, 나는이 기사가 지루하다는 것을 알고 있습니다. JS에서는 이것에 지나지 않으며이 부분을 쓰는 수천 개의 기사가있었습니다.
그러나 나는 여전히 JS에 이것에 관한 기사를 쓰고 싶습니다.이 기사는 요약으로 간주 될 수 있습니다. (신들은 돌아 다니며 내 다른 기사를 읽을 수 있습니다)
JS에서, 이것의 맥락은 항상 예측할 수 없으며, 종종 버그는 항상 혼란스러워집니다. 사실, 다른 상황에서 실행하는 방법을 명확하게 구별하는 한 괜찮을 것입니다.
글로벌 실행
먼저, 이것이 지구 환경에서 무엇인지 살펴 보겠습니다.
첫 번째. 브라우저 :
console.log (this); // 창 {speechsynthesis : speechsynthesis, caches : cachestorage, localstorage : stac창 객체가 인쇄 된 것을 볼 수 있습니다.
두번째. 마디:
Console.log (this); // global
글로벌 객체가 인쇄되어 있음을 알 수 있습니다.
요약 : 글로벌 범위에서, 이것은 현재 글로벌 객체 (브라우저의 창, 노드의 글로벌)를 실행합니다.
기능에서 실행하십시오
순수한 기능 호출
이것은 기능을 사용하는 가장 일반적인 방법입니다.
function test () {console.log (this);}; test (); // Window {spectionSynthesis : SpeciousSynthesis : SpeechSynthesis, Caches : Cachestorage, LocalStorage : Storage, Setsionstorage : Storage, WebKitstorageInfo : webkitstorageInfo…}우리는 함수가 직접 호출되면 글로벌 호출에 속하며 이시기에 이것은 글로벌 객체를 가리 킵니다.
엄격한 모드 '엄격한 사용';
순수한 기능 호출이 엄격한 모드로 실행되면 여기에서는 전역을 가리키지 않지만 정의되지 않습니다. 이것은 JS에서 불공정 한 행동을 제거하기위한 것입니다.
'strict'; function test () {console.log (this);}; test (); // 정의되지 않았습니다물론, 즉각적인 실행 기능에 넣는 것이 더 나을 것입니다. 전 세계 상황을 오염시키는 것을 피할 수 있습니다.
(function () { "strict use"; console.log (this);}) (); // 정의되지 않았습니다메소드 호출 객체로 호출합니다
함수가 객체의 메소드로 호출되는 경우 :
var obj = {이름 : 'qiutc', foo : function () {console.log (this.name); }} obj.foo (); // 'qiutc'현재 이것은 현재 객체를 가리 킵니다.
물론, 우리는 이것을 할 수 있습니다.
function test () {console.log (this.name);} var obj = {name : 'qiutc', foo : test} obj.foo (); // 'qiutc'또한 JS에서 모든 것이 객체이고 함수는 객체이기 때문에 변경되지 않습니다. 테스트의 경우 기능 이름, 함수에 대한 참조 일 뿐이며이 함수를 가리 킵니다. foo = test 일 때 Foo는 또한이 기능을 가리 킵니다.
객체의 메소드를 변수에 할당 한 다음이 변수를 직접 호출하면 다음과 같습니다.
var obj = {이름 : 'qiutc', foo : function () {console.log (this); }} var test = obj.foo; test (); // 창이 시점에서 이것이 세계 세계를 실행한다는 것을 알 수 있습니다. 테스트 = obj.foo를 배치하면 테스트는 직접 함수에 대한 참조를 가리 킵니다. 이 시점에서 실제로 OBJ 객체와 관련이 없으므로 직접 일반 기능이라고 불리우므로 글로벌 객체를 지적합니다.
약간의 함정
우리는 종종 콜백 기능에서 약간의 함정을 만납니다.
var obj = {이름 : 'qiutc', foo : function () {console.log (this); }, foo2 : function () {console.log (this); settimeout (this.foo, 1000); }} obj.foo2 ();이 코드를 실행 한 후 인쇄물이 서로 다르다는 것을 알 수 있습니다.
처음으로 이것을 FOO2로 직접 인쇄하는 것입니다.
그러나 this.foo는 Settimeout에서 실행되었습니다. 여기에서 함수 메소드로 사용되지 않습니까? 이것은 종종 많은 초보자를 퍼즐로 만듭니다.
실제로 Settimeout은 단지 함수 일 뿐이며 함수는 매개 변수가 필요할 수 있습니다. 재미있는 매개 변수가 필요한 것처럼 Settimeout 함수의 매개 변수로 this.foo를 전달합니다. 매개 변수를 전달할 때 실제로 그러한 작업 재미 = this.foo를 수행했습니다. 아니오가 있음을보고, 우리는 이것의 참조를 직접적으로 지적합니다. 실행할 때 Fun ()이 실제로 실행되므로 OBJ와는 아무 관련이 없습니다. 일반 기능이라고 직접 불리하므로 글로벌 객체를 가리 킵니다.
이 문제는 일반적으로 많은 비동기 콜백 함수에서 발생합니다.
해결하다
이 문제를 해결하기 위해 폐쇄 기능을 사용하여 처리 할 수 있습니다.
var obj = {이름 : 'qiutc', foo : function () {console.log (this); }, foo2 : function () {console.log (this); var _this = this; settimeout (function () {console.log (this); // window console.log (_this); // object {name : "qiutc"}}, 1000); }} obj.foo2 ();이것을 직접 사용하는 것은 여전히 창이라는 것을 알 수 있습니다. 이것은 foo2에서 OBJ를 가리키기 때문에 먼저 변수 _this를 사용하여 저장 한 다음 콜백 함수에서 _this를 사용하여 현재 객체를 가리킬 수 있습니다.
세트 타임 아웃의 또 다른 구덩이
앞에서 언급했듯이 콜백 함수가 바인딩 스코프없이 직접 실행되면이 점은 글로벌 오브젝트 (창)에 대한 지적으로 엄격한 모드로 정의되지 않습니다. 그러나 Settimeout의 콜백 함수는 엄격한 모드에서 다르게 나타납니다.
'strict'; function foo () {console.log (this);} settimeout (foo, 1); // 창논리적으로 말하면, 우리는 엄격한 모드를 추가했으며 Foo 호출은 이것을 지정하지 않았으므로 정의되지 않아야하지만 여전히 전 세계 객체가 있습니다. 엄격한 모드가 실패했기 때문입니까?
엄격한 모드에서도 설정 타임 아웃 메소드가 들어오는 함수를 호출 할 때도 함수가이를 지정하지 않으면 암시 적 작업을 수행합니다. 자동으로 전역 컨텍스트를 주입합니다.
물론, 우리가 함수를 전달할 때 이미 이것을 지정한다면, 우리는 다음과 같은 글로벌 객체에 주입되지 않습니다. settimeout (foo.bind (obj), 1) ;;
생성자로 사용하십시오
JS에서 클래스를 구현하려면 일부 생성자를 정의해야하며 생성자를 호출 할 때 키워드를 추가해야합니다.
기능인 (이름) {this.name = 이름; console.log (this);} var p = new Person ( 'qiutc'); // person {이름 : "qiutc"}우리는 생성자로 호출 될 때이 생성자가 호출 될 때 인스턴스화 된 물체를 가리 킵니다.
물론 생성자는 실제로 함수입니다. 정상적인 기능으로 실행하면 전 세계적으로 실행됩니다.
기능인 (이름) {this.name = 이름; console.log (this);} var p = person ( 'qiutc'); // 창차이점은 함수 (신규)를 호출하는 방법입니다.
화살표 기능
새로운 ES6 사양에서 화살표 기능이 추가되었습니다. 평범한 기능과 가장 다른 것은이 포인팅입니다. 우리는이 포인팅 문제를 해결하기 위해 클로저를 사용한다는 것을 기억하십니까? 화살표 기능을 사용하면 더 완벽하게 해결할 수 있습니다.
var obj = {이름 : 'qiutc', foo : function () {console.log (this); }, foo2 : function () {console.log (this); settimeout (() => {console.log (this); // object {이름 : "qiutc"}}, 1000); }} obj.foo2 ();보시다시피, Settimeout으로 실행 된 기능에서는 창에 인쇄되어야하지만 여기에서 OBJ를 가리 킵니다. 그 이유는 설정 타임 아웃으로 전달 된 함수 (매개 변수)가 화살표 함수이기 때문입니다.
기능 본문 의이 객체는 사용되는 객체가 아니라 정의 된 객체입니다.
예를 바탕 으로이 문장을 이해해 봅시다.
obj.foo2 ()가 실행되면 현재는 OBJ를 가리 킵니다. Settimeout을 실행할 때 먼저 익명 화살표 기능을 정의하며 핵심 사항이 여기에 있습니다. 이 화살표 함수를 정의 할 때 이것이 실행되는 화살표 함수의 객체는이 화살표 함수, 즉 obj.foo2에서, 즉 obj; 따라서 화살표 함수를 실행할 때 Obj.foo2-> obj 에서이 -> obj;
간단히 말해서, 화살표 함수에서 이것은 정의 할 때 범위에서만 관련이 있으며, 어디서 어떻게 호출되는지와 관련이 없습니다. 동시에,이 포인팅은 변할 수 없습니다.
전화, 적용, 바인딩
JS에서는 기능도 객체이며 몇 가지 방법도 있습니다. 여기에 세 가지 방법을 소개하면 기능 에서이 포인터를 변경할 수 있습니다.
부르다
fun.call (thisarg [, arg1 [, arg2 [, ...]]])))
기능을 즉시 실행합니다. 첫 번째 매개 변수는 실행 함수에서 이의 컨텍스트를 지정하고 후속 매개 변수는 실행 함수에서 전달되어야하는 매개 변수입니다.
적용하다
fun.apply (thisarg [, [arg1, arg2, ...]]))
기능을 즉시 실행합니다. 첫 번째 매개 변수는 실행 함수에서 이것의 컨텍스트를 지정하고, 두 번째 매개 변수는 배열이며, 이는 실행 함수 (통화와의 차이)로 전달 된 매개 변수입니다.
묶다
var foo = fun.bind (thisarg [, arg1 [, arg2 [, ...]]]);
함수를 실행하지는 않지만 새 기능을 반환합니다. 이 새로운 함수는 이것의 컨텍스트를 지정하며, 후속 매개 변수는 함수를 실행하기 위해 전달 해야하는 매개 변수입니다.
이 세 가지 기능은 실제로 비슷합니다. 전반적인 목적은 함수 (this)의 컨텍스트를 지정하는 것입니다. 호출 기능을 예로 들어합시다.
정상적인 기능으로 이것을 지정하십시오
var obj = {name : 'qiutc'}; function foo () {console.log (this);} foo.call (obj); // object {name : "qiutc"}foo.call (obj)을 실행할 때이 기능에서 이것은 OBJ 객체를 가리 킵니다.
객체의 메소드에 대해 이것을 지정하십시오
var obj = {이름 : 'qiutc', foo : function () {console.log (this); }} var obj2 = {이름 : 'tcqiu222222'}; obj.foo.call (obj2); // object {이름 : "tcqiu222222"}함수를 실행할 때 이것은 성공적인 OBJ2를 가리킨다는 것을 알 수 있습니다.
생성자에 대해이를 지정하십시오
기능인 (이름) {this.name = 이름; console.log (this);} var obj = {이름 : 'qiutc222222222'}; var p = new person.call (obj, 'qiutc'); // uppart typeerror : person.call은 생성자가 아닙니다 (…)우리가 새로운 사람에게 갔기 때문에 오류가 여기에보고되었습니다.
바인딩하고 시도하기 위해 변경 :
기능인 (이름) {this.name = 이름; console.log (this);} var obj = {이름 : 'qiutc2222222222222'}; var person2 = person.bind (obj); var p = new person2 ( 'qiutc'); // person {name : "qiutc"} console.log (obj); // object {Qiutc222222222221인쇄 된 것은 OBJ와 관련이없는 사람이 인스턴스화하는 객체이며, OBJ는 변경되지 않았으며,이 컨텍스트를 적용하지 않고 사람에게 지정 함을 나타냅니다.
따라서 바인드를 사용하여 생성자에 대해이를 지정한다고 결론 지을 수 있습니다. 새로운 생성자 인 경우, 이것은 BAND 함수에 의해 지정된이 기능이 적용되지 않습니다.
물론 BAND는 이것을 지정할뿐만 아니라 매개 변수를 전달할 수 있습니다. 이 작업을 시도해 봅시다 :
기능인 (이름) {this.name = 이름; Console.log (this);} var obj = {이름 : 'qiutc222222222222222221; var person2 = person.bind (obj,'qiutc111111 '); var p = new person2 ('qiutc '); // person {이름 : "qiutc111111"}보시다시피,이를 지정하는 것은 작동하지 않지만 들어오는 매개 변수는 여전히 작동합니다.
화살표 기능에 대해이를 지정하십시오
글로벌에서 화살표 함수를 정의하겠습니다. 따라서이 화살표 기능에서는 필연적으로 전역 객체를 가리킬 것입니다. 통화 메소드를 사용하여 변경되면 어떻게해야합니까?
var afoo = (a) => {console.log (a); console.log (this);} afoo (1); // 1 // Windowvar obj = {이름 : 'qiutc'}; afoo.call (obj, 2); // 2 // 창보시다시피, 여기에서 이것을 가리키는 통화의 작동은 성공하지 못했기 때문에 화살표 기능에서 이것을 정의 할 때 이미 결정했다고 결론 지을 수 있으며 (이를 정의하는 범위에서 실행), 호출 방법과 어디에서 호출하는지와 관련이 없습니다. (전화, 적용, 바인드) 및 기타 작업을 포함한 작업은이를 변경할 수 없습니다.
화살표 기능이 양호하고 변경되지 않음을 기억하십시오.
위는이 기사의 모든 내용입니다. 모든 사람의 학습에 도움이되기를 바랍니다. 모든 사람이 wulin.com을 더 지원하기를 바랍니다.