js構造函數

js構造函數

前言:以前看過公司大神的代碼,發現有不少構造函數,相似Java和C#的 new 方法來實例化一個對象,感受非常受教,恰好最近在用es6,發現了用class來實現構造函數,因而總結了一下,也是回顧和提升的過程,因爲本人也是前端小白,文章可能有不少錯誤,歡迎各位大神批評指正~~前端

傳統ES5語法

// 常規方法一
    function Persion(name, age) {
        this.name = name;                // this.key 賦值,則直接掛載到Persion實例
        this.age = age;
        this.getInfo = function() {
            return {
                name: this.name,
                age: this.age
            }
        }
    }
    // 調用
    var persion = new Persion('張三', 15);
    // 此時的persion實例擁有name、age、getInfo()三個屬性及方法

    // 常規方法二
    function Persion(name, age) {
        var name = name;
        var age = age;
        var getInfo = function() {
            return {
                name: name,
                age: age,
            }
        }
        return { // 經過return將元素暴露給實例對象
            name: name,
            age: age,
            getInfo: getInfo,
        }
    }
    // 調用 
    var persion = new Persion('張三', 15);
    // 此時的persion實例擁有name、age、getInfo()三個屬性及方法

ES6

class Persion {
    constructor(name, age) { // 一個類必須有constructor方法, 若是沒有顯式定義, 一個空的constructor方法會被默認添加。
        this.name = name;
        this.age = age;
    }
    getInfo() {
        return {
            name: this.name,
            age: this.age,
        }
    }
}
// 調用
const persion = new Persion('張三', 17);
// 此時的persion實例擁有name、age、getInfo()三個屬性及方法

注:ES6 class 聲明構造函數會將全部內部元素暴露出來,但有的時候咱們但願這些方法只在內部聲明時使用,並不暴露給實例對象,在ES5中咱們能夠很方便的作到,以下栗子:es6

// ES5 實現私有方法
    // 方案一
    function Persion(name, age) {
        this.name = name;
        this.age = age;
        var print = function(){
            return name + '今年' + age + '歲了!';
        }
        this.setName = function(newName){
            this.name = newName;
        }
        this.setAge = function(newAge){
            this.age = newAge;
        }
        this.getInfo = function(){
            {
                name: name,
                age: age,
            }
        }
        this.printInfo = function(){
            console.log(print());
        }
    }
    // 實例化
    var persion = newPersion('張三', 15);
    
    // 方案二
    function Persion(name, age) {
        var name = name,
            age = age;
        // print做爲私有方法,只在內部用於生成輸出字符串,並不須要暴露到外部
        var print = function(){
            return name + '今年' + age + '歲了!';
        }
        var setName = function(newName){
            name = newName;
        }
        var setAge = function(newAge){
            age = newAge;
        }
        var getInfo = function(){
            {
                name: name,
                age: age,
            }
        }
        var printInfo = function(){
            console.log(print());
        }
        return {
            name: name,
            age: age,
            setName: setName,
            setAge: setAge,
            getInfo: getInfo,
            printInfo: printInfo,
        }
    }
    // 實例化
    var persion = newPersion('張三', 15);
    // 此時實例化的persion 將不會暴露出print方法,我我的更傾向於方案二的方法,能夠清楚的看出哪些屬性和方法須要暴露出來,也容易修改須要暴露的接口。

那麼在ES6中咱們要怎麼實現私有的方法和屬性呢?其實方法不少,但都很不友好,我只總結了三種,若是有什麼好的方法歡迎你們給我留言,不勝感激:)segmentfault

// 私有方法 變通方案
// 方案一 (其實並不算一個方法。。。)
class Persion {
    constructor(name, age) { 
        this.name = name;
        this.age = age;
    }
    _print() { // 一般以「_」開頭命名的方法爲內部私有方法
        return name + '今年' + age + '歲了!';
    }
    setName(newName) {
        this.name = newName;
    }
    setName(newAge) {
        this.age= newAge;
    }
    printInfo() {
        console.log(_print());
    }
    getInfo() {
        return {
            name: this.name,
            name: this.age,
        }
    }
}
// 實例化
const persion = new Persion('張三', 15);
// 此時persion實例仍然能獲取到_print方法,只能用來區分私用和公有方法而已;

// 方案二
// 注意若使用ES6箭頭函數則this指向的是該方法自己,而非調用它的對象,
function _print() { // 外部聲明_print 方法,在內部調用,此時_print 成爲Persion類的私有方法
    return this.name + '今年' + this.age + '歲了!';
}
class Persion {
    constructor(name, age) { 
        this.name = name;
        this.age = age;
    }
    setName(newName) {
        this.name = newName;
    }
    setName(newAge) {
        this.age= newAge;
    }
    printInfo() {
        console.log(_print());
    }
    getInfo() {
        return {
            name: this.name,
            name: this.age,
        }
    }
}
// 實例化
const persion = new Persion('張三', 15);
// 此時persion實例獲取不到_print方法;
    
// 方案三
const print = Symbol('print'); // 聲明一個Symbol值,用來作爲私有方法的名字
class Persion {
    constructor(name, age) { 
        this.name = name;
        this.age = age;
    }
    setName(newName) {
        this.name = newName;
    }
    setName(newAge) {
        this.age= newAge;
    }
    [bar]() {  // 將私有方法的名字命名爲一個Symbol值。
        return this.name + '今年' + this.age + '歲了!';
    }
    printInfo() {
        console.log([bar]()); // 調用私有方法
    }
    getInfo() {
        return {
            name: this.name,
            name: this.age,
        }
    }
}
// 實例化
const persion = new Persion('張三', 15);
// 此時persion實例獲取不到[bar]方法;

# 追更
感謝 @黒之染 的評論, 構造函數還能夠經過prototype來添加對象函數

栗子:
```
function Persion(name, age){
    this.name = name,
    this.age = age,
}
Persion.prototype.getInfo = function(){
    return {
        name: this.name,
        age: this.name,
    }
}
// 實例化
var persion = new Persion('張三');
// 此時實例化後的對象persion擁有getInfo()方法
persion.getInfo() // 輸出{name: '張三'}
```

關於js構造函數的繼承能夠看一下個人下一篇文章js構造函數(繼承方法及利弊)this

相關文章
相關標籤/搜索