> 웹 프론트엔드 > JS 튜토리얼 > JavaScript에서 이것이 마법이란 무엇입니까?

JavaScript에서 이것이 마법이란 무엇입니까?

藏色散人
풀어 주다: 2021-09-25 17:27:37
앞으로
1955명이 탐색했습니다.
이 키워드는 JavaScript에서 가장 복잡한 메커니즘 중 하나입니다. 모든 기능의 범위에서 자동으로 정의되는 매우 특별한 키워드입니다. 그러나 경험이 풍부한 JavaScript 개발자라도 이것이 정확히 무엇을 가리키는지 파악하는 데 어려움을 겪습니다.

이게 뭐죠?

함수 자체를 가리키시나요?

문자 그대로의 의미를 보면 이것이 함수 자체를 가리키는 것이라고 생각하기 쉽습니다. 우리는 예를 볼 수 있습니다.

function foo() {
    this.count = this.count ? this.count + 1 : 1;
}

for (let i = 0; i < 5; i++) {
    foo();
}
console.log(foo.count); // undefined
로그인 후 복사

foo.count의 출력이 우리가 예상한 5가 아니라 처음에 할당된 0임을 알 수 있습니다. 즉, 5,而是一开始赋值的0。也就是说this其实并没有指向函数本身

指向作用域?

还有一种比较常见的误解是,this指向了函数的作用域。

function foo() {
    var a = 2;
    bar();
}
function bar() {
    console.log(this.a);
}

foo(); // undefined
로그인 후 복사

这段代码中,bar在foo中运行,输出this.a得到的却是undefined。也就是说this也不是指向函数的作用域的

这也不是,那也不是,this到底是什么呢?在函数执行过程中,会创建一个执行上下文(一个记录),this就是这个上下文中的一个属性,在执行过程中用到。而this的指向则是取决于函数在哪里被调用。

this的绑定规则

this的绑定有四条可以遵循的规则,下面将一一介绍。

1.默认绑定

独立函数调用,非严格模式下,指向window;严格模式下指向undefined。 这里说的独立函数可以理解成除开后面三种情况的一般函数调用。

// 非严格模式
var name = &#39;Willem&#39;;
function foo() {
    console.log(this.name);
}
foo(); // Willem

// 执行时启用严格模式
(function() {
    &#39;use strict&#39;;
    foo(); // Willem
    bar(); // Cannot read property &#39;name&#39; of undefined
})();

// 函数体使用严格模式
function bar() {
    &#39;use strict&#39;;
    console.log(this.name);
}
로그인 후 복사

上述代码中,分别在普通环境中输出Willem,说明指向的确实是window对象。需要特别注意的一点是:严格模式下指向undefined指的是函数体内启用了严格模式,而不是调用时。

2. 隐式绑定

隐式绑定说的是,在函数执行时,是否被某个对象拥有或包含。换句话说,在函数运行时,是否是作为某个对象的属性的方式运行的,这样说还是不是很清楚,来个栗子:

function foo() {
    console.log(this.a);
}
var a = 1;
var obj = {
    a: 2,
    foo
};
obj.foo(); // 2
var obj2 = {
    a: 3,
    obj
};
obj2.obj.foo(); // 2
로그인 후 복사

示例中,foo被当做了obj的一个属性进行执行,此时obj作为了函数的上下文,此时this指向了obj,this.a等价于obj.a。在对象属性链式的调用中,只有最后一层会对调用位置产生影响,也就是说最后一层会影响this指向。

有很多前端的小伙伴面试时或许还见过这样的题:

function foo() {
    console.log(this.a);
}
var a = 1;
var obj = {
    a: 2,
    foo
};
var bar = obj.foo;
bar(); // 1
로그인 후 복사

这是隐式绑定最常见的一个问题,隐式丢失:被隐式绑定的函数会丢失绑定对象。虽然bar是对obj.foo的一个引用,但实际上引用的还是foo函数本身,bar函数就是一个独立函数的调用,参考第一条,此时this指向了window|undefined

还有一种经典的回调函数的this指向问题也是隐式丢失。

function foo() {
    console.log(this.a);
}
function doFoo(fn) {
    fn();
}
var a = 1;
var obj = {
    a: 2,
    foo
};
doFoo(obj.foo); // 1
로그인 후 복사

小结:在隐式绑定中,赋值的情况下(回调是隐式赋值)需要特别注意隐式丢失的问题 。

3. 显示绑定

JavaScript中的Function提供了两个方法callapply,传入的第一个参数是一个对象,会把this绑定到这个对象。如果是传入的是一个原始值(字符串、数字、布尔),会被转换成它的对象形式(new String(), new Boolean(), new Number())。

function foo() {
    console.log(this.a);
}
var obj = {
    a: 1
};
foo.call(obj); // 1
로그인 후 복사

虽然我们可以使用callapply显式指定this的指向,但是还是会存在丢失绑定的问题。可以通过所谓的硬绑定(bind函数)来解决,这里就不过多赘述了。

4. new

最后要介绍的是使用new이것은 실제로 함수 자체를 가리키는 것이 아닙니다
.

    범위를 지정하시겠습니까?
  1. 또 다른 일반적인 오해는 이것이 함수의 범위를 가리킨다는 것입니다.
  2. function Foo(a) {
        this.a = a;
    }
    
    var bar = new Foo(2);
    bar.a; // 2
    로그인 후 복사
  3. 이 코드에서 bar는 foo에서 실행되고 this.a의 출력은 정의되지 않습니다입니다. 즉,
  4. 이것은 함수의 범위를 가리키는 것이 아닙니다.
이거 아니야 저것 아니야 이게 뭐야? 함수 실행 중에 실행 컨텍스트(레코드)가 생성됩니다. 이는 이 컨텍스트의 속성이며 실행 중에 사용됩니다. 이것의 요점은 함수가 호출되는 위치에 따라 다릅니다.

이 바인딩 규칙

이 바인딩에는 따를 수 있는 4가지 규칙이 있는데, 아래에서 하나씩 소개하겠습니다.

1. 기본 바인딩

는 비엄격 모드에서는 창을 가리키고, 정의되지 않은 함수를 가리킵니다. 여기에 언급된 독립 함수는 다음 세 가지 상황을 제외하면 일반적인 함수 호출로 이해될 수 있습니다. rrreee위 코드에서 Willem은 일반 환경에서 출력되는데, 이는 실제로 가리키는 window 객체임을 나타냅니다. 특별한 주의가 필요한 한 가지 사항은 다음과 같습니다. 엄격 모드에서 정의되지 않음을 가리키는 는 호출될 때가 아니라 함수 본문에서 엄격 모드가 활성화된다는 사실을 나타냅니다.
2. 암시적 바인딩

암시적 바인딩은 함수가 실행될 때 개체가 소유하거나 포함하는지를 의미합니다. 즉, 함수가 실행될 때 객체의 속성으로 실행되는지가 명확하지 않습니다. 예를 들면 다음과 같습니다. 🎜rrreee🎜예제에서는 foo가 obj의 속성으로 실행됩니다. , obj는 함수의 컨텍스트 역할을 하며 이는 obj를 가리킵니다. this.aobj.a와 동일합니다. 개체 속성 체인 호출에서는 마지막 레이어만 호출 위치에 영향을 미치며, 이는 마지막 레이어가 이 지점에 영향을 미친다는 의미입니다. 🎜🎜많은 프런트 엔드 친구들이 인터뷰 중에 다음 질문을 보았을 것입니다: 🎜rrreee🎜이것은 암시적 바인딩에서 가장 일반적인 문제입니다. 🎜암시적 손실: 암시적으로 바인딩된 함수는 바인딩된 개체를 잃습니다🎜. bar는 obj.foo에 대한 참조이지만 실제로는 foo 함수 자체를 참조합니다. 이때 bar 함수는 첫 번째 항목을 참조하세요. /코드> . 🎜🎜암시적으로 손실되는 고전적인 콜백 함수의 포인팅 문제도 있습니다. 🎜rrreee🎜요약: 암시적 바인딩에서 값을 할당할 때(콜백은 암시적 할당입니다) 암시적 손실 문제에 특별한 주의를 기울여야 합니다. 🎜🎜3. JavaScript의 디스플레이 바인딩🎜🎜Function은 callapply 두 가지 메서드를 제공하며 전달된 첫 번째 매개 변수는 이 개체에 바인딩됩니다. 기본 값(문자열, 숫자, Boolean)이 전달되면 객체 형태(new String(), new Boolean(), new Number())로 변환됩니다. 🎜rrreee🎜이 점을 명시적으로 지정하기 위해 callapply를 사용할 수 있지만 여전히 바인딩이 손실되는 문제가 있습니다. 소위 하드바인딩(바인딩 기능)을 통해 해결할 수 있으므로 여기서는 자세히 다루지 않겠습니다. 🎜🎜4. new🎜🎜 마지막으로 소개하고 싶은 것은 new를 사용하여 new를 수동으로 구현한 아동용 신발은 js의 new와 new의 내용을 더 명확하게 해야 한다는 것입니다. 다른 언어는 완전히 다릅니다. 🎜새 실행 프로세스: 🎜🎜🎜 빈 개체 만들기 🎜🎜 현재 빈 개체에 프로토타입 도킹 수행 🎜🎜 함수 실행 결과 또는 현재 빈 개체 반환 🎜🎜rrreee🎜 new를 사용하여 함수를 호출할 때 새 개체를 만들고 함수 호출에서 이 개체에 바인딩합니다. 🎜🎜우선순위🎜🎜마지막으로 우선순위 관계에 대해 간략하게 설명하겠습니다. new > 디스플레이 바인딩 > 암시적 바인딩 > 🎜🎜추천 학습: "🎜🎜JavaScript 기본 튜토리얼🎜🎜"🎜🎜🎜

위 내용은 JavaScript에서 이것이 마법이란 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:segmentfault.com
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿