>웹 프론트엔드 >JS 튜토리얼 >자바스크립트 객체지향 기능_자바스크립트 기술

자바스크립트 객체지향 기능_자바스크립트 기술

WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB원래의
2016-05-16 18:37:571061검색

1. 자바스크립트의 유형
---------
자바스크립트는 객체 기반 언어이지만 객체(Object)는 자바스크립트의 첫 번째 유형이 아닙니다. JS
는 Function을 첫 번째 유형으로 하는 언어입니다. 이는 JS의 함수가 고급언어의 함수의 다양한 특징을 가지고 있을 뿐만 아니라, JS에서는 Object도 함수로 구현하기 때문입니다. ——이 점에 대해서는
의 "구성 및 파괴" 섹션에서 자세한 설명을 볼 수 있습니다.

JS는 약한 유형이고 내장 유형은 간단하고 명확합니다.
------------ - ------------------
정의되지 않음 : 정의되지 않음
숫자 : 숫자
부울 : 부울 값
문자열: 문자열
함수: 함수
객체: 객체

1) 정의되지 않은 유형
=============== =======
IE5 이하에서는 직접 할당과 typeof()를 제외하고 undefine에 대한 다른 작업은
예외를 발생시킵니다. 변수가 정의되지 않았는지 여부를 알아야 하는 경우 typeof() 메서드만 사용할 수 있습니다.



그러나 IE5.5 이상에서는 정의되지 않음이 구현된 시스템 예약어입니다. 따라서
비교 및 ​​연산에는 undefine을 사용할 수 있습니다. 값이 정의되지 않았는지 확인하는 더 간단한 방법은 다음과 같습니다.



따라서 핵심 코드를 (부분적으로) IE5 및 이전 버전과 호환되도록 하려면 다음과 같은 코드 줄이 있습니다. Romo 코어 유닛을
정의되지 않은 값으로 "선언"하려면:
//------------------ ---- ----------
// JSEnhance.js에 있는 Qomolangma의 코드
//----- ----- ------------------- --
var undefine = void null;

이 코드에서 또 한 가지 설명해야 할 점이 있는데, 바로 void 문을 적용한 것입니다. void는 "다음 명령문을 실행하고
반환 값을 무시합니다"를 의미합니다. 따라서 실행될 수 있는 "단일" 명령문은 void 뒤에 나타날 수 있습니다. 실행 결과는 <script> <BR>var v; <BR>if (typeof(v) == 'undefined') { <BR>// ... <BR>} <BR></script>정의되지 않습니다. 물론 원한다면 아래 코드 중 하나를 사용하여 "정의되지 않은 정의"를 수행할 수도 있습니다.
//---------------------------------- ------------
// 1. 익명의 빈 함수를 사용하여
을 반환하는 좀 더 복잡한 방법//------------ -- ------------------------------
var undefine = 함수 (){}()

//----------------------------------- -----------
// 2. 코드는 단순하지만 이해하기 쉽지 않습니다
//---- - ------------------------------------------------- - --
var undefine = void 0;

void도 함수처럼 사용할 수 있으므로 void(0)도 가능합니다. 때로는 일부 복잡한 명령문에서는 void 키워드 형식
을 사용할 수 없지만 void 함수 형식을 사용해야 합니다. 예:
//------------------------------- ------ ---
// void() 형식의 복잡한 표현을 사용해야 합니다
//------ ---------- --------------
void(i=1) ; // 또는 다음 명령문:
void(i=1, i )

2). =========== =======
JavaScript는 항상 부동 소수점 숫자를 처리하므로 Delphi의 MaxInt와 같은 상수는 없지만 대신 다음과 같은 두 개의 상수 값 정의가 있습니다.
:
Number.MAX_VALUE : JScript가 표현할 수 있는 가장 큰 숫자를 반환합니다. 대략 1.79E 308과 같습니다.
Number.MIN_VALUE: JScript에서 0에 가장 가까운 숫자를 반환합니다. 대략 2.22E-308과 같습니다.

정수 유형이 없기 때문에 CSS 및 DOM 속성에 대한 일부 작업에서 값이 정수 2일 것으로 예상되는 경우
문자열 "2.0" 또는 이와 유사한 결과를 얻을 수 있습니다. 이 점에 관해서. 이 경우 전역 객체(Gobal)의 parseInt() 메서드에
을 사용해야 할 수도 있습니다.

전역 객체(Gobal)에는 숫자 유형 연산과 관련된 두 가지 속성이 있습니다.
NaN: 산술 표현식의 결과가 숫자가 아닌 경우 NaN 값이 반환됩니다.
무한대: MAX_VALUE보다 큰 숫자입니다.

값이 NaN인 경우 전역 개체(Gobal)의 isNaN() 메서드를 통해 감지할 수 있습니다. 그러나 두 NaN
값은 서로 동일하지 않습니다. 예를 들면 다음과 같습니다.
//---------------------------- ------- ---------------
//NaN 연산 및 감지
//---------------- ------ -----------
var
v1 = 10 * 'a';
v2 = 10 * 'a';
document.writeln(isNaN(v1))
document.writeln(isNaN(v2)); writeln(v1 == v2 );

전역 객체(Gobal)의 Infinity는 가장 큰 숫자(Number.MAX_VALUE)보다 큰 값을 나타냅니다. JS에서
는 수학 연산에서 양의 무한대와 동일한 값을 갖습니다. ——일부 실제 기술에서는
배열 시퀀스의 경계 감지를 수행하는 데에도 사용할 수 있습니다.

무한대는 Number 객체에서 POSITIVE_INFINITY로 정의됩니다. 또한 음의 무한대는 Number:
Number.POSITIVE_INFINITY: 가장 큰 양수(Number.MAX_VALUE)보다 큰 값으로도 정의됩니다. 양의 무한대.
Number.NEGATIVE_INFINITY : 가장 작은 음수(-Number.MAX_VALUE)보다 작은 값입니다. 음의 무한대.

NaN과 달리 두 개의 Infinity(또는 -Infinity)는 서로 동일합니다. 예를 들면 다음과 같습니다.
//---------------------------- ------- ---------------
//무한 연산 및 감지
//--------------- ------ -----------
var
v1 = Number.MAX_VALUE * 2;
document.writeln(v1);
document.writeln(v1 == v2 );

Global의 숫자 유형과 관련된 다른 메서드는 다음과 같습니다.
isFinite(): 값이 NaN/양의 무한대/음의 무한대이면 false를 반환하고, 그렇지 않으면 true를 반환합니다.
parseFloat(): (문자열의 접두사 부분)에서 부동 소수점 숫자를 가져옵니다. 실패하면 NaN이 반환됩니다.

3) 부울 유형
======================
(생략)

4) 문자열 유형
=======================
JavaScript의 문자열 유형은 원래 특별한 것은 아니지만 적응하기 위해
"브라우저 구현 하이퍼텍스트 환경"으로 변경되었으므로 이상한 방법이 있습니다. 예:
link(): String 객체의 텍스트 양쪽 끝에 HREF 속성이 포함된 하이퍼링크 태그
를 배치합니다.
big(): String 개체의 텍스트 양쪽 끝에
태그 쌍을 배치합니다.
다음 메소드는 이와 유사합니다.
anchor() blink()
bold() fixed()
fontcolor()
fontsize()
italics ()
small()
strike()
sub()
sup()

그 외에도 문자열의 주요 복잡성은 JavaScript( )
방법. 이는 브라우저 환경을 위해 JavaScript가 제공하는 매우 중요한 방법이기도 합니다.예를 들어
객체를 선언하고 document.writeln()을 사용하여 객체를 출력한다면 IE에는 무엇이 표시되나요?

다음 예에서는 이 문제를 보여줍니다.
//-------------------------------- - -------------
//toString() 적용
//--------- -- ---------------------
var
s = new Object();

s.v1 = '안녕하세요,'
s.v2 = '테스트!'
document.writeln(s);
document.writeln(s.toString());

s.toString = function() {
return s.v1 s.v2;
}
document.writeln( s);

이 예에서는 객체가 자신의 toString() 메서드
를 다시 선언(재정의)하지 않으면 문자열 유형으로 사용되는 것을 볼 수 있습니다(예: writeln) , Java Script
환경의 기본 toString()이 호출됩니다. 그러면 JavaScript가 이 객체를 이해하는 방식을 재정의할 수 있습니다
.

많은 JavaScript 프레임워크는 "템플릿" 메커니즘을 구현할 때 이 기능을 활용합니다. 예를 들어
다음과 같이 FontElement 개체를 정의합니다.
//-------------------------------- - -------------
// toString()을 사용하여 템플릿 메커니즘을 구현하는 간단한 원리
// ------ ------------------ ------ -
function FontElement(innerHTML) {
this.face = '宋体'
this.color = 'red'// 더보기...

var ctx = innerHTML;
this.toString = function() {
return '
' ctx
'
'; 🎜>
var obj = new FontElement('테스트입니다.');

// 다음 코드 줄 작성에 주의하세요
document.writeln(obj)

5) 함수 유형
=====================================
자바스크립트 함수에는 다음 기능 외에도 많은 기능이 있습니다. 객체 지향 부분(이에 대해서는 나중에 설명함), 고유한 기능 중 일부도 널리 사용됩니다.

우선 JavaScript의 모든 함수는 호출 프로세스 중에 인수 개체를 가질 수 있습니다. 이
객체는 스크립트 해석 환경에 의해 생성되므로 인수 객체를 직접 생성할 수 있는 다른 방법은 없습니다.

인수는 배열로 간주할 수 있습니다. 길이 속성을 가지며 각 매개변수는 인수[n]
을 통해 액세스할 수 있습니다. 하지만 가장 중요한 것은 callee 속성을 통해
을 실행하는 함수 객체에 대한 참조를 얻을 수 있다는 점입니다.

다음 질문이 흥미로워집니다. Function 객체에는 현재
함수를 호출하는 상위 함수 객체에 대한 참조를 가리키는 호출자 속성이 있습니다.

- JavaScript에서 호출 수신자/호출자를 통해
기간의 호출 스택을 탐색할 수 있음을 확인했습니다. 인수는 실제로 함수의 속성이므로
실행 호출 스택에서 각 함수의 매개변수를 순회할 수 있습니다. 아래 코드는 간단한 예입니다.

//--------------------------------- - -------
//콜 스택 순회
//--------------- ------ ------------------ ----
function foo1(v1, v2) {
foo2(v1 * 100)
}

function foo2(v1) {
foo3(v1 * 200) ;
}

function foo3(v1) {
var foo = 인수.callee;
while (foo && (foo != window)) {
document.writeln(' 호출 매개변수:
', ' ---------------
')

var args = foo.arguments, argn = args.length
for (var i=0; idocument.writeln('args[', i, ']: ', args[i], '
')
}
document.writeln('
');
// 이전 레벨
foo = foo.caller;
}

// 테스트 실행
foo1(1 , 2);

2. JavaScript 객체 지향 지원
---------
이전 예에서는 실제로 "유형 선언" 및 "인스턴스" 객체 유형 생성".
JavaScript에서는 함수를 통해 객체 유형을 선언해야 합니다.
//--------------- -- ----------------
//JavaScript의 객체 유형 선언을 위한 형식 코드
// (향후 문서에서 "객체 이름"은 일반적으로 MyObject로 대체됩니다)
//-------------------------------- - --------------
함수 객체 이름(매개변수 목록) {
this.property = 초기값; >
this.method = function (메서드 매개변수 목록) {
//메서드 구현 코드
}
}

그러면 다음과 같은 코드를 통해 이 객체를 생성할 수 있습니다. 유형:
//------------------------------- ------ -----
//인스턴스 생성을 위한 형식 코드
// (향후 문서에서는 "인스턴스 변수 이름" 일반적으로 obj로 대체됨)
//----------------------------------------- ------ -----------
var 인스턴스 변수 이름 = 새 개체 이름(매개변수 목록)

다음으로 "의 몇 가지 구체적인 구현과 이상한 점을 살펴보겠습니다. 객체"를 JavaScript 특성으로 사용합니다.

1) JavaScript의 객체 지향 메커니즘에서 함수의 5가지 정체성
------
MyObject()와 같은 "객체 이름" - 이 함수는 다음 언어 역할:
(1) 일반 함수
(2) 유형 선언
(3) 유형 구현
(4) 클래스 참조
(5) 객체 생성자

일부 프로그래머(예: Delphi 프로그래머)는 유형 선언을 구현과 별도로 유지하는 데 익숙합니다. 예를 들어, 델파이
에서 인터페이스 섹션은 유형이나 변수를 선언하는 데 사용되는 반면, 구현 섹션은
유형의 구현 코드 또는 실행을 위한 일부 함수 및 코드 프로세스를 작성하는 데 사용됩니다.

그러나 JavaScript에서는 유형 선언과 구현이 혼합되어 있습니다.
객체의 타입(클래스)은 함수를 통해 선언되며, this.xxxx는 객체가 가질 수 있는 속성이나 메소드를 나타냅니다.

이 함수는 "클래스 참조"이기도 합니다. JavaScript에서는
객체의 특정 유형을 식별해야 하는 경우 "클래스 참조"를 보유해야 합니다. ——당연히 이 함수의 이름입니다
. instanceof 연산자는 인스턴스 유형을 식별하는 데 사용됩니다. 해당 응용 프로그램을 살펴보겠습니다.
//------------ - ----------------------------------
// JavaScript의 객체 식별 유형
/ / 구문: 객체 인스턴스 인스턴스of 클래스 참조
//------------------------- ---- ---
function MyObject() {
this.data = '테스트 데이터'
}

// 여기서는 MyObject()가 생성자로 사용됩니다.
var obj = new MyObject();
var arr = new Array()

// 여기서는 MyObject가 클래스 참조로 사용됩니다. 🎜>document.writeln(obj 인스턴스of MyObject);
document.writeln(arr 인스턴스of MyObject)

==============
(To 계속)
= ==============
다음 콘텐츠:

2. JavaScript 객체 지향 지원
------ --

2) JavaScript에서 반사 메커니즘 구현
3) in 키워드를 사용한 작업
5). 키워드
6) 기타 객체지향 키워드

3. 생성 및 소멸

4. 인스턴스 및 인스턴스 참조

5. >6. 함수 컨텍스트

7. 객체 유형 확인 문제

2) JavaScript에서 반사 메커니즘 구현
------
반사 메커니즘은 다음에서 구현됩니다. for..in 구문을 통한 JavaScript. 그러나 JavaScript는
"속성", "메서드" 및 "이벤트"를 명확하게 구분하지 않습니다. 따라서 JS
에서는 유형 검사 속성이 문제입니다. 다음 코드는 for..in 및 속성 식별 사용에 대한 간단한 예입니다.
//---------------------------- --- ----------------
// JavaScript에서 for..in의 사용 및 속성 식별
//-- ------------------------------- ------ -----
var _r_event = _r_event = /^[Oo]n.*/
var colorSetting = {
메서드: 'red',
이벤트: 'blue',
property: ''
}

var obj2 = {
a_method: function() {},
a_property: 1,
onclick: 정의되지 않음
}

function propertyKind(obj, p) {
return (_r_event.test(p) && (obj[p]==undefine || typeof(obj[p]))=='function ')) ? '이벤트'
: (typeof(obj[p])=='function') ? '메서드'
: '속성'
}

var objectArr = ['window', ' obj2'];

for (var i=0; idocument.writeln('
for ', objectArr[i] , '
' );

var obj = eval(objectArr[i]) for (var p in obj) {

var kind = propertyKind(obj, p); 🎜>document.writeln( 'obj.', p, '는 ', kind.fontcolor(colorSetting[kind]), ': ', obj[p], '


')
}

document.writeln('
');
}

개발자들이 흔히 간과하는 사실은 JavaScript 자체에는 이벤트 시스템이 없다는 것입니다. 일반적으로
JavaScript에서 일반적으로 사용하는 onclick 및 기타 이벤트는 실제로 IE의 DOM 모델에서 제공됩니다. 보다 핵심적인
관점에서 보면 IE는 COM의 인터페이스 속성을 통해 일련의 이벤트 인터페이스를 DOM에 게시합니다.

JS에서 "속성이 이벤트인지 여부"를 잘 식별할 수 없는 두 가지 이유는 다음과 같습니다.
- COM 인터페이스 자체에는 메서드, 속성 및 이벤트만 있으며 모두 일련의 집합을 통해 전달됩니다. 게시할 방법을 가져오거나 설정합니다.
- JavaScript에는 독립적인 "이벤트" 메커니즘이 없습니다.

따라서 이벤트 식별 방법은 속성 이름이 'on' 문자열로 시작하는지 여부를 감지하는 것임을 알 수 있습니다('On'으로 시작하는 것이 Qomo의 관례입니다
). 다음으로, DOM 객체의 이벤트는 핸들러 함수를 지정할 필요가 없기 때문에 이 경우 이벤트 핸들은 null입니다(Qomo는 동일한 규칙을 채택합니다). 사용자는 obj2와 마찬가지로 다음 값으로 이벤트를 정의할 수 있습니다. 한정되지 않은. 따라서 "이벤트"의 판단 조건은
복잡한 표현으로 처리됩니다:
("The attribute start with on/On" && ("The value is null/undefine" || "The type is function" ))

그리고 위 코드의 실행 결과로 판단해보면. DOM 객체에 for..in을 사용하면
객체 메서드를 열거할 수 없습니다.

마지막으로 한 가지 말씀드리겠습니다. 실제로 많은 언어 구현에서 "이벤트"는 "객체 지향" 언어 기능이 아니라 특정 프로그래밍 모델에 의해 제공됩니다. 예를 들어 Delphi의 이벤트 중심 메커니즘은 Win32
운영 체제의 창 메시지 메커니즘에 의해 제공되거나 구성 요소/클래스에서
이벤트 처리 기능을 적극적으로 호출하는 사용자 코드에 의해 구현됩니다.

"이벤트"는 언어 자체의 문제가 아니라 "프로그래밍 모델을 구동하는 방법"에 대한 메커니즘/문제입니다. 하지만 PME(Property/Method/Event)를 기반으로 한 OOP 개념은 사람들의 마음 속에 깊이 뿌리내려 있기 때문에 프로그래밍 언어나 시스템이 이러한 특성을 나타내면 아무도 "이벤트"를 달성했는지에 대해 관심을 두지 않습니다.

3) this 및 키워드 사용
------
JavaScript 객체 시스템에서 this 키워드는 두 가지 위치에서 사용됩니다.
- 구성에서 변환기 함수는 새로 생성된 객체 인스턴스를 참조
- 객체의 메소드 호출 시 해당 메소드를 호출한 객체 인스턴스를 참조

함수가 객체가 아닌 일반 함수로 사용되는 경우 메서드) 호출되면 함수의 this 키워드
가 창 개체를 가리킵니다. 마찬가지로 this 키워드가 어떤 함수에도 없으면
window 객체를 가리킵니다.

자바스크립트에는 함수와 메소드의 명확한 구분이 없기 때문입니다. 그래서 일부 코드가 이상해 보입니다.
//------------------------- ----- -------
// 함수의 여러 가능한 호출 형식
//--------- ----- ------------------- --
function foo( ) {
// 아래는 이 메서드를 호출하는 객체 인스턴스를 나타냅니다.
if (this===window) {
document.write('함수를 호출합니다. ', '
') ;
}
else {
document.write('객체별로 메서드 호출: ', this.name, '
');
}

function MyObject(name) {
// 아래는 새 키워드
this.name =
this.foo = foo의 새로 생성된 인스턴스를 나타냅니다. ;
}

var obj1 = new MyObject('obj1');
var obj2 = new MyObject('obj2')

// 테스트 1:
foo()를 함수로;

// 테스트 2: 객체 메서드로 호출
obj1.foo();
obj2.foo(); 3: "지정된 개체"로 함수 호출 "메서드 호출
foo.call(obj1);
foo.apply(obj2);

위 코드에서 obj1/obj2의 foo( )은 매우 일반적인 호출 방법입니다. ——즉,
은 생성자에 함수를 객체로 지정하는 방법이다.

테스트 3의 call()과 apply()는 매우 특별합니다.

이 테스트에서 foo()는 여전히 일반 함수로 호출되지만 JavaScript 언어 기능
에서는()/apply() 호출 시 foo()를 지정하기 위해 객체 인스턴스를 전달할 수 있습니다.
의 맥락에 나타나는 this 키워드에 대한 참조입니다. ——현재 foo()는 여전히 객체 메서드 호출이 아닌 일반적인
함수 호출이라는 점에 유의해야 합니다.

은 "이 메소드를 호출하는 객체 인스턴스를 나타냅니다"와 다소 유사하며 with() 구문은
"코드에서 기본적으로 객체 인스턴스를 사용합니다"를 한정하는 데에도 사용됩니다.——with() 구문이 사용되지 않으면
이 코드는 외부 with() 문의 영향을 받습니다. 외부 with()가 없으면
" 기본 객체 인스턴스입니다. 사용되는 것은 창문이 될 것입니다.

그러나 이것과 키워드는 서로 영향을 미치지 않는다는 점에 유의해야 합니다. 다음 코드와 같습니다:
//---------------------------- - ------------------
// 테스트: 이 키워드와 키워드는 서로 영향을 미치지 않습니다.
//------------ ---------------------
function test() {
with (obj2) {
this.value = 8;
}
}
var obj2 = new Object()
obj2.value = 10;

test();
document.writeln('obj2.value: ', obj2.value, '
')
document.writeln('window.value: ', window .value, '
');

호출이 완료된 후 이러한 코드가 obj2.value 속성을 8로 설정하는 것을 기대할 수 없습니다.
코드 줄의 결과는 다음과 같습니다. 창 개체에 추가 값 속성이 있고 값은 8입니다.

with(obj){...} 구문은 obj의 기존 속성 읽기만 제한할 수 있지만 이를 적극적으로 선언할 수는
없습니다. with()의 객체에 지정된 속성이 없거나 with()가 객체가 아닌 데이터를 한정하면 결과는 예외가 됩니다.

4) in 키워드를 사용한 연산
------
객체의 멤버 정보를 반영하기 위해 for..in을 사용하는 것 외에도 JavaScript에서는 in을 직접 사용할 수도 있습니다.
객체에 지정된 이름의 속성이 있는지 감지하는 키워드입니다.

in 키워드가 자주 언급되는 이유는 속성의 존재 여부를 감지하는 능력이 아니기 때문에
초기 코드에서는 "if (!obj.propName) { }" 이 방법을 사용하면 propName
이 유효한 속성인지 감지할 수 있습니다. ——많은 경우 "속성이 존재하는지" 확인하는 것보다 유효성을 확인하는 것이
더 실용적입니다. 따라서 이 경우 in은 선택적이고 공식적인 솔루션일 뿐입니다.

in 키워드의 중요한 적용은 고속 문자열 검색입니다. 특히 "
문자열이 존재하는지 여부"만 확인하면 됩니다. 예를 들어, 100,000개의 문자열이 배열에 저장되어 있으면 검색 효율성이
매우 낮습니다.
//---------------------------------- ------------
// 개체를 사용하여 검색
//--------- --- ------------------
function arrayToObject(arr) {
for (var obj= new Object (), i=0, imax=arr.length; iobj[arr[i]]=null return obj;
var
arr = ['abc', 'def', 'ghi']; // 점점 더...
obj = arrayToObject(arr)

function valueInArray( v) {
for (var i=0, imax=arr.length; iif (arr[i]==v) return true; 🎜>return false;
}

function valueInObject(v) { return v in obj;
}

in 키워드를 사용하는 방법도 있습니다. 몇 가지 제한 사항. 예를 들어, 문자열만 찾을 수 있지만 배열 요소는 모든 값이 될 수 있습니다. 또한 arrayToObject()에는 약간의 오버헤드가 있으므로
자주 변경되는 조회 세트에 적합하지 않습니다. 마지막으로 (아시겠지만)
개체를 사용하여 검색하면 검색 데이터를 정확하게 찾을 수 없으며 배열이 결과의 아래 첨자를 가리킬 수 있습니다.

8. 자바스크립트 객체지향 지원
~~~~~~~~~~~~~~~~~~~~~
(계속)

2. 객체지향 객체 지원
---------
(계속)

5) JavaScript에서 instanceof 키워드
------
를 사용한 작업 인스턴스 유형을 감지하기 위해 instanceof 키워드가 제공됩니다. 이는 이미
이전에 "5중 정체성"을 논의할 때 논의된 바 있습니다. 그러나 instanceof의 문제는 유형을 감지하기 위해 항상 전체
프로토타입 체인을 열거한다는 것입니다(프로토타입 상속의 원리는 "구성 및 소멸" 섹션에 설명되어 있음). 예:
//-- --- ---------------------------------- ---
//instanceof 사용 시 문제
//--------------------------------- - ----------
function MyObject() {
// ...
}

function MyObject2 () {
// ...
}
MyObject2.prototype = new MyObject()

obj1 = new MyObject()
obj2 = new MyObject2( );

document.writeln(obj1 instanceof MyObject, '
');
document.writeln(obj2 instanceof MyObject, '
'); obj1과 obj2는 모두 MyObject의 인스턴스이지만 서로 다른 생성자
에 의해 생성됩니다. ——객체 지향 이론에서는 이것이 맞습니다. obj2는 MyObject의 하위 클래스 인스턴스이므로 obj1과 동일한 특성을 갖습니다. 응용 프로그램에서 이는 obj2의 다형성을 나타내는 것 중 하나입니다.

그러나 그럼에도 불구하고 우리는 다음 문제에 직면해야 합니다. obj2와 obj1이
동일한 유형의 인스턴스인지 어떻게 알 수 있습니까? ——즉, 생성자도 같다는 건가요?

instanceof 키워드는 이러한 메커니즘을 제공하지 않습니다. 이 감지를 구현하는 기능을 제공하는 것은
Object.constructor 속성입니다. --하지만 먼저 기억하세요. 생각보다 사용하기가 어렵습니다.

그럼 먼저 질문을 마치겠습니다. 생성자 속성에는 이미 "구성 및 파괴" 문제가 포함되어 있습니다.
이에 대해서는 나중에 이야기하겠습니다. "프로토타입 상속"과 "생성 및 소멸"은 JavaScript OOP
의 주요 문제이자 핵심 문제이며 "치명적인 문제"입니다.

6) null 및 정의되지 않음
------
JavaScript에서 null 및 정의되지 않음이 한 번 헷갈렸습니다. 다음 텍스트는
더 명확하게 이해하는 데 도움이 됩니다(또는 더 혼란스럽게 만듭니다).
- null은 키워드입니다. 정의되지 않은 것은 전역 개체의 속성입니다.
- null은 객체(속성 및 메소드가 없는 빈 객체)입니다. undefound는 undefine class
유형의 값입니다. 다음 코드를 시도해 보세요.
document.writeln(typeof null);
document.writeln(typeof undefine)
- 객체 모델에서 모든 객체는 Object 또는 해당 하위 클래스의 인스턴스이지만 null의 경우 예외입니다. 객체:
document.writeln(null 인스턴스of Object)
- null은 정의되지 않은 경우 "같음(==)"이지만 정의되지 않은 경우에는 "동일(===)"하지 않습니다.
document.writeln( null == 정의되지 않음);
document.writeln(null == 정의되지 않음);
- null과 undefine은 모두 작업 중에 false로 유형 변환될 수 있지만 false와 동일하지 않습니다.
document.writeln( !null, !undefine);
document.writeln(null==false);
document.writeln(undefine==false);

8. ~~~~~~~~~~~~~~~~~
(계속)

3. 제작, 파손 및 프로토타입 문제
------ ---
우리는 생성자 함수를 통해 객체를 생성해야 한다는 것을 이미 알고 있습니다. 먼저 몇 가지 사항을 기억해 봅시다.
- 생성자는 일반 함수입니다.
- 프로토타입은 객체 인스턴스입니다.
- 생성자는 프로토타입 속성을 가지지만 객체 인스턴스는 그렇지 않습니다.
- (상속인 경우 일반적으로 모델로 구현됩니다.) 객체 인스턴스의 생성자 속성은 생성자
를 가리킵니다. - 세 번째와 네 번째 항목에서 파생됩니다. obj.constructor.prototype은 객체의 프로토타입을 가리킵니다

좋습니다.
및 구성 프로세스를 사용하여 JavaScript "상속된 프로토타입" 선언을 설명하는 예제를 분석합니다.
//---------------------------------- ------------
//프로토타입, 생성, 상속 이해의 예
//------ - -------------------------------------
function MyObject() {
이것 . v1 = 'abc';
}

function MyObject2() {
this.v2 = 'def'
}
MyObject2.prototype = new MyObject(); 🎜 >
var obj1 = new MyObject();
var obj2 = new MyObject2();

1) new() 키워드의 공식 코드
------
먼저 "obj1 = new MyObject()" 코드 줄에서 new 키워드를 살펴보겠습니다.

new 키워드는 새 인스턴스를 생성하는 데 사용됩니다. (저는 예약어 키워드
를 호출하는 데 익숙하다는 점을 여기에 추가하고 싶습니다. 또한 JavaScript의 new 키워드도 연산자입니다) , 이 인스턴스의 기본 속성
은 (적어도) 생성자 함수의 프로토타입 속성(prototype)에 대한 참조를 보유합니다(ECMA Javascript
사양에서 객체의 이 속성 이름은 __proto__로 정의됨). .

생성자로 사용되는지 여부에 관계없이 모든 함수에는 고유한 프로토타입 객체가 있습니다.
JavaScript "내장 객체 생성자"의 경우 내부 프로토타입을 가리킵니다. 기본적으로 JavaScript
는 "빈 초기 객체 인스턴스(null 아님)"를 구성하고 이에 대한 프로토타입 참조를 가리킵니다. 그러나 이 함수 프로토타입에 새 개체를 할당하면 새 개체 인스턴스는 이에 대한 참조를 보유하게 됩니다.

다음으로 생성 프로세스에서는 MyObject()를 호출하여 초기화를 완료합니다. ——참고로 이것은 단지 "초기화"일 뿐입니다.

이 과정을 명확하게 설명하기 위해 이 과정을 공식적으로 설명하는 코드를 사용합니다.
//--------- - ----------------------
//new() 키워드 형식 코드
//--------------------- --- ---------
function new(aFunction) {
// 기본 객체 인스턴스
var _this = {}

// 프로토타입 참조
var _proto = aFunction.prototype;

/* ECMA 스크립트와 호환되는 경우
_this.__proto__ = _proto;
*/

// 프로토타입(내부) getter의 속성에 액세스하기 위해 추가
_this._js_GetAttributes= function(name) {
if (_existAttribute.call(this, name))
return this[name]
else if (_js_LookupProperty.call(_proto , name))
retrun OBJ_GET_ATTRIBUTES.call(_proto, name)
else
return undefine;
}

// 프로토타입 setter의 속성에 액세스하기 위해 (내부) 추가
_this._js_GetAttributes = function(이름, 값) {
if (_existAttribute.call(this, 이름))
this[name] = 값
else if (OBJ_GET_ATTRIBUTES.call(_proto, 이름) !== value) {
this[name] = value // 현재 인스턴스의 새 멤버 생성
}
}

// 생성자를 호출하여 초기화를 완료합니다. (있는 경우 ,) 전달합니다. args
aFunction.call(_this);

// Return object
return _this;
}

따라서 다음 두 가지 사항이 표시됩니다.
- 생성자(aFunction) 자체는 전달된 this 인스턴스를 "초기화"할 뿐이며
는 객체 인스턴스를 생성하지 않습니다.
- 실제로 구성 프로세스는 new() 키워드/연산자 내에서 발생합니다.

게다가 생성자(aFunction) 자체가 프로토타입을 연산할 필요도 없고 이를 반환할 필요도 없습니다.

2) 사용자 코드로 유지되는 프로토타입 체인
------
다음으로 프로토타입 체인과 구축 과정에 대해 더 자세히 논의하겠습니다.
- 프로토타입 체인은 사용자 코드에 의해 생성되며, new() 키워드는 프로토타입 체인 유지에 도움이 되지 않습니다.

델파이 코드를 예로 들면, 상속 관계를 선언할 때 다음 코드를 사용할 수 있습니다:
//---------------------------- -------- ---
// 델파이에서 사용되는 "클래스" 유형 선언
//--------- --------- --------------
type
TAnimal = class (TObject); // 동물
TMammal = class(TAnimal); // 포유류
TCanine = class(TMammal); // 개 포유류
TDog = class( TCanine); // Dog

이때 델파이 컴파일러는 컴파일 기술을 통해 상속관계 목록을 유지하게 됩니다. 다음과 유사한
코드를 통해 이 연결된 목록을 쿼리할 수 있습니다.
//------------------ ---------------
//델파이에서 상속관계 연결리스트를 사용하기 위한 키 코드
//-- - ------------------------------------------------- - ----
function isAnimal(obj: TObject): boolean;
begin
Result := obj is TAnimal
end; TDog ;

// ...
dog := TDog.Create();
writeln(isAnimal(dog))

Delphi 사용자에서 볼 수 있습니다. code 에서는 상속 관계의 연결 목록을 직접 상속할 필요가 없습니다. 이는
Delphi가 강력한 유형의 언어이기 때문입니다. class() 키워드로 선언된 유형을 처리할 때 Delphi의 컴파일러
는 이미 사용자를 위해 이러한 상속 체인을 구성했습니다. ——이 프로세스는
코드의 실행이 아니라 명령문이라는 점에 유의하세요.

JavaScript에서 객체가 특정 기본 클래스의 하위 클래스 객체인지 알아야 하는 경우
연결된 목록을 수동으로 유지 관리해야 합니다(Delphi 예와 유사). 물론 이 연결된 목록은 유형 상속 트리가 아니라 "(객체의) 프로토타입 연결 목록"이라고 합니다. ——JS에는 "class" 유형이 없습니다.

이전 JS 및 Delphi 코드를 참고하면 비슷한 예는 다음과 같습니다.
//---------- ---------------------
//JS의 "prototype linked list" 키코드
//----------------------------------------------- ----- ----------
// 1. 생성자
function Animal() {}
function Mammal()
function Canine(); {};
function Dog() {};

// 2. 프로토타입 연결 목록
Mammal.prototype = new Animal()
Canine.prototype = new Mammal();
Dog.prototype = new Canine();

// 3. 예제 함수
function isAnimal(obj) {
return obj instanceof Animal; >var
dog = new Dog();
document.writeln(isAnimal(dog))

보시다시피 JS 사용자 코드에서 "prototype linked"의 생성 방법은 다음과 같습니다. list"는 한 줄의 코드입니다:
"현재 클래스의 생성자 함수".prototype = "직접 상위 클래스의 인스턴스"

이것은 Delphi와 같은 언어와 다릅니다. 유지 관리의 본질 프로토타입 체인은 선언이 아닌 코드를 실행하는 것입니다.

그렇다면 '선언이 아니라 실행'이 무슨 뜻인가요?

JavaScript에는 컴파일 프로세스가 있습니다. 이 프로세스에서는 주로 "문법 오류 감지", "문법 선언" 및 "조건부 컴파일 명령"을 다룹니다.여기서의 "문법 선언"은 주로 함수 선언을 다룹니다. ——이것은 제가 "함수는 제1형이지만 객체는 제1형이 아니다"라고 말하는 이유 중 하나이기도 합니다.

아래 예:
//-------------------------------------- --------- --------
//함수 선언과 실행문의 관계(firefox 호환)
//--------- ---------------------------- ----------
// 1. 출력 1234
testFoo(1234)

// 2. obj1을 출력해 봅니다
// 3. 출력 obj2
testFoo(obj1);
try {
testFoo(obj2)
}
catch(e) {
document.writeln('Exception: ', e.description , '
');
}

// testFoo() 선언
function testFoo(v) {
document.writeln(v, '
')
}

// 객체 선언
var obj1 = {};
obj2 = {
toString: function() {return 'hi, object.'}
}

// 4. obj1 출력
// 5. obj2 출력
testFoo(obj1);
testFoo(obj2)

JS 환경은 다음과 같습니다.
------ ------------------
1234
정의되지 않음
예외: 'obj2' 정의되지 않음
[object Object]
안녕하세요, obj
---------------------- --------------------------
문제는 testFoo()가 선언되기 전에 실행된다는 것입니다.
"직접 선언" 형식은 선언되기 전에는 참조할 수 없습니다. ——예제에서는 두 번째와 세 번째
입력이 올바르지 않습니다.

함수는 선언 전에 참조할 수 있지만, 다른 유형의 값은 선언 후에 사용해야 합니다.
이는 JavaScript의 "선언"과 "실행 시간 참조"가 두 가지 프로세스임을 보여줍니다.

또한 "var"를 사용하여 선언할 때 컴파일러는 먼저 변수
가 존재하는지 확인하지만 변수의 값은 "정의되지 않음"이라는 것을 알 수 있습니다. ——그래서 "testFoo(obj1)"은
예외를 발생시키지 않습니다. 그러나 obj1에 대한 할당문이 실행되기 전까지는 정상적인 출력이 발생하지 않습니다.
두 번째와 세 번째 라인의 출력과 네 번째와 다섯 번째 라인의 출력 차이를 비교해 보세요.

자바스크립트는 '선언'이 아닌 '실행'을 통해 프로토타입 체인을 유지하므로, 이는 "프로토타입
체인이 컴파일러가 아닌 사용자 코드에 의해 유지된다는 의미입니다.

기반 이 추론에 대해 다음 예를 살펴보겠습니다.
//-------------------------------- -- ------------------------
// 예: 잘못된 프로토타입 체인
//--------- -- ------------------------------
// 1. 생성자
function Animal() {}; // 동물
function Mammal() {}; // 포유류
function Canine() {}; // 개 포유류 Animal

// 2. 프로토타입 체인 생성
var 인스턴스 = new Mammal();
Mammal.prototype = new Animal();
Canine.prototype = 인스턴스;

// 3. 테스트 출력
var obj = new Canine();
document.writeln(obj instanceof Animal);

이 출력을 통해 잘못된 프로토타입 체인을 볼 수 있습니다. 결과는 "개과 동물은 동물이 아닙니다"입니다. .

근본 원인은 "2. 프로토타입 체인 구성"의 다음 코드 줄이 var 및
함수처럼 컴파일 타임에 "선언"되고 이해되는 것이 아니라 해석되고 실행되기 때문입니다. 문제를 해결하는 방법은
세 줄의 코드를 수정하여 "실행 프로세스"를 논리적으로 만드는 것입니다.
//------ -- ------------------------------------
//위 예시의 수정 코드( 부분)
//-------------------------------------------- -- -----------
// 2. 프로토타입 체인 구성
Mammal.prototype = new Animal()
var instance = new Mammal(); Canine.prototype = 인스턴스;

3) 프로토타입 인스턴스가 구축 과정에서 사용되는 방식
------
아직 델파이를 예로 들어보겠습니다. 생성 과정에서 델파이는 먼저 지정된 인스턴스 크기로
"빈 객체"를 생성한 다음 속성에 하나씩 값을 할당하고 생성 프로세스에서 메서드를 호출하고 이벤트를 트리거합니다.

JavaScript의 new() 키워드에 내재된 구성 프로세스는 Delphi의 구성 프로세스와 완전히 일치하지 않습니다. 하지만
생성자 함수에서 발생하는 동작은 위와 유사합니다.
//--------------- - ---------------
//JS의 구성 과정(형식 코드)
//- --- --------------------- --- ---
function MyObject2() {
this.prop = 3;
this.method = a_method_function;

if (you_want) {
this.method( ); 🎜>this.fire_OnCreate();
}
}
MyObject2.prototype = new MyObject(); // MyObject() 선언은 생략됩니다.

var obj = new MyObject2 ( );

단일 클래스가 참조 객체로 사용되는 경우 JavaScript는 이 구성 과정에서 Delphi
와 동일한 풍부한 동작을 가질 수 있습니다. 그러나 Delphi의 구성 프로세스는 "동적"이므로 실제로
Delphi는 상위 클래스(MyObject)의 구성 프로세스도 호출하고 상위 클래스의 OnCreate() 이벤트를 트리거합니다.

JavaScript에는 그러한 기능이 없습니다. 상위 클래스의 생성 프로세스는 프로토타입(prototype
특성)에 값을 할당하는 코드 줄에서만 발생합니다. 이후에는 new MyObject2()가 아무리 많이 발생하더라도
MyObject() 생성자는 사용되지 않습니다. ——이는 또한 다음을 의미합니다.
- 생성 프로세스 중에 프로토타입 객체는 한 번 생성됩니다. 새 객체는 이 프로토타입 인스턴스에 대한 참조만 보유합니다.
(그리고 "쓰기 시 복사" 메커니즘을 사용하여 액세스합니다.) 속성) 이며 더 이상 프로토타입의 생성자를 호출하지 않습니다.

상위 클래스의 생성자가 더 이상 호출되지 않기 때문에 Delphi의 일부 기능을 JavaScript로 구현할 수 없습니다.
이는 주로 건설 단계의 일부 이벤트 및 동작에 영향을 미칩니다. ——일부 "객체 생성 프로세스 중"
코드는 상위 클래스의 생성자에 쓸 수 없습니다. 왜냐하면 하위 클래스가 몇 번이나 생성되더라도 이번에는 객체를 생성하는 과정에서 상위 클래스 생성자의 코드가 전혀 활성화되지 않기 때문입니다.

부모 클래스 속성에 대한 객체의 액세스는 프로토타입 연결 목록에 따라 다르지만
의 구성 프로세스는 정적이며 상위 클래스의 생성자에 액세스하지 않기 때문에 JavaScript의 속성 액세스는 동적입니다. ; Delphi의 일부 컴파일된 언어에서는 속성(리더와 라이터를 사용하지 않는 언어)에 대한 액세스가 정적인 반면, 객체의 생성 프로세스는 상위 클래스의 생성자를 동적으로 호출합니다.
따라서 다시 한 번 new() 키워드의 공식 코드에서 다음 줄을 명확하게 읽어보시기 바랍니다.
//--------- - ---------------------------------
//new() 키워드 형식 코드
// -------------------------------- ----- ------
function new(aFunction) {
// 프로토타입 참조
var _proto= aFunction.prototype;

// ...
}

이 과정에서 JavaScript가 하는 일은 "prototype_Ref 얻기"이고, Delphi 등 다른 언어에서 하는 일은
"Inherited Create()"입니다.

8. 자바스크립트 객체지향 지원
~~~~~~~~~~~~~~~~~~~~~
(계속)

4). 필수 사용자가 유지하는 또 다른 속성: constructor
------
이전 내용을 떠올리며 언급한 내용:
- (상속 모델이 정상적으로 구현된 경우) 객체 인스턴스의 생성자 속성 생성자 Object를 가리킵니다
- obj.constructor.prototype은 객체의 프로토타입을 가리킵니다
- Object.constructor 속성을 통해 obj2와 obj1이 동일한 유형의 인스턴스인지 여부를 감지할 수 있습니다

및 프로토타입 체인은 사용자 코드를 통해 결정되어야 합니다. 프로토타입 속성을 유지하는 것과 마찬가지로 인스턴스의 생성자 속성 생성자
도 사용자 코드로 유지해야 합니다.

JavaScript의 내장 객체의 경우 생성자 속성은 내장 생성자 함수를 가리킵니다. 예:
//------------------------------- ------ ---
// 내장 객체 인스턴스의 생성자 속성
//------------ ---------- -----------
var _object_types = {
'function' : 함수,
'boolean' : 부울,
'regexp' : RegExp,
// 'math' : 수학,
// 'debug' : 디버그,
// 'image' : 이미지;
// 'undef' : 정의되지 않음,
// 'dom' : 정의되지 않음,
// 'activex' : 정의되지 않음,
'vbarray' : VBArray,
' array' : 배열,
'string' : 문자열,
'date' : 날짜,
'error' : 오류,
'enumerator' : 열거자 ,
'number' : 숫자,
'object' : 객체
}

function objectTypes(obj) {
if (typeof obj !== 'object') return typeof obj;
if (obj == = null) return 'null';

for (var i in _object_types) {
if (obj.constructor===_object_types[i]) return i ;
}
return ' unknow';

// 테스트 데이터 및 관련 코드
function MyObject() {
}
function MyObject2() {
}
MyObject2.prototype = new MyObject();

window.execScript(''
'Function CreateVBArray()'
' Dim a(2, 2)'
' CreateVBArray = a'
'함수 종료', 'VBScript')

document.writeln('
dom

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