>  기사  >  웹 프론트엔드  >  JS에서 이로 인해 발생하는 버그에 대한 자세한 해석

JS에서 이로 인해 발생하는 버그에 대한 자세한 해석

亚连
亚连원래의
2018-06-21 14:20:271277검색

이 글에서는 주로 JavaScript에서 이로 인해 발생하는 버그 분석과 관련 처리 방법에 대한 분석을 소개합니다.

JS에서는 이러한 컨텍스트가 항상 예측할 수 없습니다. 버그가 발생하면 항상 혼란스럽습니다. 실제로 다양한 상황에서 이를 실행하는 방법만 이해하면 됩니다. 당신:

JavaScript에는 초보자를 종종 괴롭히는 매우 특별하고 일반적으로 사용되는 것이 있습니다. 바로 "this"입니다. 이번 수업에서는 "this"에 대해 이야기하겠습니다.

이것은 일반적으로 개체를 가리키며 상황에 따라 다른 개체를 가리킵니다. "이것"을 더 잘 이해하는 데 도움이 되는 몇 가지 다른 시나리오를 살펴보겠습니다.

window 객체(전역 객체)

여기서 "this"는 세 가지 다른 상황에서 인쇄됩니다. 즉, 함수 문을 사용하여 실행합니다. (아직 확실하지 않은 경우; 함수문과 함수 표현식의 차이점은 참고 1)을 참고하세요.

이 세 개의 "this"는 동일한 개체, 즉 전역 환경의 창 개체(전역 개체)를 가리킨다는 것이 밝혀졌습니다.

이는 이 함수를 직접 사용할 수 있고 이는 창 개체에 새 속성을 생성합니다.

여기에서는 this.NewVariable = "..."를 사용하여 창 개체에 새 속성을 생성합니다. 직접 console.log(NewVariable), 여기에 this.NewVariable 또는 window.NewVariable을 입력할 필요가 없는 이유는 "."를 사용하지 않고 전역 개체(창)의 모든 속성을 직접 사용할 수 있기 때문입니다. this.NewVariable = "..."来在window object建立新的属性,函数的最后,我们则可以直接console.log(NewVariable),这里之所以可以不用打this.NewVariable或window.NewVariable是因为任何在global object (window)的属性,我们都可以直接去使用它,而不用使用”.”。

跑出来的结果会像这样子:

它会打印出我们的”Create a new property”,同时,在window这个大的object中,我们也会找到NewVariable这个属性:

method in object

我们知道,在对象里的值如果是原生值(primitive type;例如,字串、数值、逻辑值),我们会把这个新建立的东西称为「属性(property)」;如果对象里面的值是函数(function)的话,我们则会把这个新建立的东西称为「方法(method)」。

在这里,我们就要来建立method:

首先,我们利用object literal的方式创建一个对象c,里面包含属性name和方法log。log是一个匿名函数(anonymous function),函数内容很简单,就是打印this而已(关于匿名函数可参考注1)。最后则是使用c.log的方式来执行该方法。

让我们来看看,这时候的”this”会是什么呢?

答案是对象c!

当这个函数是对象里面的method时,这时候的this就会指向到包含这个method的对象

JavaScript中关于this的一个bug

让我们更进一步延伸来看这个范例:

假设我们在method log裡面多这一行this.name = "Updated Object C name"

因为我们知道”this”现在指的是对象c,所以可以想像的,当我执行这个method的时候,它会去变更c.name的值。

这个部分是没有什么大问题的,不过让我们继续看下去……。

假设我在method log裡面在做一些变更,我在这个method裡面,另外建立一个函数叫做setname,一样是用this.name = newname

결과는 다음과 같습니다.

🎜"새 속성 만들기"가 인쇄됩니다. , 동시에 대형 개체 창에서 NewVariable 속성도 찾을 수 있습니다: 🎜🎜🎜🎜method in object🎜🎜우리는 객체의 값이 기본 값(기본 유형, 예: 문자열, 숫자 값, 논리 값)인 경우 이 새 항목을 추가할 것임을 알고 있습니다. value 생성된 것을 "속성"이라고 합니다. 객체의 값이 함수인 경우 새로 생성된 것을 "메서드"라고 합니다. 🎜🎜여기서 메소드를 설정하겠습니다. 🎜🎜먼저 객체 리터럴을 사용하여 속성 이름과 메소드 로그가 포함된 객체 c를 만듭니다. log는 익명 함수입니다. 함수 내용은 매우 간단합니다. 이를 인쇄하기만 하면 됩니다(익명 함수에 대해서는 참고 1 참조). 마지막으로 c.log를 사용하여 이 메서드를 실행합니다. 🎜🎜🎜🎜이번에 살펴보도록 하겠습니다 "이것"은 무엇일까요? 🎜🎜답은 객체c 입니다! 🎜🎜이 함수가 객체의 메서드인 경우 이는 이 메서드를 포함하는 객체를 가리킵니다🎜🎜🎜🎜JavaScript의 이에 대한 버그🎜🎜이 예제를 더 확장해 보겠습니다. 🎜🎜메서드 log에 this 줄을 추가한다고 가정합니다. name = "Updated Object C name "🎜🎜🎜🎜우리는 그것을 알고 있기 때문에 "this"는 이제 객체 c를 참조하므로 이 메서드를 실행하면 c.name의 값이 변경될 것이라고 상상할 수 있습니다. 🎜🎜🎜🎜이 부분에는 큰 문제가 없습니다. 하지만 계속 찾아보자… 🎜🎜메서드 로그에서 일부 변경을 한다고 가정합니다. 이 메서드에서는 setname이라는 또 다른 함수를 생성하고 this.name = newname을 사용하여 개체 c의 값을 수정합니다. 속성. 🎜🎜그런 다음 객체 c에 있는 name의 속성 값을 "객체 c의 새 이름"으로 변경하려고 setname 함수를 실행하고 마지막으로 "this"를 인쇄하여 살펴봅니다. 🎜🎜🎜🎜

결과적으로 객체 c의 name 속성 값이 "객체 c의 새 이름"으로 변경되지 않았지만 여전히 동일하다는 것을 알 수 있습니다! ? 어떻게 이런 일이 일어날 수 있습니까?

자세히 살펴보고, 다시 창 개체를 살펴보겠습니다. 창 개체에 "name"이라는 새 속성이 있고 값은 "개체 c의 새 이름"입니다.

이게 무슨 뜻인가요? 이는 우리가 setname 함수에서 방금 가리킨 this가 지금 개체 C가 아닌 전역 개체(창 개체)를 가리킨다는 것을 의미합니다!

setname 함수에서는 console.log(this)를 사용하여 살펴봅니다.

log 메서드에서는 console.log(this)를 총 3번 실행했으며 결과는 다음과 같습니다.

첫 번째와 세 번째 "this"는 객체 c를 가리키는 반면, setname의 두 번째 this는 창 객체(전역 객체)를 가리키며, 이것이 setname 함수가 이름의 이름을 수정하는 데 도움이 될 수 없는 이유입니다. "this"는 개체 c를 전혀 가리키지 않기 때문에 개체 c의 속성입니다.

그리고 많은 사람들은 이것이 JavaScript 버그라고 생각합니다.

그래서 우리는 무엇을 할 수 있나요

위의 예를 접했을 때, 다른 객체를 가리키는 것을 피하기 위해 무엇을 할 수 있을까요?

많은 사람들의 솔루션은 이와 같습니다. 객체가 모두 참조된다는 것을 알고 있으므로 이렇게 할 수 있습니다.

STEP 1

전체 함수의 상단에 한 줄을 추가합니다var self = this(有些人会用var that = this). 참조자의 특성상 self와 this는 동일한 객체를 가리키게 되고, this는 객체 c를 가리키므로 self도 객체 c를 가리키게 됩니다.

STEP 2

다음으로, 원래 메서드 로그에 사용된 "this"를 "self"로 변경하세요. 이렇게 하면 위의 예처럼 잘못된 객체를 가리킬 염려 없이 self가 c 객체를 가리키도록 할 수 있습니다.

결과는 예상한 대로입니다. console.log(self)를 두 번째로 사용하면 객체 c의 name 속성 값이 다시 대체됩니다.

요약

요약해 보겠습니다.

글로벌 환경에서 함수를 만들고 이를 인쇄하면 이 함수는 창 개체인 전역 개체를 가리킬 것입니다.

객체, 즉 메소드에 함수를 생성하면 이는 일반적으로 메소드가 포함된 객체를 가리킵니다('일반적으로'라고 말하는 이유는 위의 버그 상황을 외부에서 제외하기 때문입니다).

메서드에서 this가 무엇을 가리키는지 알 수 없는 상황이 발생하면 불필요한 오류를 피하기 위해 메서드 상단에 변수를 만들고 this(var self = this)로 지정할 수 있습니다.

4. 해당 상황에서 이것이 무엇을 의미하는지 아직도 모르겠다면 console.log를 보고 살펴보세요!

샘플 코드

// function statement
function a(){
 console.log(this);
 this.NewVariable = "Create a new property";
}
a();
console.log(NewVariable);
var c = {
 name:"The C object",
 log: function(){
 var self = this;
 self.name = "Updated object C name";
 console.log(self);
 
 var setname = function(newname){
  self.name = newname;
  console.log(self);
 }
 setname("New name for object c");
 console.log(self)
 }
}
c.log();

위 내용은 제가 정리한 내용입니다. 앞으로 도움이 되길 바랍니다.

관련 기사:

vue-cli를 사용하여 다중 페이지 애플리케이션을 구현하는 방법

VUE에서 배열 업데이트 기능을 구현하는 방법

vuejs에서 모듈식 접근 방식을 사용하여 개발

Vue 프로젝트 최적화 요구 사항 무엇에 주의해야 합니까?

vue-cli에서 컴포넌트 통신을 구현하는 방법

위 내용은 JS에서 이로 인해 발생하는 버그에 대한 자세한 해석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.