이에 대한 자세한 설명은 JavaScript로

高洛峰
풀어 주다: 2016-11-28 13:59:24
원래의
995명이 탐색했습니다.

JavaScript에서 이는 항상 혼란스럽고 js의 잘 알려진 함정 중 하나입니다. 개인적으로 저는 js에서의 이것이 좋은 디자인이 아니라고 생각합니다. 이것의 늦은 바인딩 특성으로 인해 전역 객체가 될 수도 있고, 현재 객체가 될 수도 있고, 심지어 어떤 사람들은 크기 때문에 이것을 사용하지도 않습니다. 함정.


사실 이것의 작동 원리를 완전히 이해한다면 당연히 이런 구덩이에 빠지지 않을 것입니다. 다음 상황에서 이것이 무엇을 가리키는지 살펴보겠습니다.

1. 전역 코드의 this
1 Alert(x);
// 전역 변수 x의 값은 2입니다. 🎜>

전역 범위에서 이는 브라우저의 창인 전역 개체를 가리킵니다.

2. 간단한 함수로 호출

function fooCoder(x) {
this.x = x;
}
fooCoder(2);
alert(x) ;
//전역변수 x의 값은 2

여기서는 전역 객체, 즉 윈도우를 가리킨다. 엄격 모드에서는 정의되지 않습니다.

3. 메소드를 객체로 호출

var name = "clever coder";
var person = {
name : "foocoder",
hello : function(sth) {
console.log(this.name + " say " + sth);
}
}
person.hello("hello world");

출력 foocoder는 hello world를 말합니다. 이는 현재 객체인 person 객체를 가리킵니다.

4. 생성자

1 new FooCoder();

함수 내부의 이는 새로 생성된 객체를 가리킵니다.

5. 내부 함수
var name = "clever coder";

var person = {

name : "foocoder",
hello : function( sth){
var sayhello = function(sth) {
console.log(this.name + " say " + sth);
};
sayhello(
}

person.hello("hello world");

//clever coder presents hello world

내부 함수에서는 예상대로 바인딩되지 않습니다. 대신 , 이는 전역 객체에 바인딩됩니다. 이는 일반적으로 JavaScript 언어에서 설계 오류로 간주됩니다. 왜냐하면 아무도 내부 함수에서 이것을 전역 객체로 지정하는 것을 원하지 않기 때문입니다. 그 사람 또는 자기 자신이 되기로 동의함:
var name = "clever coder";
var person = {
name : "foocoder",
hello : function(sth){
var that = this;
var sayhello = function(sth) {
console.log(that.name + " say " + sth);
};
sayhello(sth);
}
}
person.hello("hello world");
//foocoder presents hello world

call을 사용하여 적용하고 설정

1 person.hello.call(person, "world");

apply는 후속 매개변수가 별도로 전달되지 않고 배열을 통해 전달된다는 점을 제외하면 호출과 유사합니다. 정의:

call( thisArg [, arg1, arg2, ... ] );

// 매개변수 목록, arg1, arg2, ...

apply(thisArg [, argArray] ) ;
// 매개변수 배열, argArray

둘 다 함수를 특정 객체에 바인딩하는 데 사용됩니다. 당연히 이때는 명시적으로 로 설정됩니다. 첫 번째 매개변수.

간단한 요약

위 사항을 간략하게 요약해보면 여섯 번째 사항만 헷갈린다는 것을 알 수 있다.

사실 다음과 같이 요약할 수 있습니다.

객체의 메소드로 함수를 호출할 때 this는 객체를 가리킵니다.

페이드 아웃 함수로 함수가 호출되면 this는 전역 개체를 가리킵니다(엄격 모드에서는 정의되지 않음).
생성자의 This는 새로 생성된 개체를 가리킵니다
중첩된 개체의 This 함수는 상위 수준 함수를 상속하지 않습니다. 필요한 경우 변수를 사용하여 상위 계층 함수의 this를 저장할 수 있습니다.

간단히 정리하면 함수에 사용하면 객체가 함수를 직접 호출할 때만 객체를 가리킵니다.
obj.foocoder();
foocoder.call(obj, ...);
foocoder.apply(obj, ...);

가기 추가

우리는 종종 다음과 같은 코드를 작성할 수 있습니다:

1 $("#some-ele").click = obj.handler;

이것이 다음에서 사용되는 경우 handler , 이것이 obj에 바인딩됩니까? 분명히 그렇지 않습니다. 할당 후 함수는 콜백에서 실행되며 이는 $("#some-div") 요소에 바인딩됩니다. 이를 위해서는 함수의 실행 환경에 대한 이해가 필요합니다. 이 글에서는 함수의 실행 환경에 대해 자세히 다루려는 것이 아니며, "Javascript Advanced 프로그래밍"에서 실행 환경 및 범위 체인에 대한 관련 소개를 참조할 수 있습니다. 여기서 제가 지적하고 싶은 것은 js 함수의 실행 환경을 이해하는 것이 이를 더 잘 이해하는 데 도움이 된다는 것입니다.

그렇다면 콜백 함수 바인딩 문제를 어떻게 해결할 수 있을까요? ES5에는 새로운 메소드인 바인딩():
fun.bind(thisArg[, arg1[, arg2[, ...]]])

thisArg

바운드 함수가 호출되면 이 매개변수는 실행 시 원래 함수의 this 지점으로 사용됩니다. new 연산자를 사용하여 바인딩된 함수를 호출하는 경우 이 매개변수는 유효하지 않습니다.

1 arg1, arg2 , ...

바운드 함수가 호출되면 이러한 매개변수와 바인딩된 함수 자체의 매개변수가 순서대로 실행될 때 원래 함수의 매개변수로 사용됩니다.


이 메소드는 바인딩 함수라는 새로운 함수를 생성합니다. 바인딩 함수는 이를 생성할 때 바인딩 메소드에 전달된 첫 번째 매개변수를 사용하고, 바인드 메소드에 전달된 두 번째 및 후속 매개변수를 사용합니다. 매개변수와 실행 시 바인딩된 함수 자체의 매개변수를 원래 함수의 매개변수로 순서대로 사용하여 원래 함수를 호출합니다.

분명히 바인딩 메서드는 위의 문제를 잘 해결할 수 있습니다.
1
2 $("#some-ele").click(person.hello.bind(person));
//해당 요소를 클릭하면 출력 foocoder에 hello world가 표시됩니다


사실 이 메서드도 시뮬레이션하기 쉽습니다. Prototype.js의 바인딩 메서드 소스 코드를 살펴보겠습니다.
Function.prototype.bind = function(){
var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift();
return function(){
return fn.apply(object ,
args.concat(Array.prototype.slice.call(arguments)));
};
};


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