프로토타입 체이닝:
프로토타입을 사용하여 속성과 메서드를 상속합니다. 생성자, 프로토타입, 인스턴스 간의 관계를 검토합니다. 각 생성자에는 프로토타입 객체를 가리키는 프로토타입 속성이 있습니다. 프로토타입 객체에는 함수를 가리키는 생성자 속성도 있고, 인스턴스에는 프로토타입 객체를 가리키는 내부 포인터(__proto__)도 있습니다. 이 프로토타입 객체가 다른 객체의 인스턴스라면 어떻게 될까요? 이런 방식으로 프로토타입 객체에는 다른 유형에 대한 포인터가 포함됩니다. 이에 따라 다른 프로토타입에도 다른 생성자에 대한 포인터가 포함됩니다.
JS 상속은 매우 간단합니다. 즉, 하위 클래스의 프로토타입을 상위 클래스의 (인스턴스화된) 객체로 설정합니다.
function SuperType(){
this.property = true;
}
SuperType.prototype.getSuperValue = function (){
Return this.property;
};
function SubType(){
this.subproperty = false;
}
//inherit from SuperType
SubType .prototype = new SuperType();
SubType.prototype.getSubValue = function(){
return this.subproperty;
};
var 인스턴스 = new SubType() ;
alert(instance.getSuperValue()); //true
최종 결과: 인스턴스의 __proto__는 SubType.prototype 객체를 가리키고 SubType의 __proto__ 속성은 .prototype 객체 SuperType.prototype 객체를 가리킵니다. getSuperValue()는 메소드이므로 여전히 프로토타입에 존재하고, property는 인스턴스 속성이므로 이제 SubType.prototype의 인스턴스에 존재합니다. 이제 instance.constructor는 SuperType을 가리키게 됩니다. 이는 SubType.prototype이 SuperType.prototype을 가리키고 SuperType.prototype의 생성자 속성이 SuperType 함수를 가리켜서 instance.constructor가 SuperType을 가리키기 때문입니다.
기본적으로 모든 참조 유형은 Object에서 상속됩니다. 이는 모든 함수의 프로토타입 객체가 기본적으로 Object의 인스턴스이므로 내부 프로토타입(__proto__)이 Object.Prototype을 가리키기 때문입니다.
프로토타입과 인스턴스의 관계: 프로토타입과 인스턴스의 관계를 확인하려면 두 가지 방법을 사용할 수 있습니다.
- 인스턴스f 연산자: 이 연산자를 사용하여 인스턴스 및 프로토타입 체인에 나타나는 생성자를 테스트하면 true를 반환합니다.
alert(instancestanceofObject); //true
alert(instanceinstanceofSuperType)//true
alert(instanceinstanceofSubType) ); / /true
- isPrototypeOf() 메소드: 프로토타입 체인에 나타나는 프로토타입이라면 프로토타입 체인에서 파생된 인스턴스의 프로토타입이라고 할 수 있습니다. .
alert(Object.prototype.isPrototypeOf(instance) )); //true
alert(SuperType.prototype.isPrototypeOf(instance)); //true
alert(SubType.prototype.isPrototypeOf(instance)) //true
주어진 클래스에 메소드 추가에 대한 참고 사항: 때때로 우리는 하위 클래스에 메소드를 추가하거나 상위 클래스의 일부 메소드를 재정의합니다. 이때 이러한 메소드는 상속 후에 정의해야 한다는 점에 유의해야 한다. 다음 예에서는 SubType이 SuperType을 상속한 후 여기에 새 메서드 getSubValue()를 추가하고 getSuperValue() 메서드를 다시 작성합니다. 후자의 경우 SubType 인스턴스만 재정의된 메서드를 사용하고 SuperType 인스턴스는 원래 getSuperValue() 메서드를 계속 사용합니다.
function SuperType(){
this .property = true;
}
SuperType.prototype.getSuperValue = function(){
return this.property;
};
function SubType(){
this.subproperty = false;
}
//SuperType에서 상속
SubType.prototype = new SuperType();
//새 메서드
SubType.prototype.getSubValue = function(){
return this.subproperty;
};
//기존 메소드 재정의
SubType.prototype.getSuperValue = function(){
return false;
};
var 인스턴스 = new SubType( );
alert(instance.getSuperValue()) //false
또 한 가지 주의할 점은 프로토타입 체인을 통해 상속을 구현할 때 객체 리터럴을 사용하여 프로토타입 메서드를 생성할 수 없다는 점입니다. 이렇게 하면 프로토타입 체인을 덮어쓰게 되기 때문입니다. 아래 코드에서 볼 수 있듯이 SubType은 SuperType을 상속한 후 객체 리터럴을 사용하여 프로토타입에 메서드를 추가합니다. 그러나 이렇게 하면 다시 작성된 SubType.prototype에 Object 인스턴스가 포함되어 연결이 끊어집니다. 슈퍼타입 관계.
function SuperType(){
this .property = true;
}
SuperType.prototype.getSuperValue = function(){
return this.property;
};
function SubType(){
this.subproperty = false;
}
//SuperType에서 상속
SubType.prototype = new SuperType();
//새 메서드를 추가하려고 하면 이전 줄이 무효화됩니다.
SubType.prototype = {
getSubValue: 함수(){
return this.subproperty;
},
someOtherMethod: function(){
return false;
}
};
var instance = new SubType();
alert(instance.getSuperValue()); //error!
프로토타입 체인 문제: 참조 유형을 사용할 때 프로토타입과 동일 value 때로는 프로토타입 체인에 문제가 있을 수 있습니다. 참조 유형 값을 포함하는 프로토타입 속성은 모든 인스턴스에서 공유된다는 이전 내용을 상기하세요. 이것이 바로 프로토타입이 아닌 생성자에서 참조 유형 값을 정의하는 이유입니다. 프로토타입 체인을 통해 상속이 구현되면 프로토타입은 실제로 다른 유형의 인스턴스가 되므로 원래 인스턴스 속성이 원활하게 현재 프로토타입 속성이 됩니다.
function SuperType(){
this .colors = ["red", "blue", "green"];
}
function SubType(){
}
//SuperType에서 상속
SubType.prototype = new SuperType ();
var instance1 = new SubType();
instance1.colors.push(“black”);
alert(instance1.colors); //”red,blue,green,black”
var 인스턴스2 = new SubType();
alert(instance2.colors); //"red,blue,green,black"
SuperType 생성자에서 색상 배열을 정의합니다. , 각 SuperType 인스턴스에는 자체 색상 배열이 있습니다. 그러나 SubType이 프로토타입 체인을 사용하여 SuperType을 상속하는 경우 SubType.prototype은 SuperType의 인스턴스가 되므로 고유한 색상 속성, 즉 SubType.prototype.colors 속성을 갖습니다. 따라서 SubType 인스턴스를 생성할 때 모든 인스턴스는 이 속성을 공유합니다. 위의 코드에 표시된 것처럼.
두 번째 문제는 하위 클래스의 인스턴스를 생성할 때 매개변수를 슈퍼클래스의 생성자에 전달할 수 없다는 것입니다. 실제로 모든 객체 인스턴스에 영향을 주지 않고 슈퍼클래스 생성자에 매개변수를 전달할 수 있는 방법은 없습니다. 이러한 문제 때문에 우리는 프로토타입 체인만 사용하지 않을 것입니다.
---------------------------------- --- ---------------------
생성자 훔치기:
위 문제를 해결하기 위해 개발자들은 생성자 훔치기라는 기술을 발명했습니다. 이 기술의 기본 아이디어는 하위 유형 생성자 내부에서 상위 유형 생성자를 호출하는 것입니다. (함수란 특정 환경에서 코드를 실행하는 객체에 불과하다?) apply()나 call() 메소드를 이용하면 새로 생성된 객체에 생성자를 실행할 수 있다.
function SuperType(){
this .colors = ["빨간색", "파란색", "녹색"];
}
function SubType(){
//SuperType에서 상속
SuperType.call(this);
}
var 인스턴스1 = new SubType();
instance1.colors.push(“black”);
alert(instance1.colors); //”red,blue,green,black”
var instance2 = new SubType();
alert(instance2.colors); //"red, blue, green"
SubType의 call() 메소드를 사용하여 SuperType 생성자를 호출합니다. 실제로는 SuperType() 함수에 정의된 모든 객체 초기화 코드를 새로운 SubType 객체에 실행하는 것입니다. 결과적으로 각 SubType 인스턴스에는 colors 속성의 자체 복사본이 있습니다.
매개변수 전달: 차용된 생성자 메서드를 사용하면 하위 클래스 생성자에서 상위 클래스 생성자로 매개변수를 전달할 수 있다는 큰 이점이 있습니다.
function SuperType(name){
this.name = name;
}
function SubType(){
//인수를 전달하는 SuperType에서 상속
SuperType. call(this, “Nicholas”);
//인스턴스 속성
this.age = 29;
}
var instance = new SubType();
alert(instance.name); //"Nicholas";
alert(instance.age); //29
새 SuperType 생성자는 SuperType 매개변수 "Nicholas"를 호출하는 동안 새 매개변수 이름을 추가합니다. . 상위 유형 생성자가 하위 유형의 속성을 덮어쓰는 것을 방지하려면 상위 유형 생성자를 호출한 후 하위 클래스의 속성을 정의할 수 있습니다.
생성자 차용 문제: 메서드는 모두 생성자에 정의되어 있으므로 재사용할 수 없습니다. 게다가 상위 유형의 프로토타입에 정의된 메소드는 하위 유형에 표시되지 않습니다. 결과적으로 모든 유형은 생성자 패턴만 사용할 수 있습니다.
---------------------------------- --- ---------------------
결합 상속:
프로토타입 체인과 빌린 생성자의 장점을 결합한 상속 패턴입니다. 프로토타입 체인을 사용하여 프로토타입 속성과 메서드를 상속하고, 빌린 생성자를 사용하여 인스턴스 속성을 상속합니다. 다음 예에서와 같이 call() 메소드를 사용하여 SuperType의 생성자를 호출합니다(각 SubType 인스턴스는 고유한 이름과 색상 속성은 물론 SubType의 age 속성도 가짐). 그런 다음 SuperType 인스턴스를 SubType 프로토타입에 할당합니다. SuperType의 sayName() 메서드를 상속합니다(이 메서드는 각 인스턴스에서 공유됩니다).
function SuperType(이름){
this.name = 이름;
this.colors = ["빨간색", "파란색", "녹색"];
}
SuperType.prototype.sayName = function(){
경고(this.name);
};
function SubType(name, age){
//속성 상속
SuperType.call(this, name);
this.age = age;
}
//메소드 상속
SubType.prototype = new SuperType();
SubType.prototype.sayAge = function(){
Alert(this.age);
};
var instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black");
alert(instance1.colors) //"red,blue,green,black "
instance1.sayName(); //"Nicholas";
instance1.sayAge(); //29
var 인스턴스2 = new SubType("Greg", 27);
alert(instance2 .colors); //"빨간색,파란색,녹색"
instance2.sayName(); //"Greg";
instance2.sayAge(); //27
프로토타입 상속:
function object(o){
function F(){}
F.prototype = o;
return new F();
}
--------- -- ------------------------------------------------ -- -----------
기생 상속:
생성자와 같은 단점