
众所周知,JavaScript中没有“类”的概念. 但在许多环境中,有时我们需要手动实现类和继承,类似于Java. 让我们探讨如何在JS中完美地实现类和继承
我们可以简单地通过构造函数实现一个类
// 创建类
function Animal(name, sex) {
this.name = name;
this.sex = sex;
}
Animal.prototype.say = function() {
console.log('i m animal');
}
您可以直接新建实现该类的对象
// 创建对象
var cat = new Animal('cat', 'man');
console.log(cat.name)
console.log(cat.sex)
console.log(cat.say())
让我们谈谈JS中类的继承

function Cat(name, sex) {
Animal.call(this, name, sex);
}
Cat.prototype = new Animal;
var maoxian = new Cat('maoxian', 'nv');
maoxian.say();
console.log(cat.name)
console.log(cat.sex)
console.log(cat.say())
在这里我们可以看到new有一个空对象,它指向Cat原型它指向空对象,这是基于原型链的继承
特性: 基于原型链,它是父类和子类的实例
缺点: 无法实现多态继承
function Cat(name) {
Animal.call(this)
}
var maoxian = new Cat('maoxian');
console.log(maoxian.name);
console.log(maoxian.sex);
maoxian.say()
特点: 可实现多重继承

缺点: 只能继承父实例的属性和方法,不能继承原型上的属性和方法
function Cat(name){
Animal.call(this);
this.name = name || 'Tom';
}
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
// 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 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
类在ES6中可用,它也是基于prototype的语法糖. 但毫无疑问js 实现类,它使JS中的实现类变得简单

class Animal {
constructor(name) {
this.speed = 0;
this.name = name;
}
run(speed) {
this.speed += speed;
alert(`${this.name} runs with speed ${this.speed}.`);
}
stop() {
this.speed = 0;
alert(`${this.name} stopped.`);
}
}
// Inherit from Animal
class Rabbit extends Animal {
hide() {
alert(`${this.name} hides!`);
}
}
let rabbit = new Rabbit("White Rabbit");
rabbit.run(5); // White Rabbit runs with speed 5.
rabbit.hide(); // White Rabbit hides!
类为此提供超级关键字
使用超级方法(…)调用父方法
使用super(…)调用父构造函数(仅在构造函数函数中)
class Animal {
constructor(name) {
this.speed = 0;
this.name = name;
}
run(speed) {
this.speed += speed;
alert(`${this.name} runs with speed ${this.speed}.`);
}
stop() {
this.speed = 0;
alert(`${this.name} stopped.`);
}
}
class Rabbit extends Animal {
hide() {
alert(`${this.name} hides!`);
}
stop() {
super.stop(); // call parent stop
this.hide(); // and then hide
}
}
let rabbit = new Rabbit("White Rabbit");
rabbit.run(5); // White Rabbit runs with speed 5.
rabbit.stop(); // White Rabbit stopped. White rabbit hides!
class Rabbit extends Animal {
// generated for extending classes without own constructors
constructor(...args) {
super(...args);
}
}

如我们所见js 实现类,它调用父构造函数来传递所有参数. 如果我们不编写自己的构造函数,就会发生这种情况
现在我们向rabbit添加一个自定义构造函数. 除了名字,我们还设置了earlength:
class Animal {
constructor(name) {
this.speed = 0;
this.name = name;
}
// ...
}
class Rabbit extends Animal {
constructor(name, earLength) {
this.speed = 0;
this.name = name;
this.earLength = earLength;
}
// ...
}
// Doesn't work!
let rabbit = new Rabbit("White Rabbit", 10); // Error: this is not defined.
需要注意的是,在一个子类的构造函数中,这个关键字只能在调用super之后使用,否则会报告错误. 这是因为子类实例的构造基于父实例,只有super方法才能调用父实例
对于Rabbit,在使用之前需要调用super(),如下所示:
class Animal {
constructor(name) {
this.speed = 0;
this.name = name;
}
// ...
}
class Rabbit extends Animal {
constructor(name, earLength) {
super(name);
this.earLength = earLength;
}
// ...
}
// now fine
let rabbit = new Rabbit("White Rabbit", 10);
alert(rabbit.name); // White Rabbit
alert(rabbit.earLength); // 10
就这些. 实际上,类和继承在实践中很少使用. JS毕竟不是一种基于类的语言,但有时在采访中会被问到. 如果有帮助的话,请夸奖我~~
参考文章: 文章标题0
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-220680-1.html
还有那故意让老鼠咬破包长蛆的学生