머리말
JS는 객체 지향 약형 언어이며 상속 역시 매우 강력한 기능 중 하나입니다. 그렇다면 JS에서 상속을 구현하는 방법은 무엇입니까? 기다려 보자.
상속을 구현하려면 먼저 부모 클래스가 있어야 하며 코드는 다음과 같습니다.
// 定义一个动物类 function Animal (name) { // 属性 this.name = name || 'Animal'; // 实例方法 this.sleep = function(){ console.log(this.name + '正在睡觉!'); } } // 原型方法 Animal.prototype.eat = function(food) { console.log(this.name + '正在吃:' + food); };
Core:부모 클래스의 인스턴스를 사용합니다. 클래스를 하위 클래스의 프로토타입으로 사용
function Cat(){ } Cat.prototype = new Animal(); Cat.prototype.name = 'cat'; // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.eat('fish')); console.log(cat.sleep()); console.log(cat instanceof Animal); //true console.log(cat instanceof Cat); //true
특징:
매우 순수한 상속 관계, 인스턴스는 하위 클래스의 인스턴스이자 상위 클래스의 인스턴스이기도 합니다.
상위 클래스에 추가됨 프로토타입 메서드/프로토타입 속성 및 모든 하위 클래스에서 액세스할 수 있습니다
간단하고 구현하기 쉽습니다
단점:
하위 클래스에 속성과 메서드를 추가하려면 해당 new
Animal()
다음에 실행해야 합니다. 구문이며 생성자에 배치할 수 없습니다
다중 상속을 달성할 수 없습니다.
프로토타입 객체의 참조 속성은 모든 인스턴스에서 공유됩니다(자세한 내용은 부록 코드 참조: 예 1)
언제 하위 클래스 인스턴스를 생성하면 매개변수를 상위 클래스 생성자에 전달할 수 없습니다
권장 인덱스: ★★(3과 4의 두 가지 치명적인 결함)
핵심: 부모 클래스의 생성자 사용 하위 클래스의 인스턴스를 향상시키는 클래스는 상위 클래스의 인스턴스 속성을 하위 클래스에 복사하는 것과 같습니다(프로토타입은 사용되지 않음)
function Cat(name){ Animal.call(this); this.name = name || 'Tom'; } // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // false console.log(cat instanceof Cat); // true
Features:
하위 클래스 인스턴스가 상위 클래스 참조 속성을 공유하는 1의 문제를 해결하세요
하위 클래스 인스턴스를 생성할 때 매개 변수를 상위 클래스에 전달할 수 있습니다.
다중 상속이 가능합니다(여러 상위 클래스 개체 호출).
단점:
인스턴스는 상위 클래스의 인스턴스가 아닙니다. , 그러나 하위 클래스
의 인스턴스만 상위 클래스의 인스턴스 속성과 메서드만 상속할 수 있지만 프로토타입 속성 /Method
은 상속할 수 없습니다. 각 하위 클래스에는 상위 클래스 인스턴스의 복사본이 있습니다. 성능에 영향을 미치는 함수
추천 지수: ★★ (단점 3)
핵심: 상위 클래스 인스턴스에 새로운 기능 추가, 하위 클래스 인스턴스로 반환
function Cat(name){ var instance = new Animal(); instance.name = name || 'Tom'; return instance; } // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // true console.log(cat instanceof Cat); // false
특징:
不限制调用方式,不管是new
子类()
还是子类()
,返回的对象具有相同的效果
缺点:
实例是父类的实例,不是子类的实例
不支持多继承
推荐指数:★★
function Cat(name){ var animal = new Animal(); for(var p in animal){ Cat.prototype[p] = animal[p]; } Cat.prototype.name = name || 'Tom'; } // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // false console.log(cat instanceof Cat); // true
特点:
支持多继承
缺点:
效率较低,内存占用高(因为要拷贝父类的属性)
无法获取父类不可枚举的方法(不可枚举方法,不能使用for in 访问到)
推荐指数:★(缺点1)
核心:通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用
function Cat(name){ Animal.call(this); this.name = name || 'Tom'; } Cat.prototype = new Animal(); // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // true console.log(cat instanceof Cat); // true
特点:
弥补了方式2的缺陷,可以继承实例属性/方法,也可以继承原型属性/方法
既是子类的实例,也是父类的实例
不存在引用属性共享问题
可传参
函数可复用
缺点:
调用了两次父类构造函数,生成了两份实例(子类实例将子类原型上的那份屏蔽了)
推荐指数:★★★★(仅仅多消耗了一点内存)
核心:通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性,避免的组合继承的缺点
function Cat(name){ Animal.call(this); this.name = name || 'Tom'; } (function(){ // 创建一个没有实例方法的类 var Super = function(){}; Super.prototype = Animal.prototype; //将实例作为子类的原型 Cat.prototype = new Super(); })(); // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // true console.log(cat instanceof Cat); //true
特点:
堪称完美
缺点:
实现较为复杂
推荐指数:★★★★(实现复杂,扣掉一颗星)
示例一:
function Animal (name) { // 属性 this.name = name || 'Animal'; // 实例方法 this.sleep = function(){ console.log(this.name + '正在睡觉!'); } //实例引用属性 this.features = []; } function Cat(name){ } Cat.prototype = new Animal(); var tom = new Cat('Tom'); var kissy = new Cat('Kissy'); console.log(tom.name); // "Animal" console.log(kissy.name); // "Animal" console.log(tom.features); // [] console.log(kissy.features); // [] tom.name = 'Tom-New Name'; tom.features.push('eat'); //针对父类实例值类型成员的更改,不影响 console.log(tom.name); // "Tom-New Name" console.log(kissy.name); // "Animal" //针对父类实例引用类型成员的更改,会通过影响其他子类实例 console.log(tom.features); // ['eat'] console.log(kissy.features); // ['eat'] 原因分析: 关键点:属性查找过程 执行tom.features.push,首先找tom对象的实例属性(找不到), 那么去原型对象中找,也就是Animal的实例。发现有,那么就直接在这个对象的 features属性中插入值。 在console.log(kissy.features); 的时候。同上,kissy实例上没有,那么去原型上找。 刚好原型上有,就直接返回,但是注意,这个原型对象中features属性值已经变化了。 本文讲解了js的继承实现相关内容,更多相关内容请关注php中文网。 相关推荐:
위 내용은 js의 상속 구현의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!