>  기사  >  웹 프론트엔드  >  John Resig 구문 분석 간단한 JavaScript 상속 code_javascript 팁

John Resig 구문 분석 간단한 JavaScript 상속 code_javascript 팁

WBOY
WBOY원래의
2016-05-16 17:47:36997검색

작가가 자신의 학습과 활용을 위해 번역에 자신의 이해를 더할 예정이므로, 영어에 능숙한 학생들은 다음 내용을 읽어도 됩니다. 기사에 번역 오류가 있으면 소통하고 수정해 주세요. (:
====== ===============에네인 번역====================== ====

John Resig는 base2 및 PrototypeJS에서 영감을 받아 다른 언어와 유사한 JavaScript의 "상속"에 관한 기사를 작성했습니다. 그는 기사의 이름을 "Simple JavaScript Inheritance"로 지정했습니다.
당신 자세한 설명은 원문을 참조하세요. 책에서는 전역 변수를 생성하는 대신 하위 클래스를 추가하는 방법도 있습니다. .
원본 스크립트 - John Resig Simple JavaScript Inheritance
아래는 용서 코드입니다. 더 명확하게 보이도록 일부 주석을 제거했습니다.

코드 복사 코드는 다음과 같습니다.

(function(){
var 초기화 = false, fnTest = /xyz/.test( function(){xyz;} ) ? /b_superb/ : /.*/;
this.Class = function(){};
Class.extend = function(prop) {
var _super = this .prototype;
초기화 중 = true;
var 프로토타입 = new this();
초기화 = false;
for(prop의 var 이름) {
prototype[name] = typeof prop[ name] == "함수" &&
typeof _super[name] == "function" && fnTest.test(prop[name]) ?
(function(name, fn){
return function() {
var tmp = this._super;
this._super = _super[이름];
var ret = fn.apply(this, 인수);
this._super = tmp;
return ret;
} ;
})(이름, prop[이름]) :
prop[이름];
}
function Class() {
if ( !initializing && this.init )
this.init.apply(this, 인수);
}
Class.prototype = 프로토타입;
Class.constructor = 클래스;
Class.extend = 인수.callee ;
return Class;
};
})();

단순 상속 스크립트 분석
어떻게 구현되고 어떤 기술이 사용되는지 분석해 보겠습니다.

코드 복사 코드는 다음과 같습니다.

(function(){ // .. . }) ();

먼저 자체 실행 익명 함수를 만들어 코드 범위를 만듭니다.

코드 복사 코드는 다음과 같습니다.
 
var 초기화 = false

이 초기화 변수의 의미는 매우 간단합니다. 클래스 함수(나중에 설명)가 호출될 때 확인하는 부울입니다. 인스턴스를 생성할 때 초기화를 true/false로 설정하거나 현재 프로토타입을 가리키는 객체를 반환하기만 하면 됩니다. " 상속의 목적을 달성하기 위한 체인입니다.

인스턴스를 생성하면(초기화 == false) Class에는 init 메소드가 있으므로 init가 자동으로 실행됩니다. 또는 프로토타입에 할당하면(초기화 == true) 아무 일도 일어나지 않고 init 메서드가 실행되지 않습니다. 이는 생성자가 호출될 때마다 init 메소드를 실행하지 않아도 되도록 수행됩니다(var 프로토타입 = new this());.

코드 복사 코드는 다음과 같습니다.

fnTest = /xyz/.test(function (){ xyz;}) ? /b_superb/ : /.*/;

이 fnTest의 목적은 클래스 메소드에서 "_super()" 호출이 사용되는지 확인하는 것입니다. 이 기술을 "함수 디컴파일(function decompilation)", "함수 직렬화(function serialization)"라고도 하며, 함수 직렬화 함수가 문자열로 변환될 때 발생합니다. 이제 많은 브라우저가 toString 메서드를 지원합니다.

함수 직렬화를 테스트하기 위해 fnTest는 익명 함수 funciton(){xyz;}를 사용하여 내용을 "xyz"로 설정하고, 이를 문자열로 변환한 후 정규식을 사용하여 "xyz"를 검색합니다. true(브라우저가 함수 직렬화를 지원하는 경우) 함수가 이를 문자열로 변환하기 때문에 "xyz"도 문자열의 일부입니다. 이 경우 fnTest는 "/b_superb/"를 반환하고 다른 경우에는 "/.*/를 반환합니다. " 브라우저가 기능 직렬화를 지원하지 않는 경우 항상 true를 반환합니다. (원래 코드의 fnTest.test를 참조합니다.) fnTest 정규화 및 함수 직렬화 기술을 사용하면 "_super"가 메서드에 사용되는지 여부를 쉽게 확인할 수 있습니다. 이 특별한 방법은 부모 클래스와 자식 클래스에 동시에 나타나는 동일한 메서드를 방지하는 것입니다.

브라우저가 함수 직렬화를 지원하지 않으면 항상 true를 반환하므로 항상 _super에서 추가 작업이 수행되므로 이러한 새로운 메서드는 _super에서 사용되지 않습니다. 그러나 이는 약간의 성능 소모를 가져옵니다. 보장 모든 브라우저에서 정상적으로 실행됩니다.

코드를 복사하세요 코드는 다음과 같습니다.

이것 .Class = function(){};

빈 생성자를 만들어 전역 변수에 넣습니다. 이는 정의된 내용이 없거나 아래의 확장 메서드를 제외하고는 창 개체를 참조합니다. 클래스 변수는 전역 객체입니다.

코드 복사 코드는 다음과 같습니다.
 
클래스. 확장 = 함수( prop) { // ...}

확장 메소드와 간단한 prop(객체) 매개변수를 추가하면 새 생성자의 프로토타입과 상위 객체의 프로토타입이 반환됩니다.

코드 복사 코드는 다음과 같습니다.
var _super = this.prototype;

현재 개체의 프로토타입 개체를 _super에 저장합니다. this.prototype은 필요한 경우 상위 메서드에 액세스할 수 있습니다. super는 예약어이기 때문입니다. 아직 적용되지 않았습니다.

코드 복사 코드는 다음과 같습니다.
initializing = true;var 프로토타입 = new this (); 초기화 = false;

프로토타입 변수에 인스턴스 클래스 객체가 저장되어 있지만, 이전에 초기화가 true로 설정되어 있었기 때문에 프로토타입 변수가 할당된 후에는 init 메소드가 실행되지 않습니다. 다음 단계에서는 초기화가 false로 다시 설정됩니다. (예: 실제 인스턴스를 생성하려는 경우)


코드 복사 코드는 다음과 같습니다.
for (var name in prop) { // ...}

for 루프를 사용하여 prop의 속성과 메서드를 반복합니다. 속성은 _super의 일부 특수 처리 외에도 프로토타입 속성에 값을 할당합니다.


코드 복사 코드는 다음과 같습니다.
 
prototype[name] = typeof prop[name] == " function" && typeof _super[name] == "function" && fnTest.test(prop[name]) ? (function(name, fn){ return function() { // _super에 대한 특수 처리 }; })(name, 소품[이름] ) : 소품[이름];

prop의 각 객체를 반복할 때 (typeof prop[name] == "function") (typeof _super[name] == "function") (fnTest.test(prop[name]) = = true)
부모 클래스에 바인딩된 새 메서드와 원래 메서드를 처리하기 위해 새 메서드를 추가합니다.
위의 코드를 좀 더 명확하게 살펴보겠습니다.

코드 복사 코드는 다음과 같습니다.
 
if (typeof prop[name] == "function " && typeof _super[name] == "function" && fnTest.test(prop[name])) { 프로토타입[name] = (function(name, fn){ return function() { // _super에 대한 특수 처리 }; }) (name, prop[name]);} else { // 속성 복사 프로토타입[name] = prop[name];}

super에서 prop[name]이라는 이름을 처리할 때 사용되는 또 다른 자체 실행 익명 함수입니다. 이 함수를 반환할 때 이 변수에 대한 참조가 잘못됩니다. 루프 a)
전체를 반복하면 새 함수가 반환됩니다. 이 함수는 기본 메서드(수퍼를 통해)와 새 메서드를 처리합니다.

코드 복사 코드는 다음과 같습니다.
    
// supervar에 대한 특수 처리 tmp = this._super;this._super = _super[name];var ret = fn.apply(this , 인수);this._super = tmp;return ret;

super의 특수 처리를 위해 먼저 기존 _super 속성과 클래스의 일부 매개변수를 임시 tmp에 저장해야 합니다. 이는 _super의 기존 메소드를 덮어쓰는 것을 방지하기 위한 것입니다.
그 후에 할당합니다. tmp를 this._super에 할당하여 정상적으로 작동하도록 합니다.
다음으로 현재 개체의 this._super에 _super[name] 메서드를 할당하여 Apply를 통해 fn이 실행될 때 this ._Super()가 이
이 상위 메소드는 현재 객체에 액세스할 수도 있습니다.
마지막으로 반환 값을 RET 객체에 저장합니다.
아래에 간단한 예가 있습니다. 간단한 Foo를 생성하고 상속된 객체 Bar를 생성합니다.

코드 복사 코드는 다음과 같습니다.

var Foo = Class.extend({ qux: function() { return "Foo.qux"; }});var Bar = Foo.extend({ qux: function() { return "Bar.qux, " this._super(); }});

Foo.extends가 실행될 때 qux 메서드에 this._super가 존재하기 때문에 Bar 프로토타입의 qux는 실제로 다음과 같아야 합니다.

코드 복사 코드는 다음과 같습니다.
 
Bar.prototype.qux = function () { var tmp = this._super = Foo.prototype; .qux; var ret = (function() { return "Bar.qux, " this._super(); }).apply(this, 인수); return ret;}

스크립트에서 이 단계를 완료하면 생성자가 호출됩니다.

코드 복사 코드는 다음과 같습니다.

function Class() { if ( !initializing && this.init ) this.init.apply(this, 인수);}

이 코드는 Class를 호출하여 이전에 생성된 this.Class와 다른 새로운 생성자를 로컬 Class.extend로 생성합니다. 이 생성자는 Class.extend(예: 이전 Foo.extends)에 대한 호출을 반환합니다. new 이 생성자는 Foo()가 인스턴스화된 후에 실행됩니다.
생성자는 init() 메서드(존재하는 경우)를 자동으로 실행합니다. 위에서 언급한 대로 이 초기화 변수는 init 실행 여부를 제어합니다.

코드 복사 코드는 다음과 같습니다.
 
Class.prototype = 프로토타입;

마지막 프로토타입은 상위 클래스의 생성자 메서드에서 상위 클래스의 혼합 프로토타입 객체를 반환합니다(예: var 프로토타입 = new this()). 이 결과는 확장 함수의 for 루프를 통해 전달됩니다. >
Class.constructor = Class;
전체 프로토타입 객체를 다시 작성했기 때문에 이 네이티브 생성자를 이 유형에 저장하여 인스턴스 생성자에서 기본 모양을 유지할 수 있습니다.

코드 복사 코드는 다음과 같습니다.
 
Class.extend =args.callee;

은 인수.callee를 통해 자신을 할당합니다. 이 경우에는 "self"를 의미합니다. 실제로 기본 메서드(예: Class.extend = function 확장(prop))를 수정하면 여기서 인수.callee 사용을 피할 수 있습니다. ) 그런 다음


을 사용하여 코드를 복사할 수 있습니다.
;.return 클래스 ;


그런 다음 인스턴스는 프로토타입 객체, 생성자 속성, 확장 메서드 및 자체 실행 가능한 메서드 init를 반환합니다.!!!

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