JavaScript의 정적 변수


716

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


"dispaly : none"스타일 속성으로 레이블 또는 다른 html 태그를 정의하고이 값에 대한 변수 값과이 값에 대한 조작을 설정할 수 있습니다. 열심히하지 말자
asghar 2019

내가 찾은 가장 간단한 해결책 : 클래스에서 정적 변수를 전혀 정의하지 마십시오. 정적 변수를 사용하려는 경우, 단지 예를 들어, 다음 거기를 정의하고 someFunc = () => { MyClass.myStaticVariable = 1; }. 그런 다음 정적 메소드를 작성하여 정적 멤버를 리턴하십시오 (예 :) static getStatic() { return MyClass.myStaticVariable; }. 그런 다음 MyClass.getStatic()클래스 외부에서 호출 하여 정적 데이터를 유지할 수 있습니다!
픽셀

답변:


863

클래스 기반의 정적으로 유형이 지정된 객체 지향 언어 (예 : 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"


5
아마도 privilegedMethodMyClass 인스턴스에서 호출 될 수있는 것처럼 보이기 때문에 OO의 개인 메소드와 같지 않을까요? 액세스 할 수 있기 때문에 권한이 있음을 의미 privateVariable합니까?
Dónal

3
this.constructor"인스턴스 메소드"에서 정적 변수에 액세스하는 데 사용할 수 없습니까 ? 그렇다면 대답에 추가 할 가치가 있습니다.
Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功

1
예제에서 정적 함수 를 언급 할 수도 있습니다 .
David Rodrigues

18
안녕하세요, 나는이 줄에 동의하지 않습니다 // 모든 인스턴스가 공유하는 정적 변수 'MyClass.staticProperty = "baz";' 에 관해서는 를 추론 당신이 'myInstance.staticProperty'에서 바즈 찾을 수 있다고하는 과정의 당신은 할 수 없습니다.
fullstacklife

5
아마도 MyClass.prototype.staticProperty = "baz";정적 속성은 실제로 익명 함수로 정의되어 MyClass.prototype.staticProperty = function () {return staticVar;}모든 변수가 단일 변수에 액세스하여 세터로 변경할 수 있도록 OO 원칙을 읽 거나 훨씬 더 정확해야합니다 .
lindsaymacvean

535

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.

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


50
바로 가기로, countMyself.counter = countMyself.counter || initial_value;정적 변수가 거짓이 아닌 경우 (false, 0, null 또는 빈 문자열)
Kip

3
약간 더 짧고 명확합니다. (function () {var id = 0; function uniqueID () {return id ++;};}) ();
Tom Robinson

3
Firefox의 클래스보다 클로저 인 카운터가 매우 빠릅니다. jsperf.com/static-counter-in-class-vs-in-closure
Sony Santos

사용 ===을위한 typeof검사는 다른 몇 가지 이상한 강압에가는거야.
dewd

@SonySantos 테스트 쇼 파이어 폭스 (40)에 대한 반대
BARTOLO-otrit

96

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

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

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

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

21
이것이 JavaScript에서 가장 관용적 인 방법이라고 말하고 싶습니다. 다른 언어를 사용하는 사람들이 선호하는 다른 방법 덕분에 너무 많은 공짜를 얻지 못합니다.

1
'IIFE'가 아닌 'closure'를 사용하여 문구를 바꾸겠습니다.
zendka

39

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

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

3
내가 이해할 수있는 한,이 방법은 pascal MARTIN의 방법에 비해 하나의 장점 만 있습니다. 익명 함수에서 사용할 수 있습니다. 이에 대한 예가 좋을 것입니다
Dan

27
arguments.callee더 이상 사용되지 않습니다.
Quolonel Questions

나는 항상 거의 JS를 조롱했지만 callee가지고있는 것이 좋았습니다. 해킹이 왜 이것을 사용하지 않기로 결정했는지 궁금합니다 ... : |
user2173353

35

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

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

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

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 = 즉시 호출 된 함수 표현이라고도 함)은 여기에보다 자세히 설명되어 있습니다 .


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

28

업데이트 된 답변 :

에서 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 함수는 객체이므로 속성에 할당 할 수 있습니다 .


Foo.bar;주석이 암시하는 것처럼 함수가 반환 한 문자열이 아니라 할당 된 함수를 반환합니다.

두 예제에서 정적 값을 설정 (덮어 쓰기)하는 방법에 대한 정보를 추가 할 수 있습니까?
Wilt

1
@Wilt 두 경우 모두 "정적"속성은 함수의 속성 일 뿐이므로 JavaScript의 다른 속성과 마찬가지로 설정하고 덮어 씁니다. 두 경우 모두 설정할 수 bar의 속성을 Foo하기 위해 3이 같은Foo.bar = 3;
최대 Heiber


16

다음 예제와 설명은 Nicholas Zakas의 책 전문 웹 개발자를위한 전문 JavaScript 2 판입니다. 이것은 내가 찾고있는 대답이므로 여기에 추가하는 것이 도움이 될 것이라고 생각했습니다.

(function () {
    var name = '';
    Person = function (value) {
        name = value;
    };
    Person.prototype.getName = function () {
        return name;
    };
    Person.prototype.setName = function (value) {
        name = value;
    };
}());
var person1 = new Person('Nate');
console.log(person1.getName()); // Nate
person1.setName('James');
console.log(person1.getName()); // James
person1.name = 'Mark';
console.log(person1.name); // Mark
console.log(person1.getName()); // James
var person2 = new Person('Danielle');
console.log(person1.getName()); // Danielle
console.log(person2.getName()); // Danielle

Person이 예제 의 생성자는 getName()setName()메소드 와 마찬가지로 개인 변수 이름에 액세스 할 수 있습니다. 이 패턴을 사용하면 이름 변수가 정적이되어 모든 인스턴스에서 사용됩니다. 즉 setName(), 한 인스턴스를 호출 하면 다른 모든 인스턴스에 영향을줍니다. setName()Person인스턴스를 호출 하거나 만들면 이름 변수가 새 값으로 설정됩니다. 이로 인해 모든 인스턴스가 동일한 값을 반환합니다.


생성자 + 프로토 타입 (하이브리드)를 보인다
Ganesh Kumar

2
이렇게하면 Person 개체가 전역 네임 스페이스에 배치됩니다. 내가 권장하는 해결책이 아닙니다.
Ghola

이것이 각각의 새로운 객체와 다르게 인스턴스화되기 때문에 이것이 진정한 정적 변수라고 생각하지 않습니다. 정적 프로토 타입은 부모 프로토 타입에서 상속 된 모든 오브젝트에서 일관성이 있어야합니까?
lindsaymacvean

1
@Ghola 여기서 정적 변수를 만드는 방법을 설명하고자했습니다. 적절한 이름을 지정하고 글로벌을 피하는 것은 답변의 복잡성을 더할 수있는 별도의 주제입니다. 오염없이 생성자를 부착하는 방법을 결정하는 것은 사용자의 몫입니다. 니콜라스 자 카스에게 충분하다면 나에게 충분합니다.
Nate

@lindsaymacvean 단일 값이 모든 인스턴스에서 공유되므로 정적 변수입니다. 값을 변경해도됩니다. 한 인스턴스가 값을 변경하면 모든 인스턴스가 영향을받습니다. 위의 예와 정확히 동일하게 사용되지는 않습니다. 인스턴스화 중에 값을 설정하는 것은 가능하다는 것을 보여주는 것입니다. 더 유스 케이스는 getter와 setter 만 갖거나 적어도 정의되지 않은 것 이외의 것으로 설정되어 있는지 확인하는 것입니다.
Nate

15

클래스 구문 을 사용하는 경우 이제 다음을 수행 할 수 있습니다.

    class MyClass {
      static get myStaticVariable() {
        return "some static variable";
      }
    }

    console.log(MyClass.myStaticVariable);

    aMyClass = new MyClass();
    console.log(aMyClass.myStaticVariable, "is undefined");

이는 JavaScript에서 정적 변수를 효과적으로 만듭니다.


정적 유틸리티 클래스를 빌드 할 때 유용합니다!
Indolering

1
그러나 이제 문제는 어떻게 값을 유지하고 세터를 사용하여 값을 변경할 수 있는지입니다. MyClass클래스 구문 외부 에서 정의 된 클로저가 필요합니다 .
trincot


8

응용 프로그램에서 상수를 만들기 위해 정적 변수를 선언하려면 가장 간단한 접근법으로 다음을 발견했습니다.

ColorConstants = (function()
{
    var obj = {};
    obj.RED = 'red';
    obj.GREEN = 'green';
    obj.BLUE = 'blue';
    obj.ALL = [obj.RED, obj.GREEN, obj.BLUE];
    return obj;
})();

//Example usage.
var redColor = ColorConstants.RED;

8

classECMAScript 2015에 의해 도입 된 정보 . 다른 답변은 완전히 명확하지 않습니다.

여기에 정적 var에 만드는 방법을 보여주는 예입니다 staticVar와 함께 ClassName. var신택스 :

class MyClass {
    constructor(val) {
        this.instanceVar = val;
        MyClass.staticVar = 10;
    }
}

var class1 = new MyClass(1);
console.log(class1.instanceVar);      // 1
console.log(class1.constructor.staticVar); // 10

// New instance of MyClass with another value
var class2 = new MyClass(3);
console.log(class1.instanceVar);      // 1
console.log(class2.instanceVar);      // 3

정적 변수에 액세스하기 .constructor위해 클래스를 만든 객체 생성자 함수에 대한 참조를 반환하는 속성을 사용합니다 . 생성 된 두 인스턴스에서 호출 할 수 있습니다.

MyClass.staticVar = 11;
console.log(class1.constructor.staticVar); // 11
console.log(class2.constructor.staticVar); // 11 <-- yes it's static! :)

MyClass.staticVar = 12;
console.log(class1.constructor.staticVar); // 12
console.log(class2.constructor.staticVar); // 12

7

다른 유사한 답변이 있지만 그중 어느 것도 나에게 호소하지 못했습니다. 내가 끝내었던 것은 다음과 같습니다.

var nextCounter = (function () {
  var counter = 0;
  return function() {
    var temp = counter;
    counter += 1;
    return temp;
  };
})();

7

나머지 외에도 현재 ECMA 제안서 에 초안 ( 2 단계 제안서 )이 있어 수업에 공개 필드 를 소개 합니다. ( 비공개 분야 고려 )static

제안서의 예제를 사용하여 제안 된 static구문은 다음과 같습니다.

class CustomDate {
  // ...
  static epoch = new CustomDate(0);
}

다른 사람들이 강조한 다음과 같습니다.

class CustomDate {
  // ...
}
CustomDate.epoch = new CustomDate(0);

그런 다음을 통해 액세스 할 수 있습니다 CustomDate.epoch.

에서 새로운 제안을 추적 할 수 있습니다 proposal-static-class-features.


현재 babel은 사용할 수 있는 변환 클래스 특성 플러그인 으로이 기능을 지원 합니다. 또한 여전히 진행 중이지만 V8구현하고 있습니다.


6

아래와 같이 JavaScript에서 정적 변수를 만들 수 있습니다. count정적 변수는 다음과 같습니다 .

var Person = function(name) {
  this.name = name;
  // first time Person.count is undefined, so it is initialized with 1
  // next time the function is called, the value of count is incremented by 1
  Person.count = Person.count ? Person.count + 1 : 1;
}

var p1 = new Person('User p1');
console.log(p1.constructor.count);   // prints 1
var p2 = new Person('User p2');
console.log(p2.constructor.count);   // prints 2

Person함수 또는 인스턴스를 사용하여 정적 변수에 값을 지정할 수 있습니다 .

// set static variable using instance of Person
p1.constructor.count = 10;         // this change is seen in all the instances of Person
console.log(p2.constructor.count); // prints 10

// set static variable using Person
Person.count = 20;
console.log(p1.constructor.count); // prints 20

이것은 정적 변수를 선언하고 JavaScript로 액세스하는 좋은 방법 중 하나입니다.
ArunDhwaj IIITH

5

전역 정적 변수를 만들려면 다음을 수행하십시오.

var my_id = 123;

변수를 아래로 바꿉니다.

Object.defineProperty(window, 'my_id', {
    get: function() {
            return 123;
        },
    configurable : false,
    enumerable : false
});

4

JavaScript에서 정적 변수에 가장 가까운 것은 전역 변수입니다. 이것은 단순히 함수 또는 객체 리터럴의 범위 밖에서 선언 된 변수입니다.

var thisIsGlobal = 1;

function foo() {
    var thisIsNot = 2;
}

다른 방법으로는 전역 변수를 다음과 같이 객체 리터럴 안에 저장하는 것입니다.

var foo = { bar : 1 }

그런 다음 variabels에 다음과 같이 액세스하십시오 foo.bar.


이것으로 여러 파일을 업로드 할 수있었습니다 ..... var foo = {counter : 1}; function moreFiles () {fileName = "파일"+ foo.counter; foo.counter = foo.counter + 1;
veer7

4

여기에서 모든 클래스 개념을 요약하려면 다음을 테스트하십시오.

var Test = function() {
  // "super private" variable, accessible only here in constructor. There are no real private variables
  //if as 'private' we intend variables accessible only by the class that defines the member and NOT by child classes
  var test_var = "super private";

  //the only way to access the "super private" test_var is from here
  this.privileged = function(){
    console.log(test_var);
  }();

  Test.test_var = 'protected';//protected variable: accessible only form inherited methods (prototype) AND child/inherited classes

  this.init();
};//end constructor

Test.test_var = "static";//static variable: accessible everywhere (I mean, even out of prototype, see domready below)

Test.prototype = {

 init:function(){
   console.log('in',Test.test_var);
 }

};//end prototype/class


//for example:
$(document).ready(function() {

 console.log('out',Test.test_var);

 var Jake = function(){}

 Jake.prototype = new Test();

 Jake.prototype.test = function(){
   console.log('jake', Test.test_var);
 }

 var jake = new Jake();

 jake.test();//output: "protected"

});//end domready

글쎄, 이러한 것들에서 모범 사례를 살펴볼 수있는 또 다른 방법은 커피 스크립트가 이러한 개념을 어떻게 번역하는지 보는 것입니다.

#this is coffeescript
class Test
 #static
 @prop = "static"

 #instance
 constructor:(prop) ->
   @prop = prop
   console.log(@prop)

 t = new Test('inst_prop');

 console.log(Test.prop);


//this is how the above is translated in plain js by the CS compiler
  Test = (function() {
    Test.prop = "static";

    function Test(prop) {
     this.prop = prop;
     console.log(this.prop);
    }

    return Test;

  })();

  t = new Test('inst_prop');

  console.log(Test.prop);

4

JavaScript 변수는 기본적으로 정적 입니다. :

var x = 0;

function draw() {
    alert(x); //
    x+=1;
}

setInterval(draw, 1000);

x의 값은 1000 밀리 초마다 1 씩 증가합니다.
1,2,3 등을 인쇄합니다.


2
다른 경우입니다. 귀하의 예는 범위에 관한 것입니다.
challet

4

이 스레드를 탐색 한 후 요구 사항을 해결하는 또 다른 접근법이 있습니다. "정적 변수"를 사용하여 정확히 달성하려는 대상에 따라 다릅니다.

전역 속성 sessionStorage 또는 localStorage를 사용하면 세션 수명 동안 또는 명시 적으로 지울 때까지 무기한 더 오랜 기간 동안 데이터를 저장할 수 있습니다. 이를 통해 페이지 / 앱의 모든 창, 프레임, 탭 패널, 팝업 등에서 데이터를 공유 할 수 있으며 하나의 코드 세그먼트에서 간단한 "정적 / 전역 변수"보다 훨씬 강력합니다.

최상위 전역 변수, 즉 Window.myglobal의 범위, 수명, 의미, 역학 등 모든 번거 로움을 피합니다. 그것이 얼마나 효율적인지 모르지만, 적당한 속도로 액세스하는 적당한 양의 데이터에는 중요하지 않습니다.

"sessionStorage.mydata = anything"로 쉽게 액세스하고 유사하게 검색합니다. "JavaScript : 결정적인 안내서, 6 판", David Flanagan, ISBN : 978-0-596-80552-4, 20 장, 섹션 20.1을 참조하십시오. 이것은 간단한 검색 또는 O'Reilly Safaribooks 구독 (무게가 금으로 표시됨)을 통해 PDF로 쉽게 다운로드 할 수 있습니다.


2

함수 / 클래스는 객체 범위에 단일 생성자 만 허용합니다. Function Hoisting, declarations & expressions

  • Function 생성자로 생성 된 함수는 해당 생성 컨텍스트에 대한 클로저를 생성하지 않습니다. 그들은 항상 글로벌 범위에서 만들어집니다.

      var functionClass = function ( ) {
            var currentClass = Shape;
            _inherits(currentClass, superClass);
            function functionClass() { superClass.call(this); // Linking with SuperClass Constructor.
                // Instance Variables list.
                this.id = id;   return this;
            }
        }(SuperClass)

클로저 -클로저의 복사본은 보존 된 데이터로 작동합니다.

  • 각 클로저의 사본은 자체 자유 값 또는 참조가있는 함수에 작성됩니다. 다른 함수 내에서 함수를 사용할 때마다 클로저가 사용됩니다.
  • JavaScript에서의 클로저는 innerFunctions에 의해 부모 함수의 모든 로컬 변수 사본을 유지 관리하는 것과 같습니다.

      function closureFun( args ) {
            // Local variable that ends up within closure
            var num = args;
            num++;
            return function() { console.log(num); }
        }
        var closure1 = closureFun( 5 );
        var closure2 = closureFun( 777 );
        closure1(); // 5
        closure2(); // 777
        closure2(); // 778
        closure1(); // 6

ES5 함수 클래스 : Object.defineProperty (O, P, Attributes)를 사용합니다

Object.defineProperty () 메소드는 개체에 직접 새 속성을 정의하거나 수정 기존 속성을 개체에 대한, 그리고 개체를 반환합니다.

`` 를 사용하여 몇 가지 방법을 만들었습니다. 으므로 매번 함수 클래스를 쉽게 이해할 수 있습니다.

'use strict';
var Shape = function ( superClass ) {
    var currentClass = Shape;
    _inherits(currentClass, superClass); // Prototype Chain - Extends

    function Shape(id) { superClass.call(this); // Linking with SuperClass Constructor.
        // Instance Variables list.
        this.id = id;   return this;
    }
    var staticVariablesJOSN = { "parent_S_V" : 777 };
    staticVariable( currentClass, staticVariablesJOSN );

    // Setters, Getters, instanceMethods. [{}, {}];
    var instanceFunctions = [
        {
            key: 'uniqueID',
            get: function get() { return this.id; },
            set: function set(changeVal) { this.id = changeVal; }
        }
    ];
    instanceMethods( currentClass, instanceFunctions );

    return currentClass;
}(Object);

var Rectangle = function ( superClass ) {
    var currentClass = Rectangle;

    _inherits(currentClass, superClass); // Prototype Chain - Extends

    function Rectangle(id, width, height) { superClass.call(this, id); // Linking with SuperClass Constructor.

        this.width = width;
        this.height = height;   return this;
    }

    var staticVariablesJOSN = { "_staticVar" : 77777 };
    staticVariable( currentClass, staticVariablesJOSN );

    var staticFunctions = [
        {
            key: 'println',
            value: function println() { console.log('Static Method'); }
        }
    ];
    staticMethods(currentClass, staticFunctions);

    var instanceFunctions = [
        {
            key: 'setStaticVar',
            value: function setStaticVar(staticVal) {
                currentClass.parent_S_V = staticVal;
                console.log('SET Instance Method Parent Class Static Value : ', currentClass.parent_S_V);
            }
        }, {
            key: 'getStaticVar',
            value: function getStaticVar() {
                console.log('GET Instance Method Parent Class Static Value : ', currentClass.parent_S_V);
                return currentClass.parent_S_V;
            }
        }, {
            key: 'area',
            get: function get() {
                console.log('Area : ', this.width * this.height);
                return this.width * this.height;
                }
        }, {
            key: 'globalValue',
            get: function get() {
                console.log('GET ID : ', currentClass._staticVar);
                return currentClass._staticVar;
            },
            set: function set(value) {
                currentClass._staticVar = value;
                console.log('SET ID : ', currentClass._staticVar);
            }
        }
    ];
    instanceMethods( currentClass, instanceFunctions );

    return currentClass;
}(Shape);

// ===== ES5 Class Conversion Supported Functions =====
function defineProperties(target, props) {
    console.log(target, ' : ', props);
    for (var i = 0; i < props.length; i++) {
        var descriptor = props[i];
        descriptor.enumerable = descriptor.enumerable || false;
        descriptor.configurable = true;
        if ("value" in descriptor) descriptor.writable = true;
        Object.defineProperty(target, descriptor.key, descriptor);
    }
}
function staticMethods( currentClass, staticProps ) {
    defineProperties(currentClass, staticProps);
};
function instanceMethods( currentClass, protoProps ) {
    defineProperties(currentClass.prototype, protoProps);
};
function staticVariable( currentClass, staticVariales ) {
    // Get Key Set and get its corresponding value.
    // currentClass.key = value;
    for( var prop in staticVariales ) {
        console.log('Keys : Values');
        if( staticVariales.hasOwnProperty( prop ) ) {
            console.log(prop, ' : ', staticVariales[ prop ] );
            currentClass[ prop ] = staticVariales[ prop ];
        }
    }
};
function _inherits(subClass, superClass) {
    console.log( subClass, ' : extends : ', superClass );
    if (typeof superClass !== "function" && superClass !== null) {
        throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
    }
    subClass.prototype = Object.create(superClass && superClass.prototype, 
            { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } });
    if (superClass)
        Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}

아래 코드 스 니펫은 각 인스턴스마다 인스턴스 멤버 및 공통 정적 멤버의 자체 사본이 있습니다.

var objTest = new Rectangle('Yash_777', 8, 7);
console.dir(objTest);

var obj1 = new Rectangle('R_1', 50, 20);
Rectangle.println(); // Static Method
console.log( obj1 );    // Rectangle {id: "R_1", width: 50, height: 20}
obj1.area;              // Area :  1000
obj1.globalValue;       // GET ID :  77777
obj1.globalValue = 88;  // SET ID :  88
obj1.globalValue;       // GET ID :  88  

var obj2 = new Rectangle('R_2', 5, 70);
console.log( obj2 );    // Rectangle {id: "R_2", width: 5, height: 70}
obj2.area;              // Area :  350    
obj2.globalValue;       // GET ID :  88
obj2.globalValue = 999; // SET ID :  999
obj2.globalValue;       // GET ID :  999

console.log('Static Variable Actions.');
obj1.globalValue;        // GET ID :  999

console.log('Parent Class Static variables');
obj1.getStaticVar();    // GET Instance Method Parent Class Static Value :  777
obj1.setStaticVar(7);   // SET Instance Method Parent Class Static Value :  7
obj1.getStaticVar();    // GET Instance Method Parent Class Static Value :  7

정적 메서드 호출은 클래스에서 직접 이루어지며 클래스 인스턴스에서는 호출 할 수 없습니다. 그러나 인스턴스 내부에서 정적 멤버를 호출 할 수 있습니다.

구문 사용하기 :

   this.constructor.staticfunctionName();
class MyClass {
    constructor() {}
    static staticMethod() {
        console.log('Static Method');
    }
}
MyClass.staticVar = 777;

var myInstance = new MyClass();
// calling from instance
myInstance.constructor.staticMethod();
console.log('From Inside Class : ',myInstance.constructor.staticVar);

// calling from class
MyClass.staticMethod();
console.log('Class : ', MyClass.staticVar);

ES6 클래스 : ES2015 클래스는 프로토 타입 기반 OO 패턴에 대한 간단한 설탕입니다. 편리한 단일 선언 형식을 사용하면 클래스 패턴을보다 쉽게 ​​사용할 수 있으며 상호 운용성을 장려합니다. 클래스는 프로토 타입 기반 상속, 수퍼 호출, 인스턴스 및 정적 메소드 및 생성자를 지원합니다.

: 내 이전 게시물을 참조하십시오.


2

Javascript에서 함수 로컬 정적 변수를 에뮬레이트하는 방법에는 4 가지가 있습니다.

방법 1 : 함수 객체 속성 사용 (이전 브라우저에서 지원됨)

function someFunc1(){
    if( !('staticVar' in someFunc1) )
        someFunc1.staticVar = 0 ;
    alert(++someFunc1.staticVar) ;
}

someFunc1() ; //prints 1
someFunc1() ; //prints 2
someFunc1() ; //prints 3

방법 2 : 클로저, 변형 1 사용 (이전 브라우저에서 지원됨)

var someFunc2 = (function(){
    var staticVar = 0 ;
    return function(){
        alert(++staticVar) ;
    }
})()

someFunc2() ; //prints 1
someFunc2() ; //prints 2
someFunc2() ; //prints 3

방법 3 : 클로저, 변형 2 사용 (이전 브라우저에서도 지원됨)

var someFunc3 ;
with({staticVar:0})
    var someFunc3 = function(){
        alert(++staticVar) ;
    }

someFunc3() ; //prints 1
someFunc3() ; //prints 2
someFunc3() ; //prints 3

방법 4 : 클로저, 변형 3 사용 (EcmaScript 2015 지원 필요)

{
    let staticVar = 0 ;
    function someFunc4(){
        alert(++staticVar) ;
    }
}

someFunc4() ; //prints 1
someFunc4() ; //prints 2
someFunc4() ; //prints 3

2

키워드를 사용하여 JavaScript에서 정적 함수를 정의 할 수 있습니다 static.

class MyClass {
  static myStaticFunction() {
    return 42;
  }
}

MyClass.myStaticFunction(); // 42

이 글을 쓰는 시점에서 여전히 클래스 내에서 정적 속성 (함수 이외의)을 정의 할 수는 없습니다. 정적 속성은 여전히 3 단계 제안서 이므로 아직 JavaScript의 일부가 아닙니다. 그러나 다른 객체와 마찬가지로 클래스에 단순히 할당하는 것을 막을 수있는 것은 없습니다.

class MyClass {}

MyClass.myStaticProperty = 42;

MyClass.myStaticProperty; // 42

마지막 참고 사항 : 상속 된 정적 객체를 사용할 때주의하십시오. 상속 된 모든 클래스는 동일한 객체 사본을 공유합니다 .


1

JavaScript에는 용어 또는 키워드 정적이 없지만 이러한 데이터를 다른 객체와 마찬가지로 함수 객체에 직접 넣을 수 있습니다.

function f() {
    f.count = ++f.count || 1 // f.count is undefined at first
    alert("Call No " + f.count)
}

f(); // Call No 1

f(); // Call No 2

1

정적 함수 변수를 많이 사용하며 JS에는 내장 메커니즘이 없기 때문에 부끄러운 일입니다. 변수와 함수가 하나의 함수 내에서 사용되었지만 외부 범위에서 정의되는 코드를 너무 자주 볼 수 있습니다. 이것은 추악하고 오류가 발생하기 쉽고 문제를 묻는 것입니다 ...

나는 다음과 같은 방법을 생각해 냈습니다.

if (typeof Function.prototype.statics === 'undefined') {
  Function.prototype.statics = function(init) {
    if (!this._statics) this._statics = init ? init() : {};
    return this._statics;
  }
}

이것은 모든 함수에 'statics'메서드를 추가합니다 (예, 긴장을 풀십시오). 호출 될 때 함수 객체에 빈 객체 (_statics)를 추가하고 반환합니다. init 함수가 제공되면 _statics는 init () result로 설정됩니다.

그런 다음 다음을 수행 할 수 있습니다.

function f() {
  const _s = f.statics(() => ({ v1=3, v2=somefunc() });

  if (_s.v1==3) { ++_s.v1; _s.v2(_s.v1); }
} 

이것을 다른 정답 인 IIFE와 비교할 때, 이것은 하나의 할당과 하나의 함수 호출마다 하나의 함수를 추가하고 함수에 '_statics'멤버를 추가하는 경우 단점이 있지만, 몇 가지 장점이 있습니다. 내부 함수 코드에서 '정적'을 사용하는 내부 함수가 아닌 상단은 '_s'로 명시 적입니다. 접두사를 사용하면 전체적으로보고 이해하는 것이 더 간단합니다.


1

요약:

에서 ES6/ ES 2015 class키워드는 함께 소개 된 static키워드. 이것은 javavscript가 구현하는 프로토 타입 상속 모델에 대한 구문 설탕이라는 점을 명심하십시오. static키워드는 방법에 대한 다음과 같은 방식으로 작동합니다 :

class Dog {

  static bark () {console.log('woof');}
  // classes are function objects under the hood
  // bark method is located on the Dog function object
  
  makeSound () { console.log('bark'); }
  // makeSound is located on the Dog.prototype object

}

// to create static variables just create a property on the prototype of the class
Dog.prototype.breed = 'Pitbull';
// So to define a static property we don't need the `static` keyword.

const fluffy = new Dog();
const vicky = new Dog();
console.log(fluffy.breed, vicky.breed);

// changing the static variable changes it on all the objects
Dog.prototype.breed = 'Terrier';
console.log(fluffy.breed, vicky.breed);


2
그는 정적 함수가 아닌 정적 변수를 요구했습니다.
Konrad Höffner

1

나는 프로토 타입을 사용했고 그 방식으로 작동했습니다.

class Cat extends Anima {
  constructor() {
    super(Cat.COLLECTION_NAME);
  }
}

Cat.COLLECTION_NAME = "cats";

또는 정적 게터 사용 :

class Cat extends Anima {
  constructor() {
    super(Cat.COLLECTION_NAME);
  }

  static get COLLECTION_NAME() {
    return "cats"
  }
}

0

창 수준 변수는 직접 참조를 사용할 수 있다는 점에서 정적과 비슷하며 앱의 모든 부분에서 사용할 수 있습니다


3
이러한 변수에 대한 훨씬 더 나은 설명은 정적이 아니라 '전역'입니다.
Patrick M

0

Javascript에는 정적 변수와 같은 것이 없습니다. 이 언어는 프로토 타입 기반 객체를 지향하므로 클래스는 없지만 객체가 "복사"하는 프로토 타입은 없습니다.

전역 변수 또는 프로토 타입을 사용하여 프로토 타입에 속성을 추가하여 시뮬레이션 할 수 있습니다.

function circle(){
}
circle.prototype.pi=3.14159

이 방법은 효과적이지만 Function.prototype
Dan

@ Dan : 이것이 기능이 아닌 서클을위한 것임을 이해합니다. 적어도 그것이 크롬이 말하려는 것입니다. function circle() {}| circle.prototype| circle.prototype.pi = 3.14| circle.prototype| Function.prototype| Function.__proto__(그것이 당신이 의도 한 것이라면)
Aktau

0

jQuery를 사용하는 MVC 웹 사이트를 사용하면서 특정 이벤트 핸들러 내의 AJAX 작업을 이전 요청이 완료된 후에 만 ​​실행할 수 있는지 확인하고 싶습니다. 이것을 달성하기 위해 "정적"jqXHR 객체 변수를 사용합니다.

다음과 같은 버튼이 있습니다 :

<button type="button" onclick="ajaxAction(this, { url: '/SomeController/SomeAction' })">Action!</button>

일반적으로 클릭 핸들러에 다음과 같은 IIFE를 사용합니다.

var ajaxAction = (function (jqXHR) {
    return function (sender, args) {
        if (!jqXHR || jqXHR.readyState == 0 || jqXHR.readyState == 4) {
            jqXHR = $.ajax({
                url: args.url,
                type: 'POST',
                contentType: 'application/json',
                data: JSON.stringify($(sender).closest('form').serialize()),
                success: function (data) {
                    // Do something here with the data.
                }
            });
        }
    };
})(null);

0

프로토 타입을 사용하려면 방법이 있습니다

var p = function Person() {
    this.x = 10;
    this.y = 20;
}
p.prototype.counter = 0;
var person1 = new p();
person1.prototype = p.prototype;
console.log(person1.counter);
person1.prototype.counter++;
var person2 = new p();
person2.prototype = p.prototype;
console.log(person2.counter);
console.log(person1.counter);

이렇게하면 모든 인스턴스에서 카운터 변수에 액세스 할 수 있으며 속성의 변경 사항이 즉시 반영됩니다!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.