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、原型類繼承

下面是一典型的關于原型繼承的代碼。

/* 創(chuàng)建Foo原型類的Constructor函數(shù) */
var Foo = function (name) {
    this.name = name;
}

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

/* 創(chuàng)建Bar原型類的Constructor函數(shù),并將this指針綁定到Foo類,使得Bar類的實例可以訪問Foo類的屬性和方法*/
var Bar = function (name, label) {
    Foo.call(this, name);
    this.label = label;
}

/* 創(chuàng)建Bar類并使用Foo.prototype對象作為新創(chuàng)建的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、靜態(tài)類

調(diào)用該類的靜態(tài)方法不需要類的實例,該類的實例無法調(diào)用該類的任一靜態(tài)方法,這也意味著類的靜態(tài)方法內(nèi)部的this指針是指向類本身的,而不是指向其實例。靜態(tài)方法通常用于為一個應用程序創(chuàng)建工具函數(shù)。

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));   // 因?qū)嵗裏o法調(diào)用靜態(tài)方法,所以瀏覽器會報錯
console.log(Point.distance(p1, p2));

4、原型類擴展-繼承常規(guī)對象

如果原型類要繼承一個常規(guī)對象,則可以將對象設置為原型類的protoype對象。

/* 實例1:類繼承常規(guī)對象(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的時候,首先會執(zhí)行自己的構造器中的方法。

2、類繼承

?????? extends關鍵字在類聲明或類表達式中用于創(chuàng)建一個繼承于另一個類的子類。

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();

?????? 如果子類中存在構造函數(shù),則需要在使用“this”之前首先調(diào)用super()。

3、靜態(tài)類

?????? static關鍵字用來定義一個類的一個靜態(tài)方法,調(diào)用該類的靜態(tài)方法不需要類的實例,該類的實例無法調(diào)用該類的任一靜態(tài)方法,這也意味著類的靜態(tài)方法內(nèi)部的this指針是指向類本身的,而不是指向其實例。靜態(tài)方法通常用于為一個應用程序創(chuàng)建工具函數(shù)。

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));   // 因?qū)嵗裏o法調(diào)用靜態(tài)方法,所以瀏覽器會報錯
console.log(Point.distance(p1, p2));

4、類擴展-類繼承常規(guī)對象

?????? 請注意,類不能擴展常規(guī)(不可構造/非構造的)對象。如果要繼承常規(guī)對象,可以改用Object.setPrototypeOf():

/* 實例1:類繼承常規(guī)對象(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:類繼承常規(guī)對象(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]);
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。

相關閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,978評論 25 709
  • 第2章 基本語法 2.1 概述 基本句法和變量 語句 JavaScript程序的執(zhí)行單位為行(line),也就是一...
    悟名先生閱讀 4,546評論 0 13
  • The rule is simple: if a property or a method is not foun...
    __Liu__閱讀 153評論 0 0
  • 人生應該是一個輪回。我感覺很多事情都是重走一遭。我認識某位女顧客很久了,總是保持若即若離的關系,像日光下的影子,有...
    2668e9ad2f35閱讀 784評論 1 0
  • 秋風真的不易, 它為了消除塑料垃圾, 忽而將其高高拋起, 忽而又狠摔在地, 或者將其卷入水里,墻角,石頭的縫隙, ...
    緣wxh閱讀 393評論 11 21

友情鏈接更多精彩內(nèi)容