찾다
웹 프론트엔드JS 튜토리얼당신이 알고 싶은 모든 것이 여기에 있습니다

당신이 알고 싶은 모든 것이 여기에 있습니다

Jan 23, 2017 pm 04:12 PM
javascript프런트 엔드

자바스크립트를 일상적으로 사용하거나 프론트엔드 면접 과정에서 나타나는 비율이 매우 높습니다. 이는 의심할 여지없이 이것의 중요성을 보여줍니다. 그러나 이는 매우 유연하기 때문에 많은 사람들이 이 동작을 이해하기 어렵게 만듭니다. 이 기사는 이것이 왜 필요한지부터 시작하여 이에 대한 6가지 규칙을 요약하여 귀하의 혼란에 답하는 데 도움이 되기를 바랍니다.

소개

이 매개변수는 실제로 개발 중에 수동으로 전달될 수도 있고 JS 또는 세 번째 세 당사자로부터 수신됩니다.
이 매개변수는 일반적으로 함수가 실행될 때 "소유자"를 가리킵니다. 이 메커니즘은 기능 설계를 더욱 간결하고 재사용 가능하게 만들 수 있습니다.

함수가 실행될 때 바인딩됩니다. 총 6가지 바인딩 규칙이 있습니다.

●new 바인딩: new 키워드를 사용하여 객체를 생성할 때 this가 바인딩됩니다. 생성된 개체에 대해

● 명시적 바인딩: 호출, 적용 또는 바인드 메서드를 사용하여 명시적으로 바인딩하는 경우 첫 번째 매개변수입니다.

●암시적 바인딩: 객체에 함수가 실행되면 시스템이 이를 객체에 암시적으로 바인딩합니다.

●기본 바인딩: 함수가 독립적으로 실행될 때 엄격 모드에서 this의 기본 바인딩 값은 정의되지 않고, 그렇지 않으면 전역 개체입니다.

●화살표 함수 바인딩: 화살표 함수를 사용할 때 this의 바인딩 값은 외부 일반 함수(또는 전역 개체 자체)의 this와 동일합니다.

●시스템 또는 제3자 바인딩: 시스템이나 제3자가 제공하는 인터페이스에 함수가 매개변수로 전달되면 전달된 함수의 해당 함수가 시스템 또는 제3자에 의해 바인딩됩니다.

이 메커니즘의 역할은 객체를 암시적으로 전달하는 우아한 방법을 제공하여 기능 설계를 더욱 간결하고 재사용 가능하게 합니다.

클릭하면 배경이 빨간색으로 바뀌는 두 개의 버튼에 대한 다음 예를 살펴보세요.

function changeBackgroundColor(ele) {
  ele.style.backgroundColor = 'red';
}
btn1.addEventListener('click',function () {
  changeBackgroundColor(btn1);
});
btn2.addEventListener('click',function () {
  changeBackgroundColor(btn2);
});

여기서는 클릭한 요소를 명시적으로changeBackgroundColor 함수에 전달합니다. 그러나 실제로는 암시적으로 컨텍스트를 전달하는 이 기능을 활용하여 현재 클릭된 요소를 함수에서 직접 가져올 수 있습니다. 다음과 같습니다:

function changeBackgroundColor() {    this.style.backgroundColor = 'red';
}
btn1.addEventListener('click',changeBackgroundColor);
btn2.addEventListener('click',changeBackgroundColor);

첫 번째 예에서는 클릭한 요소가 이 형식 매개변수인 ele로 대체됩니다. 두 번째 예에서는 특수 키워드 this로 대체되었습니다. 이는 형식 매개변수와 유사한 기능을 가지고 있으며, 본질적으로 객체에 대한 참조이며, 수동으로 값을 전송할 필요가 없으므로 사용이 더 간단하고 편리하다는 것이 특징입니다.

6가지 규칙

실제로 이것이 가리키는 대상이 무엇인지 가장 혼란스럽습니다. 이 문서에서는 6가지 유형의 시나리오를 분류하고 이에 대한 6가지 바인딩 규칙을 요약합니다.

1.new 바인딩

new를 사용하여 객체를 생성할 때 클래스의 this를 참조합니다. 무엇입니까?

class Person {
  constructor(name){
    this.name = name;
  }
  getThis(){
    return this
  }
}
const xiaoMing = new Person("小明");
console.log(xiaoMing.getThis() === xiaoMing); // true
console.log(xiaoMing.getThis() === Person); // false
console.log(xiaoMing.name === "小明"); // true

위의 예에서 Person 클래스는 ES6 구문을 사용하여 생성되었습니다. new 키워드를 사용하여 개체를 생성하는 과정에서 이는 시스템에 의해 생성된 개체, 즉 xiaoMing에 자동으로 바인딩됩니다.

규칙 1: new 키워드를 사용하여 객체를 생성할 때 생성된 객체에 바인딩됩니다.

2. 명시적 바인딩


시나리오 2, 호출, 적용 및 바인딩 메서드를 사용하여 이 매개변수를 명시적으로 바인딩합니다.

call을 예로 들어 보겠습니다. call 메소드에 전달된 첫 번째 매개변수는 이것이 참조하는 객체입니다.

function foo() {  console.log( this === obj ); // true
  console.log( this.a === 2 ); // true}const obj = {
  a: 2};
foo.call( obj );

명시적 전달의 경우 이것이 가리키는 객체가 분명하며 이는 호출, 적용 또는 바인드 메소드의 첫 번째 매개변수입니다.

규칙 2: 호출, 적용 또는 바인드 메소드를 사용하여 명시적으로 바인딩하는 경우 이것이 첫 번째 매개변수입니다.

3. 암시적 바인딩


명시적 바인딩과 암시적 바인딩의 차이점은 개발자의 몫입니다. 암시적으로 바인딩되면 함수나 메서드에 "소유자"가 있고 이 "소유자"는 직접 호출되는 함수나 메서드 개체를 나타냅니다.

예제 1

먼저 가장 간단한 예를 살펴보겠습니다.

function bar() {  console.log( this === obj );
}const obj = {
  foo: function () {    console.log( this === obj );
  },
  bar: bar
};
obj.foo(); // trueobj.bar(); // true


foo 함수는 obj 객체에 직접 걸려 있고, bar 함수는 외부에 정의된 후 obj 객체에 걸려 있습니다. 함수가 어디에 정의되어 있든 상관없이 함수가 최종적으로 호출될 때 함수의 "소유자"는 obj입니다. 따라서 이는 함수가 호출될 때 "소유자" obj를 가리킵니다.

예제 2

더 깊은 이해를 위해 새로운 객체에 기능을 재할당하는 경우를 생각해 보겠습니다.

function bar() {  console.log( this === obj1 ); // false
  console.log( this === obj2 ); // true}const obj1 = {
  foo: function () {    console.log( this === obj1 ); // false
    console.log( this === obj2 ); // true
  },
  bar: bar
};const obj2 = {
  foo: obj1.foo,
  bar: obj1.bar
};

obj2.foo();
obj2.bar();

이 예에서는 obj1의 foo 및 bar 메소드가 obj2에 할당됩니다. 함수가 호출되면 "소유자"는 obj1이 아니라 obj2입니다. 따라서 이것은 obj2를 가리킵니다.

예 3

객체는 여러 수준에 중첩될 수 있습니다. 이 경우 함수가 실행될 때 함수의 "소유자"는 누구입니까?

const obj1 = {
  obj2: {
    foo: function foo() {      console.log( this === obj1 );      // false
      console.log( this === obj1.obj2 ); // true
    }
  }
};

obj1.obj2.foo()

foo 메서드/함수의 직접 호출자는 obj1이 아니라 obj2입니다. 따라서 함수의 "소유자"는 가장 가까운 직접 호출자를 가리킵니다.

예시 4

如果一个方法/函数,在它的直接对象上调用执行,又同时执行了 call 方法,那么它是属于隐式绑定还是显式绑定呢?

const obj1 = {
  a: 1,
  foo: function () {    console.log(this === obj1); // false
    console.log(this === obj2); // true
    console.log(this.a === 2);  // true
  }
};const obj2 = {
  a: 2};

obj1.foo.call(obj2); // true

由上,可以看出,如果显式绑定存在,它就不可能属于隐式绑定。

规则三:如果函数是挂在对象上执行的,这个时候系统会隐式的将 this 绑定为函数执行时的“拥有者”。

4.默认绑定

前一小段,讨论了函数作为对象的方法执行时的情况。本小段,要讨论的是,函数独立执行的情况。

在函数直接调用的情况下,this 绑定的行为,称之为默认绑定。

例一

为了简单起见,先讨论在浏览器的非严格模式的下绑定行为。

function foo() {  console.log( this === window); // true}
foo();

在上面的例子中,系统将 window 默认地绑定到函数的 this 上。

例二

在这里,先介绍一种我们可能会在代码中见到的显式绑定 null 的写法。

function foo() {  console.log( this == window ); // true}

foo.apply(null);

将例一默认绑定的情况,改为了显式绑定 null 的情况。

在实际开发中,我们可能会用到 apply 方法,并在第一个参数传入 null 值,第二个参数传入数组的方式来传递数组类型的参数。这是一种传统的写法,当然现在可以用 ES6 的写法来代替,但是这不在本文的讨论范围内。

在本例最需要关注的是,this 竟然指向的 window 而不是 null。个人测试的结果是,在函数独立调用时,或者显式调用,传入的值为 null 和 undefined 的情况下,会将 window 默认绑定到 this 上。

在函数多次调用,形成了一个调用栈的情况下,默认绑定的规则也是成立的。

例三

接着,探讨下严格模式下,this 的默认绑定的值。

"use strict";

function foo() {
  console.log( this === undefined );
}

foo();               // true
foo.call(undefined); // true
foo.call(null);      // false

在严格模式下,this 的默认绑定的值为 undefined。

规则四:在函数独立执行的情况下,严格模式 this 的默认绑定值为 undefined,否则默认绑定的值为 window。

5.箭头函数绑定

箭头函数实际上,只是一个语法糖,实际上箭头函数中的 this 实际上是其外层函数(或者 window/global 本身)中的 this。

// ES6
function foo() {
  setTimeout(() => {
    console.log(this === obj); // true
  }, 100);
}

const obj = {
  a : 1
}

foo.call(obj);

// ES5
function foo() {
  var _this = this;

  setTimeout(function () {
    console.log(_this === obj); // true
  }, 100);
}

var obj = {
  a : 1
}

foo.call(obj);

规则五:使用箭头函数时,this 的绑定值和其外层的普通函数(或者 window/global 本身) this 绑定值相同。

6.系统或第三方绑定

在 JavaScript 中,函数是第一公民,可以将函数以值的方式,传入任何系统或者第三方提供的函数中。现在讨论,最后一种情况。当将函数作为值,传入系统函数或者第三方函数中时,this 究竟是如何绑定的。

我们在文章一开始提到的,两个按钮例子,系统自动将 this 绑定为点击的按钮。

function changeBackgroundColor() {    console.log(this === btn1); // true}

btn1.addEventListener('click',changeBackgroundColor);

接着测试系统提供的 setTimeout 接口在浏览器和 node 中绑定行为。

// 浏览器
setTimeout(function () {
  console.log(this === window); // true
},0)

// node
setTimeout(function () {
  console.log(this === global); // false
  console.log(this); // Timeout
},0)

很神奇的是,setTimeout 在 node 和浏览器中的绑定行为不一致。如果我们将 node 的中的 this 打印出来,会发现它绑定是一个 Timeout 对象。

如果是第三发提供的接口,情况会更加复杂。因为在其内部,会将什么值绑定到传入的函数的 this 上,事先是不知道的,除非查看文档或者源码。

系统或者第三方,在其内部,可能会使用前面的五种规则一种或多种规则,对传入函数的 this 进行绑定。所以,规则六,实际上一条在由前五条规则上衍生出来的规则。

规则六:调用系统或者第三方提供的接口时,传入函数中的 this 是由系统或者第三方绑定的。

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

Node.js는 크림 덕분에 효율적인 I/O에서 탁월합니다. 스트림은 메모리 오버로드를 피하고 큰 파일, 네트워크 작업 및 실시간 애플리케이션을위한 메모리 과부하를 피하기 위해 데이터를 점차적으로 처리합니다. 스트림을 TypeScript의 유형 안전과 결합하면 Powe가 생성됩니다

Python vs. JavaScript : 성능 및 효율성 고려 사항Python vs. JavaScript : 성능 및 효율성 고려 사항Apr 30, 2025 am 12:08 AM

파이썬과 자바 스크립트 간의 성능과 효율성의 차이는 주로 다음과 같이 반영됩니다. 1) 해석 된 언어로서, 파이썬은 느리게 실행되지만 개발 효율이 높고 빠른 프로토 타입 개발에 적합합니다. 2) JavaScript는 브라우저의 단일 스레드로 제한되지만 멀티 스레딩 및 비동기 I/O는 Node.js의 성능을 향상시키는 데 사용될 수 있으며 실제 프로젝트에서는 이점이 있습니다.

JavaScript의 기원 : 구현 언어 탐색JavaScript의 기원 : 구현 언어 탐색Apr 29, 2025 am 12:51 AM

JavaScript는 1995 년에 시작하여 Brandon Ike에 의해 만들어졌으며 언어를 C로 실현했습니다. 1.C Language는 JavaScript의 고성능 및 시스템 수준 프로그래밍 기능을 제공합니다. 2. JavaScript의 메모리 관리 및 성능 최적화는 C 언어에 의존합니다. 3. C 언어의 크로스 플랫폼 기능은 자바 스크립트가 다른 운영 체제에서 효율적으로 실행하는 데 도움이됩니다.

무대 뒤에서 : 어떤 언어의 힘이 자바 스크립트입니까?무대 뒤에서 : 어떤 언어의 힘이 자바 스크립트입니까?Apr 28, 2025 am 12:01 AM

JavaScript는 브라우저 및 Node.js 환경에서 실행되며 JavaScript 엔진을 사용하여 코드를 구문 분석하고 실행합니다. 1) 구문 분석 단계에서 초록 구문 트리 (AST)를 생성합니다. 2) 컴파일 단계에서 AST를 바이트 코드 또는 기계 코드로 변환합니다. 3) 실행 단계에서 컴파일 된 코드를 실행하십시오.

파이썬과 자바 스크립트의 미래 : 트렌드와 예측파이썬과 자바 스크립트의 미래 : 트렌드와 예측Apr 27, 2025 am 12:21 AM

Python 및 JavaScript의 미래 추세에는 다음이 포함됩니다. 1. Python은 과학 컴퓨팅 분야에서의 위치를 ​​통합하고 AI, 2. JavaScript는 웹 기술의 개발을 촉진하고, 3. 교차 플랫폼 개발이 핫한 주제가되고 4. 성능 최적화가 중점을 둘 것입니다. 둘 다 해당 분야에서 응용 프로그램 시나리오를 계속 확장하고 성능이 더 많은 혁신을 일으킬 것입니다.

Python vs. JavaScript : 개발 환경 및 도구Python vs. JavaScript : 개발 환경 및 도구Apr 26, 2025 am 12:09 AM

개발 환경에서 Python과 JavaScript의 선택이 모두 중요합니다. 1) Python의 개발 환경에는 Pycharm, Jupyternotebook 및 Anaconda가 포함되어 있으며 데이터 과학 및 빠른 프로토 타이핑에 적합합니다. 2) JavaScript의 개발 환경에는 Node.js, VScode 및 Webpack이 포함되어 있으며 프론트 엔드 및 백엔드 개발에 적합합니다. 프로젝트 요구에 따라 올바른 도구를 선택하면 개발 효율성과 프로젝트 성공률이 향상 될 수 있습니다.

JavaScript가 C로 작성 되었습니까? 증거를 검토합니다JavaScript가 C로 작성 되었습니까? 증거를 검토합니다Apr 25, 2025 am 12:15 AM

예, JavaScript의 엔진 코어는 C로 작성되었습니다. 1) C 언어는 효율적인 성능과 기본 제어를 제공하며, 이는 JavaScript 엔진 개발에 적합합니다. 2) V8 엔진을 예를 들어, 핵심은 C로 작성되며 C의 효율성 및 객체 지향적 특성을 결합하여 C로 작성됩니다.

JavaScript의 역할 : 웹 대화식 및 역동적 인 웹JavaScript의 역할 : 웹 대화식 및 역동적 인 웹Apr 24, 2025 am 12:12 AM

JavaScript는 웹 페이지의 상호 작용과 역학을 향상시키기 때문에 현대 웹 사이트의 핵심입니다. 1) 페이지를 새로 고치지 않고 콘텐츠를 변경할 수 있습니다. 2) Domapi를 통해 웹 페이지 조작, 3) 애니메이션 및 드래그 앤 드롭과 같은 복잡한 대화식 효과를 지원합니다. 4) 성능 및 모범 사례를 최적화하여 사용자 경험을 향상시킵니다.

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

맨티스BT

맨티스BT

Mantis는 제품 결함 추적을 돕기 위해 설계된 배포하기 쉬운 웹 기반 결함 추적 도구입니다. PHP, MySQL 및 웹 서버가 필요합니다. 데모 및 호스팅 서비스를 확인해 보세요.

에디트플러스 중국어 크랙 버전

에디트플러스 중국어 크랙 버전

작은 크기, 구문 강조, 코드 프롬프트 기능을 지원하지 않음

SublimeText3 영어 버전

SublimeText3 영어 버전

권장 사항: Win 버전, 코드 프롬프트 지원!

SublimeText3 Linux 새 버전

SublimeText3 Linux 새 버전

SublimeText3 Linux 최신 버전

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기