JavaScript中的类与继承

一、ECMAScript 5标准中的类

1、定义原型类
/* 定义Calcula类 */
var Calcula = function (x, y) {
    this.x = x;
    this.y = y;
}
/* 此处使用了Object.defineProperties方法给Calcula.prototype添加方法,是
 * 为了保证类与ES6-Class编译后的类保持相同的特性,非必需不使用也可以
 */
Object.defineProperties(Calcula.prototype,  {
    add: {
        configurable: false,
        enumerable: false,
        value: function () {
            return this.x + this.y;
        },
        writable: false
    },
    sub: {
        configurable: false,
        enumerable: false,
        value: function () {
            let x = this.x;
            let y = this.y;
            if (x > y) {
                return x - y;
            } else if (x < y) {
                return y - x;
            } else {
                return 0;
            }
        },
        writable: false
    }
});
const calcula = new Calcula(100, 900);
console.log(calcula.sub());

2、原型类继承

下面是一典型的关于原型继承的代码。

/* 创建Foo原型类的Constructor函数 */
var Foo = function (name) {
    this.name = name;
}

/* 为Foo原型类添加prototype方法*/
Foo.prototype = {
    myName: function () {
        console.log(this.name);
        return this.name;
    };
};

/* 创建Bar原型类的Constructor函数,并将this指针绑定到Foo类,使得Bar类的实例可以访问Foo类的属性和方法*/
var Bar = function (name, label) {
    Foo.call(this, name);
    this.label = label;
}

/* 创建Bar类并使用Foo.prototype对象作为新创建的Bar类的prototype对象 */
Bar.prototype = Object.create(Foo.prototype);

/* 为Bar类添加方法*/
Bar.prototype = {
    myLabel: function () {
        console.log(this.label);
        return this.label;
    };
};

const a = new Bar("编程语言JavaScript", "它是一门弱类型语言");
a.myName();
a.myLabel();

3、静态类

调用该类的静态方法不需要类的实例,该类的实例无法调用该类的任一静态方法,这也意味着类的静态方法内部的this指针是指向类本身的,而不是指向其实例。静态方法通常用于为一个应用程序创建工具函数。

var Point = function (x, y) {
    this.x = x;
    this.y = y;
};

Point.distance = function (a, b) {
    const x = a - b;
    const y = a + b;
    return Math.hypot(x, y);
};

console.log(p1.distance(10, 10));   // 因实例无法调用静态方法,所以浏览器会报错
console.log(Point.distance(p1, p2));

4、原型类扩展-继承常规对象

如果原型类要继承一个常规对象,则可以将对象设置为原型类的protoype对象。

/* 实例1:类继承常规对象(JSON)*/
var Animal = {
    hobby: ["篮球", "编程"],
    speak() {
        console.log(this.name + ' can speak English!');
        console.log(this.hobby);
    }
};
var Person = function (name) {
    this.name = name;
};
Person.prototype = Animal;
var p = new Person("小明");
p.speak();

二、ECMAScript 6标准中的类

1、类

/* 定义Greeter类,并添加Constructor构造器和greet方法  */
class Greeter {
    constructor(message) {
        this.greeting = message;
    }
    greet() {
        return "你好," + this.greeting;
    }
}
let greeter = new Greeter("world");
console.log(greeter.greet());

       声明了一个Greeter的类,它有3个成员:类的属性(greeting)、类的构造器(Constructor)、类的方法(greet)。

       当我们使用new关键字实例化Class的时候,首先会执行自己的构造器中的方法。

2、类继承

       extends关键字在类声明或类表达式中用于创建一个继承于另一个类的子类。

class Animal { 
    constructor(name) {
        this.name = name;
    }
    eat() {
        console.log(this.name + '会汪汪叫');
    }
}

class Dog extends Animal {
    constructor() {
        super();
    }
}

var d = new Dog('狗A'); 
d.eat();

       如果子类中存在构造函数,则需要在使用“this”之前首先调用super()。

3、静态类

       static关键字用来定义一个类的一个静态方法,调用该类的静态方法不需要类的实例,该类的实例无法调用该类的任一静态方法,这也意味着类的静态方法内部的this指针是指向类本身的,而不是指向其实例。静态方法通常用于为一个应用程序创建工具函数。

class Point {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }

    static distance(a, b) {
        const dx = a.x - b.x;
        const dy = a.y - b.y;

        return Math.hypot(dx, dy);
    }
}

const p1 = new Point(5, 5);
const p2 = new Point(10, 10);

console.log(p1.distance(10, 10));   // 因实例无法调用静态方法,所以浏览器会报错
console.log(Point.distance(p1, p2));

4、类扩展-类继承常规对象

       请注意,类不能扩展常规(不可构造/非构造的)对象。如果要继承常规对象,可以改用Object.setPrototypeOf():

/* 实例1:类继承常规对象(JSON)*/
const Animal = {
    hobby: ["篮球", "编程"],
    speak() {
        console.log(this.name + ' can speak English!');
        console.log(this.hobby);
    }
};
class Person {
    constructor(name) {
        this.name = name;
    }
}
// 以Animal对象作为Person类的原型对象
Object.setPrototypeOf(Person.prototype, Animal);
const d = new Person("小明");
d.speak();
/* 实例2:类继承常规对象(Array)*/
const methods = [
    "正弦",
    "余弦",
    {
        name: "小明",
        hobby: [
            "编程", "LOL"
        ]
    }
];
class Methods {
    constructor(name) {
        this.name = name;
    }
}
Object.setPrototypeOf(Methods.prototype, methods);
const methodsItem = new Methods("小明");
console.log(methodsItem[2]);
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
禁止转载,如需转载请通过简信或评论联系作者。

相关阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 176,569评论 25 709
  • 第2章 基本语法 2.1 概述 基本句法和变量 语句 JavaScript程序的执行单位为行(line),也就是一...
    悟名先生阅读 9,738评论 0 13
  • The rule is simple: if a property or a method is not foun...
    __Liu__阅读 1,184评论 0 0
  • 人生应该是一个轮回。我感觉很多事情都是重走一遭。我认识某位女顾客很久了,总是保持若即若离的关系,像日光下的影子,有...
    2668e9ad2f35阅读 3,989评论 1 0
  • 秋风真的不易, 它为了消除塑料垃圾, 忽而将其高高抛起, 忽而又狠摔在地, 或者将其卷入水里,墙角,石头的缝隙, ...
    缘wxh阅读 2,801评论 11 21

友情链接更多精彩内容