Programing

Traceur를 사용하여 ES6 클래스에서 전용 메소드를 구현하는 방법

lottogame 2020. 6. 28. 18:28
반응형

Traceur를 사용하여 ES6 클래스에서 전용 메소드를 구현하는 방법


이 질문에는 이미 답변이 있습니다.

지금은 Traceur Compiler를 사용하여 ES6 기능을 활용할 수 있습니다.

ES5 에서이 물건을 구현하고 싶습니다.

function Animal() {
    var self = this,
        sayHi;

    sayHi  = function() {
        self.hi();
    };

    this.hi = function() {/* ... */}
}

현재 traceur는 지원하지 않습니다 privatepublic키워드 ( 하모니에서 ). 그리고 ES6 클래스 구문은 클래스 본문에서 간단한 var(또는 let) 문 을 사용할 수 없습니다 .

내가 찾은 유일한 방법은 클래스 선언 전에 개인을 시뮬레이션하는 것입니다. 다음과 같은 것 :

var sayHi = function() {
    // ... do stuff
};

class Animal {
...

그것은 낫지 만 아무 기대도 없지만 예상대로 매번마다 호출하거나 호출 this하지 않고 개인 메소드에 올바른 것을 전달할 수는 없습니다 .applybind

따라서 추적 프로그램 컴파일러와 호환되는 ES6 클래스의 개인 데이터를 사용할 가능성이 있습니까?


아무 없다 private, public또는 protected현재의 키워드 인 ECMAScript 6 규격은 .

따라서 Traceur는 private및을 지원하지 않습니다 public. 6to5 (현재 "Babel"이라고 함)는 실험 목적 으로이 제안실현 합니다 ( 이 토론 참조 ). 그러나 그것은 단지 제안 일뿐입니다.

이제는 개인 속성을 시뮬레이션 할 수 있습니다 WeakMap( 여기 참조 ). 또 다른 대안은 Symbol– 부동산을 통해 쉽게 접근 할 수 있기 때문에 실제 프라이버시를 제공하지는 않습니다 Object.getOwnPropertySymbols.

현재 최고의 솔루션을 IMHO하십시오. 의사 프라이버시 만 사용하십시오. 자주 apply또는 call메서드와 함께 사용하는 경우이 메서드는 개체별로 매우 다릅니다. 따라서 밑줄 접두어로 클래스에서 선언하는 것이 좋습니다.

class Animal {

    _sayHi() {
        // do stuff
    }
}

항상 일반 기능을 사용할 수 있습니다.

function myPrivateFunction() {
  console.log("My property: " + this.prop);
}

class MyClass() {
  constructor() {
    this.prop = "myProp";
    myPrivateFunction.bind(this)();
  }
}

new MyClass(); // 'My property: myProp'

현재 메소드 또는 특성을 개인으로 선언 할 방법 이 없지만 ES6 모듈은 글로벌 네임 스페이스에 없습니다 . 따라서 모듈에서 선언하고 내 보내지 않은 내용은 프로그램의 다른 부분에서는 사용할 수 없지만 런타임 동안 모듈에서 계속 사용할 수 있습니다. 따라서 개인 속성과 메서드가 있습니다 :)

다음은 예제입니다 ( test.js파일).

function tryMe1(a) {
  console.log(a + 2);
}

var tryMe2 = 1234;

class myModule {
  tryMe3(a) {
    console.log(a + 100);
  }

  getTryMe1(a) {
    tryMe1(a);
  }

  getTryMe2() {
    return tryMe2;
  }
}

// Exports just myModule class. Not anything outside of it.
export default myModule; 

다른 파일에서

import MyModule from './test';

let bar = new MyModule();

tryMe1(1); // ReferenceError: tryMe1 is not defined
tryMe2; // ReferenceError: tryMe2 is not defined
bar.tryMe1(1); // TypeError: bar.tryMe1 is not a function
bar.tryMe2; // undefined

bar.tryMe3(1); // 101
bar.getTryMe1(1); // 3
bar.getTryMe2(); // 1234

Symbol을 사용할 수 있습니다

var say = Symbol()

function Cat(){
  this[say]() // call private methos
}

Cat.prototype[say] = function(){ alert('im a private') }

PS alexpods가 올바르지 않습니다. 상속은 이름 충돌이기 때문에 개인보다는 보호를 받는다

실제로 var say = String(Math.random())대신 Symbol을 사용할 수 있습니다.

ES6에서 :

var say = Symbol()

class Cat {

  constructor(){
    this[say]() // call private
  }

  [say](){
    alert('im private')
  }

}

도움이 되길 바랍니다. :)

I. IIFE (즉시 호출 함수 표현식) 내부의 vars 함수를 선언 하면 익명 함수에서만 사용할 수 있습니다. ES6 코드를 변경해야 할 때 'var'을 사용하지 않고 "let, const"키워드를 사용하는 것이 좋습니다.

let Name = (function() {
  const _privateHello = function() {
  }
  class Name {
    constructor() {
    }
    publicMethod() {
      _privateHello()
    }
  }
  return Name;
})();

II. WeakMap 객체는 메모리 누수 문제에 유용 할 수 있습니다.

WeakMap에 저장된 변수는 인스턴스가 제거 될 때 제거됩니다. 이 기사를 확인하십시오. ( ES6 클래스의 개인 데이터 관리 )

let Name = (function() {
  const _privateName = new WeakMap();
})();

III. 모두 함께합시다.

let Name = (function() {
  const _privateName = new WeakMap();
  const _privateHello = function(fullName) {
    console.log("Hello, " + fullName);
  }

  class Name {
    constructor(firstName, lastName) {
      _privateName.set(this, {firstName: firstName, lastName: lastName});
    }
    static printName(name) {
      let privateName = _privateName.get(name);
      let _fullname = privateName.firstName + " " + privateName.lastName;
      _privateHello(_fullname);
    }
    printName() {
      let privateName = _privateName.get(this);
      let _fullname = privateName.firstName + " " + privateName.lastName;
      _privateHello(_fullname);
    }
  }

  return Name;
})();

var aMan = new Name("JH", "Son");
aMan.printName(); // "Hello, JH Son"
Name.printName(aMan); // "Hello, JH Son"

As alexpods says, there is no dedicated way to do this in ES6. However, for those interested, there is also a proposal for the bind operator which enables this sort of syntax:

function privateMethod() {
  return `Hello ${this.name}`;
}

export class Animal {
  constructor(name) {
    this.name = name;
  }
  publicMethod() {
    this::privateMethod();
  }
}

Once again, this is just a proposal. Your mileage may vary.


Have you considered using factory functions? They usually are a much better alternative to classes or constructor functions in Javascript. Here is an example of how it works:

function car () {

    var privateVariable = 4

    function privateFunction () {}

    return {

        color: 'red',

        drive: function (miles) {},

        stop: function() {}

        ....

    }

}

Thanks to closures you have access to all private functions and variabels inside the returned object, but you can not access them from outside.


As Marcelo Lazaroni has already said,

Although currently there is no way to declare a method or property as private, ES6 modules are not in the global namespace. Therefore, anything that you declare in your module and do not export will not be available to any other part of your program, but will still be available to your module during run time.

But his example didn't show how the private method could access members of the instance of the class. Max shows us some good examples of how access instance members through binding or the alternative of using a lambda method in the constructor, but I would like to add one more simple way of doing it: passing the instance as a parameter to the private method. Doing it this way would lead Max's MyClass to look like this:

function myPrivateFunction(myClass) {
  console.log("My property: " + myClass.prop);
}

class MyClass() {
  constructor() {
    this.prop = "myProp";
  }
  testMethod() {
    myPrivateFunction(this);
  }
}
module.exports = MyClass;

Which way you do it really comes down to personal preference.


I came up with what I feel is a much better solution allowing:

  • no need for 'this._', that/self, weakmaps, symbols etc. Clear and straightforward 'class' code

  • private variables and methods are really private and have the correct 'this' binding

  • No use of 'this' at all which means clear code that is much less error prone

  • public interface is clear and separated from the implementation as a proxy to private methods

  • allows easy composition

with this you can do:

function Counter() {
  // public interface
  const proxy = {
    advance,  // advance counter and get new value
    reset,    // reset value
    value     // get value
  }
	
  // private variables and methods
  let count=0;
    
  function advance() {
    return ++count;
  }
    	
  function reset(newCount) {
    count=(newCount || 0);
  }
    	
  function value() {
    return count;
  }
    
  return proxy;
}
    	
let counter=Counter.New();
console.log(counter instanceof Counter); // true
counter.reset(100);
console.log('Counter next = '+counter.advance()); // 101
console.log(Object.getOwnPropertyNames(counter)); // ["advance", "reset", "value"]
<script src="https://cdn.rawgit.com/kofifus/New/7987670c/new.js"></script>

see New for the code and more elaborate examples including constructor and composition

참고URL : https://stackoverflow.com/questions/27849064/how-to-implement-private-method-in-es6-class-with-traceur

반응형