Home >Web Front-end >JS Tutorial >js inherits the source code analysis of the Base class_js object-oriented
// timestamp: Tue, 01 May 2007 19:13:00
/*
base2.js - copyright 2007, Dean Edwards
http://www.opensource.org/licenses/mit-license
*/
// You know, writing a javascript library is awfully time consuming.
///////////////////// BEGIN: CLOSURE /// //////////////////
// ============================ =============================================
// base2/Base.js
// ========================================== =================================
// version 1.1
var Base = function(){
// call this method from any other method to invoke that method's ancestor
};
Base.prototype = {
extend: function(source){
//When the parameter is greater than one
if (arguments.length > 1) { // extending with a name/value pair
//Get the ancestor of proto
var ancestor = this[source];
var value = arguments[1] ;
//If value (second parameter) is function and the ancestor object exists, when base is called in the overloaded function
if (typeof value == "function" && ancestor && /bbaseb/.test (value) {
// get the underlying method
var method = value;
// override
value = function(){
var previous = this.base;
this.base = ancestor;
//Trace back to the parent class object
var returnValue = method.apply(this, arguments);
this.base = previous;
return returnValue;
} ;
value.method = method;
value.ancestor = ancestor;
}
this[source] = value;
}
else
if (source) { / / extending with an object literal Use a list of objects to extend
var extend = Base.prototype.extend;
/**
* 1. Extend prototype methods and properties 2.
*/
//If you are extending a method or property belonging to the prototype, First traverse the three methods of overloaded Object
if (Base._prototyping) {
var key, i = 0, members = ["constructor", "toString", "valueOf"];
while (key = members[i ]) {
//If these methods are overloaded
if (source[key] != Object.prototype[key]) {
/**
* Expand one by one. The reason for using call is to change the context of extend to the source this to be extended.
* is the parent class object of the new object
* /
extend.call(this, key, source[key]);
}
}
}
else
if (typeof this != "function") {
// if the object has a customized extend() method then use it
extend = this.extend || extend;
}
// copy each of the source object's properties to this object
for (key in source)
if (!Object.prototype[key]) {
extend.call(this, key, source[key]);
}
}
return this ;
},
base: Base
};
Base.extend = function(_instance, _static){ // subclass
/**
* Extended alias of Base class prototype, call this as a method
*/
var extend = Base.prototype.extend;
/**
* build the prototype, create the prototype
* Set the prototype flag
*/
Base._prototyping = true;
/**
* Create an instance of Base and initialize the inheritance part
* The inheritance method is roughly as follows:
* function A(){}
* function B(){
* this.b=[];
* }
* A.prototype=new B();//A는 B의 모든 속성과 메서드를 상속합니다.
* 이 상속 메서드에 문제가 있습니다. B에서 선언된 객체(예: b)는 다음과 같은 형식입니다. 프로토타입
* A에 의해 상속된 후 프로토타입은 B의 객체에 대한 참조를 생성합니다. 즉,
* A의 모든 인스턴스는 B의 객체를 공유합니다. (b)
* var a1= new A() >* var a2=new A();
* a1.b.push("a11")
* a2.b.push("a21"); * 이때, a1.b =a2.b=["a11","a21"],
* 여기서는
대신 proto.extend(_instance)를 사용할 수 없습니다.* Dean Edwards가 상속을 구현할 때 상위 클래스를 기반으로 인스턴스를 생성하고,
* 확장을 사용하여 인스턴스를 확장하고 마지막으로 A를 사용합니다. 프로토타입=new B(); 상속을 구현합니다
* 그러나 객체인 경우 속성을 처리하지 않습니다
* 여전히 위의 상속 결함을 피하지 않습니다
*/
var proto=new this
/**
* 클래스 인스턴스 속성 및 메소드의 프로토타입 부분이 구성되고 플래그 비트가 삭제됩니다.
*/
extend.call(proto, _instance)
/**
* 여기서 작성자는 어댑터 패턴을 사용하고 사용자 정의 생성자를 사용하여 새 클래스 객체를 생성합니다.
* 래퍼/어댑터: 특정 메서드를 통해 한 객체가 다른
* 객체를 캡슐화하거나 권한을 부여하여 인터페이스를 변경합니다. 또는 행동
*/
delete Base._prototyping ;
/**
* 생성자에 대한 참조 가져오기
*/
// 생성자 함수에 대한 래퍼 생성
/**
* klass의 Function 객체를 생성하고 사용자 정의 생성자를 호출합니다. klass는 파생 하위 클래스입니다.
* 두 가지 경우에 이 메서드를 호출합니다.
* 1. 클래스 인스턴스를 생성할 때 이때는 프로토타입 구축 단계가 아니고, 상속시 상속 메소드
* 에서 설정한 구축 메소드가 실행됩니다
* 2. 서브 클래스 파생을 위해 확장 메소드를 사용할 경우---new this
* klass 때문에 아래의 모든 속성을 얻었으므로
* new가 완료된 후에는 상위 클래스의 모든 메소드와 속성이
* proto에 포함됩니다. 이때 proto를 기반으로 프로토타입의 확장 메소드를 사용합니다.
* proto에 이 하위 클래스의 속성과 메서드를 추가하세요
*/
var constructor = proto.constructor
/* *
* var proto=new this; 상위 클래스의 생성자를 호출하고 상위 클래스의 인스턴스를 생성합니다.
* new this를 모두 사용한 후 함수는 하위 클래스 객체 생성 메서드로 리디렉션됩니다.
*/
var klass = proto.constructor = function(){
/**
* 생성자에서 기본 메서드가 호출되면
* 기본 메서드는 상위 클래스 개체의 생성자를 호출합니다. 이때
* 호출 이 코드 세그먼트가 중첩되고 메소드가 실행됩니다. 조건은 this._constructing==true
*/
if (!Base._prototyping) {
/**
*
*는 더 이상 하향 실행되지 않습니다.
*/
if (this._constructing || this.constructor == klass) { // 인스턴스화
this._constructing = true;
constructor.apply(this, 인수)
delete this ._constructing;
}
/**
*
*/
else { // 캐스팅
var object = 인수[0]
if (object != null) {
(object.extend || 확장) call(object, proto);
}
return object;
}
}// 클래스 인터페이스 구축
/**
* 상속 체인 생성
*/
for (var i in Base){
klass[i] = this[i]
}
/**
* Java의 정적 메소드와 유사한 클래스 메소드, 속성 확장
*/
klass.ancestor = this;
klass.base = Base.base;
klass.prototype = proto;
klass.toString =
/***/
extend.call(klass, _static );
// 클래스 초기화 init 함수 호출이 있는 경우
if (typeof klass.init == "function")
klass.init();
return klass;
};
// 초기화
Base = Base.extend({
constructor: function(){
this.extend(arguments[0]);
}
}, {
조상: 객체,
베이스: 베이스,
구현: function(_interface){
if (typeof _interface == "function") {
// 함수라면 호출하세요
_interface(this.prototype);
}
else {
// 확장() 메서드를 사용하여 인터페이스를 추가하세요
this.prototype.extend (_interface);
}
반환
}
});