전날 면접을 갔는데 gg에서 call 및 지원 사용법에 대한 질문이 있었습니다. 365일 전에 call 방법을 사용했지만 여전히 답변을 할 수 없었습니다. 그때는 오늘 자세히 정리해 보겠습니다.
호출 및 적용의 경우 해당 기능은 실행할 다른 개체에 함수를 바인딩하는 것입니다.
두 가지 모두의 형식 및 매개변수 정의:
call( thisArg [, arg1, arg2, ... ] ) // 매개변수 목록, arg1, arg2, ...
apply(thisArg [, argArray] ); // 매개변수 배열, argArray
위의 두 함수 내부의 this 포인터에는 thisArg가 할당되며, 이는 해당 함수를 다른 객체의 메서드로 실행하는 목적을 실현할 수 있습니다.
1. 간단한 통화 사용법
먼저 간단한 예(호출)를 살펴보겠습니다.
다음과 같이 코드 코드를 복사합니다.
<!doctype html>
<html>
<머리>
<title> 통화신청 </title>
</head>
<본문>
<input type="text" id="idTxt" value="입력 텍스트">
<스크립트 유형="텍스트/자바스크립트">
var 값 = "전역 변수";
함수 mFunc()
{
this.value = "멤버 var";
}
함수 gFunc()
{
경고(this.value);
}
window.gFunc();// gFunc 표시, 전역 변수
gFunc.call(window);// gFunc 표시, 전역 변수
gFunc.call(new mFunc());// mFunc 표시, var 멤버
gFunc.call(document.getElementById('idTxt'));// 요소 표시, 입력 텍스트
</script>
<스크립트 언어="자바스크립트">
var func = 새 함수()
{
this.a = "기능";
}
var func2 = 함수(x)
{
var a = "func2";
경고(this.a);
경고(x);
}
func2.call(func, "func2");// func 및 func2 표시
</script>
</body>
</html>
그러면 실행 결과는 다음과 같습니다.
글로벌 변수글로벌 변수
멤버 var
입력 텍스트
기능
기능2
테스트 환경: Google Chrome10.0.648.45
마지막으로 결과를 분석한다.
1. 전역 개체 창은 gFunc 함수를 호출하며 이는 창 개체를 가리키므로 this.value는 전역 변수입니다.
2. gFunc 함수는 호출 메소드를 호출합니다. 이는 기본적으로 첫 번째 매개변수 창 객체를 가리키므로 this.value도 전역 변수입니다.
3. 함수 gFunc는 호출 메소드를 호출합니다. 이는 mFunc의 객체인 첫 번째 매개변수인 new mFunc()를 기본값으로 합니다. 따라서 this.value는 mFunc의 멤버 변수입니다.
4. gFunc 함수는 호출 메소드를 호출합니다. 기본적으로 이는 첫 번째 매개변수 입력 텍스트 컨트롤, 즉 id='idTxt'인 컨트롤을 가리킵니다. 따라서 this.value는 입력 컨트롤의 값 입력 텍스트입니다.
5. 함수 func2는 호출 메소드를 호출합니다. 이는 기본적으로 첫 번째 매개변수 func 함수 객체이므로 this.value는 func인 this.a입니다.
6. 함수 func2는 호출 메소드를 호출합니다. 두 번째 매개변수는 함수 객체 func2의 매개변수에 속하므로, Alert(x)는 두 번째 매개변수 func2입니다.
2. 호출 상속 활용 및 개선
js는 상속을 시뮬레이션하기 위해 호출을 사용합니다.
테스트 코드:
다음과 같이 코드 코드를 복사합니다.
<!doctype html>
<html>
<머리>
<title> 전화 - 상속 신청 </title>
</head>
<본문>
<스크립트 유형="텍스트/자바스크립트">
함수 baseA()// 기본 클래스 A
{
this.member = "baseA 멤버";
this.showSelfA = 함수()
{
window.alert(this.member);
}
}
함수 baseB()// 기본 클래스 B
{
this.member = "baseB 멤버";
this.showSelfB = 함수()
{
window.alert(this.member);
}
}
function extendAB()// A와 B의 클래스 상속
{
baseA.call(this);// A를 호출합니다.
baseB.call(this);// B 호출
}
window.onload = 함수()
{
var 확장 = 새로운 확장AB();
extend.showSelfA();// A 표시
extend.showSelfB();// B 표시
}
</script>
</body>
</html>
실행 결과는 다음과 같습니다.베이스B 멤버
베이스B 멤버
테스트 환경: Google Chrome10.0.648.45
결과 분석:
예상 결과는 baseA 멤버와 baseB 멤버를 출력하는 것이어야 하지만 실제 출력은 baseB 멤버와 baseB 멤버입니다.
(IE9, 8, 6, Maxthon, Chrome, FF, Opera, Safari, 360 등의 브라우저에서 테스트해본 결과 후자: baseB 멤버)
이 시점에서는 기계가 잘못된 것이 아니므로 심층적인 분석이 필요합니다.
이는 baseB 객체를 두 번 가리키는 것이 원인이라고 쉽게 생각할 수 있지만, 정말 그럴까요?
본질을 탐구하기 위해 우리는 Chrome 브라우저의 디버깅 도구를 사용하여 중단점을 설정하고 디버그한 결과 다음과 같은 사실을 발견했습니다.
extend.showSelfA();가 호출되면 이는 extendAB를 가리킵니다(우리가 두 번 추측한 것처럼 baseB 개체를 가리키는 것이 아닙니다).
실제 이유는 baseB.call(this)에 의해 인스턴스화될 때 ExtensionAB 객체의 멤버 변수 멤버가 baseB의 멤버 멤버로 덮어쓰기 때문입니다. 베이스B 멤버.
물론 디버깅 분석의 정확성을 확인하기 위해 위의 baseA 코드를 약간 수정할 수도 있습니다.
다음과 같이 코드 코드를 복사합니다.
function baseA()// 기본 클래스 A
{
this.memberA = "baseA member"; // baseB의 멤버를 구별하기 위해 멤버를 memberA로 변경합니다.
this.showSelfA = 함수()
{
window.alert(this.memberA); // 멤버A 표시
}
}
크롬 등의 브라우저를 다시 실행해 보면 다음과 같습니다.
baseA 멤버
베이스B 멤버
결과는 우리의 기대와 동일하며 크롬 디버깅 정보도 우리의 정확성을 확인합니다.
상속 개선(프로토타입)
위의 시뮬레이션된 상속 방법은 주의 깊게 분석한 결과 최선이 아닙니다.
함수(클래스)에 멤버 메서드가 정의될 때마다 인스턴스 복사본이 발생하므로 프로토타입 프로토타입을 사용하여 개선할 수 있습니다.
개선사례는 다음과 같습니다.
다음과 같이 코드 코드를 복사합니다.
<!doctype html>
<html>
<머리>
<title> 전화 - 프로토타입 신청 </title>
</head>
<본문>
<스크립트 유형="텍스트/자바스크립트">
var클래스 = {
생성: function()// 함수 생성
{
반환 함수()
{
this.initialize.apply(this, 인수);
}
}
};
var Person = Class.create();// 클래스 Person 생성
Person.prototype = {// 프로토타입 초기화
초기화: 함수(obj1, obj2)
{
this.obj1 = obj1;
this.obj2 = obj2;
},
showSelf: 함수()
{
Alert("obj: " + this.obj1 + " 및 " + this.obj2);
}
}
// 인스턴스 클래스
var person = new Person("man", "women");// 두 개의 매개변수
person.showSelf();// 사람 표시
</script>
</body>
</html>
실행 결과는 다음과 같습니다.
obj: 남자와 여자