[javascript] JavaScript의 정적 변수

Javascript에서 정적 변수를 작성하는 방법



답변

클래스 기반의 정적으로 유형이 지정된 객체 지향 언어 (예 : Java, C ++ 또는 C #) 에서 온 경우 인스턴스가 아닌 “유형”과 관련된 변수 또는 메소드를 작성하려고한다고 가정합니다.

생성자 함수와 함께 “클래식”접근 방식을 사용하는 예는 기본 OO JavaScript의 개념을 이해하는 데 도움이 될 수 있습니다.

function MyClass () { // constructor function
  var privateVariable = "foo";  // Private variable 

  this.publicVariable = "bar";  // Public variable 

  this.privilegedMethod = function () {  // Public Method
    alert(privateVariable);
  };
}

// Instance method will be available to all instances but only load once in memory 
MyClass.prototype.publicMethod = function () {
  alert(this.publicVariable);
};

// Static variable shared by all instances
MyClass.staticProperty = "baz";

var myInstance = new MyClass();

staticProperty는 MyClass 객체 (함수)에 정의되어 있으며 생성 된 인스턴스와 관련이 없으며 JavaScript는 함수를 일급 객체 로 취급 하므로 객체 이므로 속성을 함수에 할당 할 수 있습니다.

업데이트 : ES6 은 키워드를 통해 클래스선언 하는 기능을 도입했습니다 class. 기존 프로토 타입 기반 상속에 대한 구문 설탕입니다.

static키워드는 쉽게 클래스에 정적 속성 또는 메서드를 정의 할 수 있습니다.

ES6 클래스로 구현 된 위의 예제를 보자.

class MyClass {
  // class constructor, equivalent to
  // the function body of a constructor
  constructor() {
    const privateVariable = 'private value'; // Private variable at the constructor scope
    this.publicVariable = 'public value'; // Public property

    this.privilegedMethod = function() {
      // Public Method with access to the constructor scope variables
      console.log(privateVariable);
    };
  }

  // Prototype methods:
  publicMethod() {
    console.log(this.publicVariable);
  }

  // Static properties shared by all instances
  static staticProperty = 'static value';

  static staticMethod() {
    console.log(this.staticProperty);
  }
}

// We can add properties to the class prototype
MyClass.prototype.additionalMethod = function() {
  console.log(this.publicVariable);
};

var myInstance = new MyClass();
myInstance.publicMethod();       // "public value"
myInstance.additionalMethod(); // "public value"
myInstance.privilegedMethod(); // "private value"
MyClass.staticMethod();             // "static value"


답변

JS 함수도 객체라는 사실을 활용할 수 있습니다. 즉, 속성을 가질 수 있습니다.

예를 들어 Javascript 의 (현재 사라진) 기사 정적 변수에 제공된 예제를 인용하십시오 .

function countMyself() {
    // Check to see if the counter has been initialized
    if ( typeof countMyself.counter == 'undefined' ) {
        // It has not... perform the initialization
        countMyself.counter = 0;
    }

    // Do something stupid to indicate the value
    alert(++countMyself.counter);
}

해당 함수를 여러 번 호출하면 카운터가 증가하는 것을 볼 수 있습니다.

그리고 이것은 전역 변수로 전역 네임 스페이스를 오염시키는 것보다 훨씬 나은 솔루션 일 것입니다.

그리고 클로저를 기반으로 한 또 다른 가능한 솔루션 이 있습니다 : javascript에서 정적 변수를 사용하는 Trick :

var uniqueID = (function() {
   var id = 0; // This is the private persistent value
   // The outer function returns a nested function that has access
   // to the persistent value.  It is this nested function we're storing
   // in the variable uniqueID above.
   return function() { return id++; };  // Return and increment
})(); // Invoke the outer function after defining it.

어떤 종류의 결과를 얻습니까? 이번을 제외하고는 증가 된 값이 표시되는 대신 반환됩니다.


답변

IIFE (즉시 호출 된 함수 표현식)를 통해 수행합니다.

var incr = (function () {
    var i = 1;

    return function () {
        return i++;
    }
})();

incr(); // returns 1
incr(); // returns 2


답변

arguments.callee를 사용하여 “정적”변수를 저장할 수 있습니다 (익명 함수에서도 유용함).

function () {
  arguments.callee.myStaticVar = arguments.callee.myStaticVar || 1;
  arguments.callee.myStaticVar++;
  alert(arguments.callee.myStaticVar);
}


답변

비슷한 답변을 두 번 보았지만 이 게시물이 가장 잘 설명되어 있다고 말씀 드리고 싶습니다.

여기에서 가져온 코드가 있습니다. 클래스의 디자인 템플릿으로 사용할 수 있기 때문에 커뮤니티에 도움이되는 완전한 예제를 얻도록 수정했습니다.

또한 귀하의 질문에 답변합니다 :

function Podcast() {

    // private variables
    var _somePrivateVariable = 123;

    // object properties (read/write)
    this.title = 'Astronomy Cast';
    this.description = 'A fact-based journey through the galaxy.';
    this.link = 'http://www.astronomycast.com';

    // for read access to _somePrivateVariable via immutableProp 
    this.immutableProp = function() {
        return _somePrivateVariable;
    }

    // object function
    this.toString = function() {
       return 'Title: ' + this.title;
    }
};

// static property
Podcast.FILE_EXTENSION = 'mp3';
// static function
Podcast.download = function(podcast) {
    console.log('Downloading ' + podcast + ' ...');
};

해당 예제가 제공되면 다음과 같이 정적 속성 / 기능에 액세스 할 수 있습니다 .

// access static properties/functions
console.log(Podcast.FILE_EXTENSION);   // 'mp3'
Podcast.download('Astronomy cast');    // 'Downloading Astronomy cast ...'

그리고 객체 속성 / 기능 은 다음과 같이 간단합니다.

// access object properties/functions
var podcast = new Podcast();
podcast.title = 'The Simpsons';
console.log(podcast.toString());       // Title: The Simpsons
console.log(podcast.immutableProp());  // 123

참고 podcast.immutableProp ()에있는 것을, 우리는이 폐쇄 : _somePrivateVariable에 대한 참조가 함수 내에서 유지됩니다.

getter와 setter를 정의 할 수도 있습니다 . 이 코드 스 니펫을 살펴보십시오 ( d속성을 선언하려는 객체의 프로토 타입 y은 생성자 외부에서 볼 수없는 개인 변수입니다).

// getters and setters
var d = Date.prototype;
Object.defineProperty(d, "year", {
    get: function() {return this.getFullYear() },
    set: function(y) { this.setFullYear(y) }
});

d.year를 통해 속성 getset함수 를 정의합니다. 를 지정하지 않으면 set속성은 읽기 전용이며 수정할 수 없습니다 (설정하려고하면 오류가 발생하지 않지만 아무런 영향을 미치지 않습니다). 각 속성에는 속성 (선언 후 변경 가능) 및 속성 으로 열거 자로 사용할 수 있는 속성 writable이 있습니다 configurable( enumerable기본값) false. defineProperty예를 들어 3 번째 파라미터 를 통해 설정할 수 있습니다 enumerable: true.

유효한 것은 다음 구문입니다.

// getters and setters - alternative syntax
var obj = { a: 7,
            get b() {return this.a + 1;},
            set c(x) {this.a = x / 2}
        };

읽기 / 쓰기 가능 속성 a, 읽기 전용 속성 b및 쓰기 전용 속성 을 정의하여 속성 ca액세스 할 수 있습니다.

용법:

console.log(obj.a); console.log(obj.b); // output: 7, 8
obj.c=40;
console.log(obj.a); console.log(obj.b); // output: 20, 21

노트:

new키워드를 잊어 버렸을 때 예기치 않은 동작을 피하려면 함수에 다음을 추가하는 것이 좋습니다 Podcast.

// instantiation helper
function Podcast() {
    if(false === (this instanceof Podcast)) {
        return new Podcast();
    }
// [... same as above ...]
};

이제 다음 인스턴스화가 모두 예상대로 작동합니다.

var podcast = new Podcast(); // normal usage, still allowed
var podcast = Podcast();     // you can omit the new keyword because of the helper

‘new’문은 새로운 객체를 생성하고 모든 속성과 메소드를 복사합니다.

var a=new Podcast();
var b=new Podcast();
a.title="a"; b.title="An "+b.title;
console.log(a.title); // "a"
console.log(b.title); // "An Astronomy Cast"

또한 상황 return에 따라 생성자 함수 의 명령문 을 사용 Podcast하여 클래스가 내부적으로 의존하지만 노출되어야하는 함수를 보호하는 사용자 정의 객체를 반환하는 것이 유용 할 수 있습니다 . 이에 대해서는 기사 시리즈의 2 장 (객체)에서 자세히 설명합니다.

당신은 말할 수 ab상속 Podcast. 지금, 당신은 이후에 모두 적용 팟 캐스트에 대한 방법을 추가하는 것을 원하는 경우 ab통해 인스턴스 한을? 이 경우 .prototype다음을 사용하십시오 .

Podcast.prototype.titleAndLink = function() {
    return this.title + " [" + this.link + "]";
};

이제 전화를 a하고 b다시 :

console.log(a.titleAndLink()); // "a [http://www.astronomycast.com]"
console.log(b.titleAndLink()); // "An Astronomy Cast [http://www.astronomycast.com]"

프로토 타입에 대한 자세한 내용은 여기를 참조 하십시오 . 더 많은 상속을 원한다면 이것을 살펴 보는 것이 좋습니다 .


기사 시리즈 내가 위에서 언급 한 적이있다 추천 읽고, 그들은 또한 다음과 같은 항목을 포함한다 :

  1. 기능
  2. 사물
  3. 프로토 타입
  4. 생성자 함수에 새로운 기능 적용
  5. 게양
  6. 자동 세미콜론 삽입
  7. 정적 속성 및 방법

참고 것을 자동 세미콜론 삽입 (6.에서 언급 한) 자바 스크립트의 “기능”매우 자주 코드에서 이상한 문제의 원인에 대한 책임이있다. 따라서 기능보다는 버그로 간주합니다.

자세한 내용을 보려면 여기 에 이러한 주제에 대한 흥미로운 MSDN 기사 가 있으며 그중 일부는 더 자세한 내용을 제공합니다.

무엇이다 읽는 재미 (또한 주제는 위에서 언급 한 커버)로부터 그 기사입니다뿐만 아니라 MDN 자바 스크립트 가이드 :

JavaScript 에서 c # out매개 변수에뮬레이트 하는 방법을 알고 싶다면 여기에서 샘플 코드를DateTime.TryParse(str, out result) 찾을 수 있습니다.


당신의 그들을 IE 작업 (사용 개발자 도구를 엽니 다하지 않는 자바 스크립트에 대한 콘솔이없는 F12다음을 찾을 수 콘솔 탭을 엽니 다)는 유용 니펫을. console.log(msg);위의 예에서 사용 된 대로 사용할 수 있습니다 . Podcast기능 전에 삽입하십시오 .

편의를 위해 하나의 완전한 단일 코드 스 니펫에 위의 코드가 있습니다.


노트:

  • JavaScript 프로그래밍에 대한 몇 가지 유용한 팁, 힌트 및 권장 사항은 일반적으로 여기 (JavaScript 모범 사례)여기 ( ‘var’대 ‘let’)에서 찾을 수 있습니다. 또한 암시 적 타입 캐스트 (강제)에 대한 이 기사도 권장됩니다 .

  • 클래스를 사용하고 JavaScript로 컴파일하는 편리한 방법은 TypeScript입니다. 작동 방식을 보여주는 예제를 찾을 수 있는 놀이터 가 있습니다. 현재 TypeScript를 사용하지 않더라도 TypeScript를 JavaScript 결과와 나란히 볼 수 있기 때문에 살펴볼 수 있습니다. 대부분의 예제는 간단하지만 즉시 시도 할 수있는 Raytracer 예제도 있습니다. 특히 “클래스 사용”, “상속 사용”및 “제네릭 사용”예제를 콤보 상자에서 선택하여 살펴 보는 것이 좋습니다. JavaScript에서 즉시 사용할 수있는 멋진 템플릿입니다. Typescript는 Angular 와 함께 사용됩니다 .

  • JavaScript에서 로컬 변수, 함수 등을 캡슐화 하려면 다음과 같은 패턴을 사용하는 것이 좋습니다 (JQuery는 동일한 기술을 사용함).

<html>
<head></head>
<body><script>
    'use strict';
    // module pattern (self invoked function)
    const myModule = (function(context) {
    // to allow replacement of the function, use 'var' otherwise keep 'const'

      // put variables and function with local module scope here:
      var print = function(str) {
        if (str !== undefined) context.document.write(str);
        context.document.write("<br/><br/>");
        return;
      }
      // ... more variables ...

      // main method
      var _main = function(title) {

        if (title !== undefined) print(title);
        print("<b>last modified:&nbsp;</b>" + context.document.lastModified + "<br/>");
        // ... more code ...
      }

      // public methods
      return {
        Main: _main
        // ... more public methods, properties ...
      };

    })(this);

    // use module
    myModule.Main("<b>Module demo</b>");
</script></body>
</html>

물론, 스크립트 코드를 별도의 *.js파일 에 넣을 수 있습니다 . 이것은 예제를 짧게 유지하기 위해 인라인으로 작성되었습니다.

자체 호출 기능 (IIFE = 즉시 호출 된 함수 표현이라고도 함)은 여기에보다 자세히 설명되어 있습니다 .


답변

function Person(){
  if(Person.count == undefined){
    Person.count = 1;
  }
  else{
    Person.count ++;
  }
  console.log(Person.count);
}

var p1 = new Person();
var p2 = new Person();
var p3 = new Person();


답변

업데이트 된 답변 :

에서 ECMAScript를 6 , 당신은 사용하여 정적 함수 만들 수 있습니다 static키워드 :

class Foo {

  static bar() {return 'I am static.'}

}

//`bar` is a property of the class
Foo.bar() // returns 'I am static.'

//`bar` is not a property of instances of the class
var foo = new Foo()
foo.bar() //-> throws TypeError

ES6 클래스는 정적에 대한 새로운 의미를 도입하지 않습니다. ES5에서 다음과 같이 동일한 작업을 수행 할 수 있습니다.

//constructor
var Foo = function() {}

Foo.bar = function() {
    return 'I am static.'
}

Foo.bar() // returns 'I am static.'

var foo = new Foo()
foo.bar() // throws TypeError

FooJavaScript 함수는 객체이므로 속성에 할당 할 수 있습니다 .