JavaScript물론 객체는 필수입니다. 바로 this 키워드입니다! this 키워드를 사용하면 JavaScript의 코드가 줄어듭니다. 오늘은 JavaScript에서 이를 분석하겠습니다!
암시적 바인딩
이에 대해 일반적으로 말하면 메소드를 호출하는 사람은 누구나 이 메소드가 가리키는 대상을 가리킵니다. 예:
function foo(){ console.log(this.a) } var a = 3; var obj = { a: 2, foo: foo }; obj.foo(); // 输出2,因为是obj调用的foo,所以foo的this指向了obj,而obj.a = 2
여러 호출이 있는 경우 객체 property참조 체인만 이전 또는 마지막 레이어는 다음과 같이 호출 위치에서 역할을 합니다.
function foo() { console.log( this.a ) } var obj2 = { a: 42, foo: foo } var obj1 = { a: 2, obj2: obj2 } obj1.obj2.foo(); // 42
Implicit loss
가장 일반적인 바인딩 문제 중 하나는 암시적으로 바인딩된 기능이 손실된다는 것입니다. 이는 기본 바인딩을 적용해야 함을 의미하며, 이를 통해 엄격 모드에 있는지 여부에 따라 전역 개체 또는 정의되지 않은 개체에 바인딩됩니다.
function foo() { console.log( this.a ) } var obj1 = { a: 2, foo: foo } var bar = obj1.foo; // 函数别名! var a = "oops, global"; // a是全局对象的属性 bar(); // "oops, global"
bar는 obj.foo에 대한 참조이지만 실제로는 foo 함수 자체를 참조하므로 이때 bar()는 실제로 아무런 수정 없이 함수 호출이므로 기본 바인딩이 적용됩니다
더 보기 콜백 함수를 전달할 때 미묘하고 일반적이며 예상치 못한 상황이 발생합니다.
function foo() { console.log( this.a ) } function doFoo( fn ){ // fn 其实引用的是 foo fn(); // <-- 调用位置! } var obj = { a: 2, foo: foo } var a = "oops, global"; // a是全局对象的属性 doFoo( obj.foo ); // "oops, global"
매개변수 전달은 실제로 일종의 암시적 할당이므로 함수를 전달할 때도 암시적으로 할당되므로 결과는 동일합니다. 앞의 예와 같이 직접 선언한 함수(예: setTimeout 등) 대신 언어 내장 함수에 함수를 전달하면 결과도 동일합니다
Explicit 바인딩
간단히 put 은 호출, 적용, 바인드, 새 바인딩 등을 지정하는 것입니다.
하드 바인딩
function foo( something ) { console.log( this.a, something) return this.a + something } var obj = { a: 2 } var bar = function() { return foo.apply( obj, arguments) } var b = bar(3); // 2 3 console.log(b); // 5
다음은 간단한 설명입니다. bar 함수에서 foo는 적용 함수를 사용하여 obj를 바인딩합니다. 즉, foo에서 이것은 obj를 가리킬 것입니다. 동시에 인수(전달된 매개변수 수에는 제한이 없음)가 매개변수로 사용되고 bar(3)을 실행할 때 obj가 전달됩니다. a는 첫 번째 출력이고 2와 3이 전달된 다음 foo는 두 값의 합을 반환하므로 b의 값은 5
마찬가지로 이 예에서도 바인딩을 사용할 수 있습니다.
function foo( something ) { console.log( this.a, something) return this.a + something } var obj = { a: 2 } var bar = foo.bind(obj) var b = bar(3); // 2 3 console.log(b); // 5
new 바인딩
in the traditional 클래스 지향 언어에서는 new를 사용하여 클래스를 초기화할 때 클래스의 constructor가 호출되지만 JS의 new 메커니즘은 실제로 클래스의 메커니즘과 완전히 다릅니다. 지향적이고 언어 지향적입니다.
new를 사용하여 함수를 호출하거나 생성자 호출이 발생하면 다음 작업이 자동으로 수행됩니다.
새로운 개체 생성(또는 구성)
이 새 개체가 실행됩니다. [[프로토타입]] 연결
이 새 객체는 함수 호출의 this에 바인딩됩니다.
함수가 다른 객체를 반환하지 않으면 newexpression의 함수는 다음과 같이 자동으로 이 새 객체를 반환합니다.
function foo(a){ this.a = a } var bar = new foo(2); console.log(bar.a); // 2
new를 사용하여 호출할 때 foo(...) , 우리는 새로운 객체를 생성하고 foo(...) 호출에서 이 객체에 바인딩할 것입니다. new는 함수가 호출될 때 바인딩 동작에 영향을 줄 수 있는 마지막 메서드입니다.
이것은 우선순위
기본 바인딩의 우선순위가 네 가지 규칙 중 가장 낮다는 것은 의심의 여지가 없으므로 먼저 무시해도 됩니다.
암시적 바인딩과 명시적 바인딩 중 어느 것이 더 높은 우선순위를 가집니까? 테스트해 봅시다:
function foo(a){ console.log(this.a) } var obj1 = { a: 2, foo: foo } var obj2 = { a: 3, foo: foo } obj1.foo(); // 2 obj2.foo(); // 3 obj1.foo.call(obj2); // 3 obj2.foo.call(obj1); // 2
명시적 바인딩의 우선순위가 더 높다는 것을 알 수 있습니다. 즉, 판단을 내릴 때 명시적 바인딩이 존재할 수 있는지 여부를 먼저 고려해야 함을 의미합니다.
이제 새 바인딩과 암시적 바인딩 중 누가 더 높은 우선순위를 갖고 누가 더 낮은 우선순위를 갖는지 파악해야 합니다.
function foo(something){ this.a = something } var obj1 = { foo: foo } var obj2 = {} obj1.foo(2); console.log(obj1.a); // 2 obj1.foo.call(obj2,3); console.log(obj2.a); // 3 var bar = new obj1.foo(4) console.log(obj1.a); // 2 console.log(bar.a); // 4
새 바인딩이 암시적 바인딩보다 우선순위가 더 높다는 것을 알 수 있습니다. 하지만 새로운 바인딩과 명시적 바인딩 중 어느 것이 더 높은 우선순위를 갖나요?
function foo(something){ this.a = something } var obj1 = {} var bar = foo.bind(obj1); bar(2); console.log(obj1.a); // 2 var baz = new bar(3); console.log(obj1.a); // 2 console.log(baz.a); // 3
하드 바인딩에서는 새 바인딩이 이를 수정하므로 새 바인딩이 명시적 바인딩보다 우선순위가 높다는 것을 알 수 있습니다.
new에서 하드 바인딩된 함수를 사용하는 주요 목적은 함수의 일부 매개변수를 미리 설정하여 new로 초기화할 때 나머지 매개변수만 전달할 수 있도록 하는 것입니다. 바인딩(...)의 기능 중 하나는 첫 번째 매개변수(첫 번째 매개변수는 이를 바인딩하는 데 사용됨)를 제외한 모든 매개변수를 기본 함수(이 기술을 "부분 적용"이라고 하며 다음과 같은 유형)에 전달할 수 있다는 것입니다. "커링"). 예를 들면 다음과 같습니다.
function foo(p1,p2){ this.val = p1 + p2; } // 之所以使用null是因为在本例中我们并不关心硬绑定的this是什么 // 反正使用new时this会被修改 var bar = foo.bind(null,'p1'); var baz = new bar('p2'); baz.val; // p1p2 }
커링: 직관적으로 커링은 "일부 매개변수를 수정하면 나머지 매개변수를 허용하는 함수를 얻게 됩니다"라고 말합니다. 따라서 두 개의 변수가 있는 함수 yx의 경우 y = 2가 고정되면 하나의 변수가 있는 함수 2x를 얻습니다
화살표 함수의 이 응용 프로그램
화살표 함수는 이것의 네 가지 표준 규칙을 사용하지 않지만, 외부(함수 또는 전역) 범위를 기준으로 이를 결정합니다.
我们来看一下箭头函数的词法作用域:
function foo() { // 返回一个箭头函数 return (a) => { // this继承自foo() console.log(this.a) }; } var obj1 = { a: 2 }; var obj2 = { a: 3 }; var bar = foo.call(obj1); bar.call(obj2); // 2, 不是3!
foo()内部创建的箭头函数会捕获调用时foo()的this。由于foo()的this绑定到obj1,bar(引用箭头函数)的this也会绑定到obj1,箭头函数的绑定无法被修改。(new也不行!)
总结
如果要判断一个运行中的函数的this绑定,就需要找到这个函数的直接调用位置。找到之后就可以顺序应用下面这四条规则来判断this的绑定对象。
由new调用?绑定到新创建的对象。
由call或者apply(或者bind)调用?绑定到指定的对象。
由上下文对象调用?绑定到那个上下文对象。
默认:在严格模式下绑定到undefined,否则绑定到全局对象。
相关推荐:
위 내용은 JavaScript에서 이에 대한 종합적인 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!