이 글은 주로 생성자 상속(클래스 상속)을 소개하고 있으며, ES5, ES6의 소개도 포함하고 있습니다. 능력의 한계로 인해 부득이하게 불합리하거나 잘못된 부분이 있을 수 있으니 비판과 정정을 부탁드립니다. ~
Prototype
우선 다음 내용을 더 잘 이해할 수 있도록 인스턴스 속성/메서드와 프로토타입 속성/메서드를 간략하게 소개합니다
function Persion(name){ this.name = name; // 属性 this.setName = function(nameName){ // 实例方法 this.name = newName; } } Persion.prototype.sex = 'man'; // 向 Persion 原型中追加属性(原型方法) var persion = new Persion('张三'); // 此时我们实例化一个persion对象,看一下name和sex有什么区别
콘솔에서 지속성을 확인하고 다음과 같이 인쇄합니다.
프로토타입을 통해 추가된 원래 속성은 인스턴스 개체의 프로토타입 체인에 나타납니다.
각 개체에는 내장된 proto 개체가 있습니다. 프로토타입 체인(즉, 프로토타입 체인)
us 아래 예를 살펴보겠습니다
참고: 생성자에는 일반적으로 배열 형식의 참조 속성이 거의 없습니다. 대부분의 경우 기본 속성 + 메서드입니다.
function Animal(n) { // 声明一个构造函数 this.name = n; // 实例属性 this.arr = []; // 实例属性(引用类型) this.say = function(){ // 实例方法 return 'hello world'; } } Animal.prototype.sing = function() { // 追加原型方法 return '吹呀吹呀,我的骄傲放纵~~'; } Animal.prototype.pArr = []; // 追加原型属性(引用类型)
다음으로 인스턴스 속성/메서드와 프로토타입 속성/메서드의 차이점을 살펴보겠습니다.
프로토타입 개체의 목적은 각 인스턴스 개체에 대한 공유 메서드와 속성을 저장하는 것입니다. 그리고 모든 인스턴스는 동일한 프로토타입 객체를 공유하므로 인스턴스 메서드나 속성과 달리 프로토타입 객체의 복사본은 하나만 있습니다. 인스턴스가 많으며 인스턴스 속성과 메서드는 독립적입니다.
var cat = new Animal('cat'); // 实例化cat对象 var dog = new Animal('dog'); // 实例化狗子对象 cat.say === dog.say // false 不同的实例拥有不同的实例属性/方法 cat.sing === dog.sing // true 不同的实例共享相同的原型属性/方法 cat.arr.push('zz'); // 向cat实例对象的arr中追加元素;(私有) cat.pArr.push('xx'); // 向cat原型对象的pArr中追加元素;(共享) console.log(dog.arr); // 打印出 [],因为cat只改变了其私有的arr console.log(dog.pArr); // 打印出 ['xx'], 因为cat改变了与狗子(dog)共享的pArr
물론 프로토타입 속성이 기본 데이터 유형인 경우 공유되지 않습니다.
생성자에서: 속성(인스턴스 기본 속성)의 개인정보 보호와 메서드(인스턴스 참조 속성)의 재사용 및 공유를 위해. 우리는 다음을 옹호합니다:
1. 생성자에 속성 캡슐화
2. 프로토타입 객체에 대한 메소드 정의
먼저, Animal 상위 클래스 정의
function Animal(n) { this.name = n; // 实例属性 this.arr = []; // 实例属性(引用类型) this.say = function(){ // 实例方法 return 'hello world'; } } Animal.prototype.sing = function() { // 追加原型方法 return '吹呀吹呀,我的骄傲放纵~~'; } Animal.prototype.pArr = []; // 追加原型属性(引用类型)
단점: 하위 클래스 인스턴스는 상위 클래스 생성자의 참조 데이터 유형 속성을 공유합니다.
2. 생성자 차용
function Cat(n) { this.cName = n; } Cat.prototype = new Animal(); // 父类的实例作为子类的原型对象 var tom = new Cat('tom'); // 此时Tom拥有Cat和Animal的所有实例和原型方法/属性,实现了继承 var black = new Cat('black'); tom.arr.push('Im tom'); console.log(black.arr); // 打印出 ['Im tom'], 结果其方法变成了共享的,而不是每个实例所私有的,这是因为父类的实例方法/属性变成了子类的原型方法/属性了;
1. 하위 개체는 상위 개체의 인스턴스 메서드/속성을 상속합니다. 각 하위 클래스 인스턴스가 상속하는 속성은 Private입니다.
2. 하위 클래스 인스턴스를 생성할 때 매개변수를 상위 클래스 생성자에 전달할 수 있습니다.
단점: 하위 클래스 인스턴스는 상위 클래스의 구성 속성과 메서드를 상속할 수 없습니다. function Cat(n) {
this.cName = n;
Animal.call(this, this.cName); // 核心,把父类的实例方法属性指向子类
}
var tom = new Cat('tom'); // 此时Tom拥有Cat和Animal的所有实例和原型方法/属性,实现了继承
var black = new Cat('black');
tom.arr.push('Im tom');
console.log(black.arr); // 打印出 [], 其方法和属性是每个子类实例所私有的;
tom.sing(); // undefind 无法继承父类的原型属性及方法;
장점:
2 상위 클래스의 인스턴스 메서드는 상위 클래스의 프로토타입 개체에 정의되어 메서드 재사용이 가능합니다.
3. 상위 클래스의 생성자와 속성을 공유하지 마세요.
단점: 상위 클래스의 생성자가 두 번 호출됩니다.
4. 기생 조합 상속function Cat(n) {
this.cName = n;
Animal.call(this, this.cName); // 核心,把父类的实例方法属性指向子类
}
Cat.prototype = new Parent() // 核心, 父类的实例作为子类的原型对象
Cat.prototype.constructor = Cat; // 修复子类Cat的构造器指向,防止原型链的混乱
tom.arr.push('Im tom');
console.log(black.arr); // 打印出 [], 其方法和属性是每个子类实例所私有的;
tom.sing(); // 打印出 '吹呀吹呀,我的骄傲放纵~~'; 子类继承了父类的原型方法及属性
장점:
2. 하위 클래스의 인스턴스는 상위 클래스의 생성자와 속성을 공유하지 않습니다.
3. 단점: 상위 클래스와 하위 클래스가 동일한 프로토타입을 사용하므로 하위 클래스의 프로토타입 수정이 상위 클래스에 영향을 미칩니다.
5. 기생 조합 상속(단순히 완벽함)
function Cat(n) { this.cName = n; Animal.call(this, this.cName); // 核心,把父类的实例方法属性指向子类 } Cat.prototype = Parent.prototype; // 核心, 将父类原型赋值给子类原型(子类原型和父类原型,实质上是同一个) Cat.prototype.constructor = Cat; // 修复子类Cat的构造器指向,防止原型链的混乱 tom.arr.push('Im tom'); console.log(black.arr); // 打印出 [], 其方法和属性是每个子类实例所私有的; tom.sing(); // 打印出 '吹呀吹呀,我的骄傲放纵~~'; 子类继承了父类的原型方法及属性 tom.pArr.push('publish'); // 修改继承于父类原型属性值 pArr; console.log(black.pArr); // 打印出 ['publish'], 父类的原型属性/方法 依旧是共享的, // 至此简直是完美呀~~~ 然鹅! Cat.prototype.childrenProp = '我是子类的原型属性!'; var parent = new Animal('父类'); console.log(parent.childrenProp); // 打印出'我是子类的原型属性!' what? 父类实例化的对象拥有子类的原型属性/方法,这是因为父类和子类使用了同一个原型
function Cat(n) { this.cName = n; Animal.call(this, this.cName); // 核心,把父类的实例方法属性指向子类; } var F = function(){}; // 核心,利用空对象作为中介; F.prototype = Parent.prototype; // 核心,将父类的原型赋值给空对象F; Cat.prototype = new F(); // 核心,将F的实例赋值给子类; Cat.prototype.constructor = Cat; // 修复子类Cat的构造器指向,防止原型链的混乱; tom.arr.push('Im tom'); console.log(black.arr); // 打印出 [], 其方法和属性是每个子类实例所私有的; tom.sing(); // 打印出 '吹呀吹呀,我的骄傲放纵~~'; 子类继承了父类的原型方法及属性; tom.pArr.push('publish'); // 修改继承于父类原型属性值 pArr; console.log(black.pArr); // 打印出 ['publish'], 父类的原型属性/方法 依旧是共享的; Cat.prototype.childrenProp = '我是子类的原型属性!'; var parent = new Animal('父类'); console.log(parent.childrenProp); // undefind 父类实例化的对象不拥有子类的原型属性/方法;
은 하위 개체에 대한 uber 속성을 설정하는 것을 의미하며, 이는 상위 개체의 프로토타입 속성을 직접 가리킵니다. (Uber는 "위" 또는 "한 레벨 위"를 의미하는 독일어입니다.) 이는 하위 개체에 대한 채널을 여는 것과 동일하며 상위 개체의 메서드를 직접 호출할 수 있습니다. 이 줄은 상속의 완전성을 달성하기 위해 여기에 배치되었으며 순전히 백업 목적으로 사용됩니다. ES6 상속 방법
function extend(Child, Parent) { var F = function(){}; F.prototype = Parent.prototype; hild.prototype = new F(); Child.prototype.constructor = Child; Child.uber = Parent.prototype; } // 使用 extend(Cat,Animal);관련 기사:
Child.uber = Parent.prototype;
관련 동영상:
위 내용은 js 생성자의 상속 방법과 장단점에 대한 자세한 소개(전체 코드)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!