首页 > ES6 中的类如何实现 protected 成员?

ES6 中的类如何实现 protected 成员?

ES6 的类不支持受保护成员,那么有什么奇巧淫技可以达到相同的效果吗?


"use strict";
var property = Symbol();
class Something {
    constructor(){
        this[property] = "hello";
    }

    test(){
      console.log(this[property]);
    }
}

var instance = new Something();

console.log(instance.property); //undefined
instance.test() //hello

这个方案可以实现,

参考:http://stackoverflow.com/questions/22156326/private-properties-in-javascript-es6-classes
https://tc39.github.io/ecma262/#sec-symbol-objects

传统方式实现就很简单了

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

  var z = this.x + this.y;
  this.printZ = function(){
    console.log(z);
  }
}

z就是类中的私有变量


应该没有吧
要么公有要么用奇技淫巧实现私有


module foo:

class Foo {
    constructor() {
        this[Foo.PROPERTY] = 'hello';
    }

    test() {
      console.log(this[Foo.PROPERTY]);
    }
}

Foo.PROPERTY = Symbol();

export default Foo;

module bar:

import Foo from '(module foo)';

class Bar extends Foo {
    test2() {
      console.log(this[Bar.PROPERTY]);
    }
}

export default Bar;

module main:

import Bar from '(module bar)';

new Bar.test2();

奇技淫巧版:

class Protectable {
    static fetchSymbols(Klass, protectedSymbols) {
        if (!(Klass instanceof this))
            throw new TypeError('PROTECTED_SYMBOLS are only accessible to sub classes');
        if (!Object.prototype.hasOwnProperty.call(Klass, 'receiver'))
            throw new TypeError('receiver is not defined on Klass');

        Object.keys(protectedSymbols).forEach(name => {
            Klass.receiver(name, protectedSymbols[name]);
        });
    }
}

Object.freeze(Protectable);
module.exports = Protectable;
const Protectable = require('./protectable.js');

const SYMBOLS = {
    NAME: Symbol(),
};

class Nameable extends Protectable {
    constructor(name) {
        super();

        this[SYMBOLS.NAME] = name;
    }
    intro() {
        console.log('My name is ' + this[SYMBOLS.NAME] + '. ');
    }
    
    static fetchSymbols(Klass, SUBCLASS_SYMBOLS) {
        super.fetchSymbols(Klass, Object.assign({}, SYMBOLS, SUBCLASS_SYMBOLS));
    }
}

Object.freeze(Nameable);
module.exports = Nameable;
const Nameable = require('./nameable.js');

const SYMBOLS = {
    NICKNAME: Symbol(),
};

class Nicknameable extends Nameable {
    constructor(name, nickname) {
        super(name);

        this[SYMBOLS.NICKNAME] = nickname;
    }
    intro() {
        console.log('I\'m ' + this[SYMBOLS.NAME] + ' and you can call me ' + this[SYMBOLS.NICKNAME] + '. ');
    }
    
    static fetchSymbols(Klass, SUBCLASS_SYMBOLS) {
        super.fetchSymbols(Klass, Object.assign({}, SYMBOLS, SUBCLASS_SYMBOLS));
    }
    static receiver(name, symbol) {
        SYMBOLS[name] = symbol;
    }
}

Nameable.fetchSymbols(Nicknameable);

Object.freeze(Nicknameable);
module.exports = Nicknameable;
const Nicknameable = require('./nicknameable.js');

const SYMBOLS = {
    JOB: Symbol(),
};

class Person extends Nicknameable {
    constructor(name, nickname, job) {
        super(name, nickname)
        this[SYMBOLS.JOB] = job;
    }
    intro() {
        console.log('I\'m ' + this[SYMBOLS.NICKNAME] + ', who is a(n) ' + this[SYMBOLS.JOB] + '. ');
    }

    static fetchSymbols(Klass, SUBCLASS_SYMBOLS) {
        super.fetchSymbols(Klass, Object.assign({}, SYMBOLS, SUBCLASS_SYMBOLS));
    }
    static receiver(name, symbol) {
        SYMBOLS[name] = symbol;
    }
}

Nicknameable.fetchSymbols(Person);

Object.freeze(Person);
module.exports = Person;
const Person = require('./person.js');

let person = new Person('Steven Paul Jobs', 'Steve Jobs', 'inventor');

person.intro();

【热门文章】
【热门文章】