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는 함수를 일급 객체 로 취급 하므로 객체 이므로 함수에 속성을 할당 할 수 있습니다.
JS 함수도 객체라는 사실을 활용할 수 있습니다. 즉, 속성을 가질 수 있습니다.
예를 들어, 자바 스크립트의 정적 변수 (현재 사라진) 기사에 제공된 예제를 인용합니다 .
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);
}
이 함수를 여러 번 호출하면 카운터가 증가하는 것을 볼 수 있습니다.
그리고 이것은 아마도 전역 변수로 전역 이름 공간을 poluting하는 것보다 훨씬 더 나은 해결책 일 것입니다.
그리고 여기에 클로저를 기반으로 한 또 다른 가능한 해결책 이 있습니다. 자바 스크립트에서 정적 변수를 사용하는 트릭 :
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
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
를 통해 속성 을 정의합니다.을 지정하지 않으면 속성이 읽기 전용이며 수정할 수 없습니다 (설정하려고해도 오류가 발생하지 않지만 효과가 없음). 각 속성에는 기본 속성 인 (선언 후 변경 허용) 및 (열거 자로 사용 허용 ) 속성이 있습니다 . 세 번째 매개 변수 를 통해 설정할 수 있습니다 ( 예 : .get
set
set
writable
configurable
enumerable
false
defineProperty
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
및 쓰기 전용 속성 을 정의하며이를 c
통해 속성에 a
액세스 할 수 있습니다.
용법:
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 장 (객체)에서 자세히 설명합니다.
당신은 말할 수 a
및 b
상속 Podcast
. 지금, 당신은 이후에 모두 적용 팟 캐스트에 대한 방법을 추가하는 것을 원하는 경우 a
와 b
통해 인스턴스 한을? 이 경우 .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]"
여기에서 프로토 타입에 대한 자세한 내용을 확인할 수 있습니다 . 더 많은 상속을 원한다면 이것을 조사하는 것이 좋습니다 .
기사 시리즈 내가 위에서 언급 한 적이있다 추천 읽고, 그들은 또한 다음과 같은 항목을 포함한다 :
- 기능
- 사물
- 프로토 타입
- 생성자 함수에 새로운 적용
- 게양
- 자동 세미콜론 삽입
- 정적 속성 및 방법
참고 것을 자동 세미콜론 삽입 (6.에서 언급 한) 자바 스크립트의 "기능"매우 자주 코드에서 이상한 문제의 원인에 대한 책임이있다. 따라서 나는 그것을 기능 이라기보다는 버그로 간주하고 싶습니다.
자세한 내용을 보려면 여기 에 이러한 주제에 대한 매우 흥미로운 MSDN 기사 가 있습니다. 여기 에 설명 된 일부 항목은 더 자세한 정보를 제공합니다.
흥미로운 것은 (위에서 언급 한 주제도 다룹니다) MDN JavaScript Guide의 기사입니다 .
JavaScript 에서 C # out
매개 변수 (예 :) 를 에뮬레이션 하는 방법을 알고 싶다면 여기에서 샘플 코드를DateTime.TryParse(str, out result)
찾을 수 있습니다.
IE ( F12콘솔 탭을 사용하여 개발자 도구를 열지 않는 한 JavaScript 용 콘솔이 없음) 로 작업하는 사용자 는 다음 스 니펫이 유용 할 수 있습니다. console.log(msg);
위의 예에서 사용 된 대로 사용할 수 있습니다 . Podcast
함수 앞에 삽입하십시오 .
편의를 위해 다음은 하나의 완전한 단일 코드 스 니펫으로 위의 코드입니다.
let console = { log: function(msg) {
let canvas = document.getElementById("log"), br = canvas.innerHTML==="" ? "" : "<br/>";
canvas.innerHTML += (br + (msg || "").toString());
}};
console.log('For details, see the explaining text');
function Podcast() {
// with this, you can instantiate without new (see description in text)
if (false === (this instanceof Podcast)) {
return new Podcast();
}
// private variables
var _somePrivateVariable = 123;
// object properties
this.title = 'Astronomy Cast';
this.description = 'A fact-based journey through the galaxy.';
this.link = 'http://www.astronomycast.com';
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
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
// getters and setters
var d = Date.prototype;
Object.defineProperty(d, "year", {
get: function() {
return this.getFullYear()
},
set: function(y) {
this.setFullYear(y)
}
});
// getters and setters - alternative syntax
var obj = {
a: 7,
get b() {
return this.a + 1;
},
set c(x) {
this.a = x / 2
}
};
// usage:
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
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"
Podcast.prototype.titleAndLink = function() {
return this.title + " [" + this.link + "]";
};
console.log(a.titleAndLink()); // "a [http://www.astronomycast.com]"
console.log(b.titleAndLink()); // "An Astronomy Cast [http://www.astronomycast.com]"
<div id="log"></div>
메모:
일반적으로 JavaScript 프로그래밍에 대한 몇 가지 좋은 팁, 힌트 및 권장 사항은 여기 (JavaScript 모범 사례) 와 거기 ( 'var'대 'let')에서 찾을 수 있습니다. 암시 적 유형 변환 (강제)에 대한 이 문서도 권장됩니다 .
클래스를 사용하고 JavaScript로 컴파일하는 편리한 방법은 TypeScript입니다. 다음은 작동 방식을 보여주는 몇 가지 예를 찾을 수 있는 놀이터 입니다. 현재 TypeScript를 사용하지 않더라도 TypeScript와 JavaScript 결과를 나란히 볼 수 있기 때문에 살펴볼 수 있습니다. 대부분의 예제는 간단하지만 즉시 사용해 볼 수있는 Raytracer 예제도 있습니다. 특히 "Using Classes", "Using Inheritance"및 "Using Generics"예제를 콤보 상자에서 선택하여 살펴볼 것을 권장합니다.이 예제는 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: </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
파일 에 넣을 수 있습니다 . 이것은 예제를 짧게 유지하기 위해 인라인으로 작성되었습니다.
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
Foo
JavaScript에서 함수는 객체이기 때문에 속성에 할당 할 수 있습니다 .
다음 예제와 설명은 Nicholas Zakas의 Professional JavaScript for Web Developers 2nd Edition 책에서 발췌 한 것입니다. 이것이 제가 찾고 있던 답변이므로 여기에 추가하는 것이 도움이 될 것이라고 생각했습니다.
(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
인스턴스를 호출 하거나 생성 하면 이름 변수가 새 값으로 설정됩니다. 이로 인해 모든 인스턴스가 동일한 값을 반환합니다.
새 클래스 구문 을 사용하는 경우 이제 다음을 수행 할 수 있습니다.
class MyClass {
static get myStaticVariable() {
return "some static variable";
}
}
console.log(MyClass.myStaticVariable);
aMyClass = new MyClass();
console.log(aMyClass.myStaticVariable, "is undefined");
이것은 JavaScript에서 효과적으로 정적 변수를 생성합니다.
응용 프로그램에서 상수를 만들기 위해 정적 변수를 선언하려면 가장 단순한 접근 방식으로 다음을 발견했습니다.
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;
class
ECMAScript 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
다른 유사한 답변이 있지만 그중 어느 것도 나에게 호소력이 없습니다. 내가 끝내게 된 것은 다음과 같습니다.
var nextCounter = (function () {
var counter = 0;
return function() {
var temp = counter;
counter += 1;
return temp;
};
})();
아래와 같이 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
전역 정적 변수를 만들고 싶다면 :
var my_id = 123;
변수를 아래로 바꿉니다.
Object.defineProperty(window, 'my_id', {
get: function() {
return 123;
},
configurable : false,
enumerable : false
});
JavaScript에서 변수는 기본적으로 정적 입니다. 예 :
var x = 0;
function draw() {
alert(x); //
x+=1;
}
setInterval(draw, 1000);
x의 값은 1000 밀리 초마다 1 씩 증가합니다.
1,2,3 등이 인쇄됩니다.
JavaScript에서 정적 변수에 가장 가까운 것은 전역 변수입니다. 이것은 단순히 함수 또는 객체 리터럴의 범위 밖에서 선언 된 변수입니다.
var thisIsGlobal = 1;
function foo() {
var thisIsNot = 2;
}
다른 방법은 다음과 같이 객체 리터럴 내에 전역 변수를 저장하는 것입니다.
var foo = { bar : 1 }
그리고 그 다음이 같은 variabels 액세스합니다 foo.bar
.
여기에 모든 클래스 개념을 요약하려면 다음을 테스트하십시오.
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
글쎄요, 이런 것들에서 모범 사례를 살펴 보는 또 다른 방법은 coffeescript가 이러한 개념을 어떻게 번역하는지 보는 것입니다.
#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);
이 스레드를 탐색 한 후 내 요구 사항을 해결 한 또 다른 접근 방식이 있습니다. "정적 변수"로 달성하려는 목표에 따라 다릅니다.
전역 속성 sessionStorage 또는 localStorage를 사용하면 세션 수명 동안 또는 명시 적으로 지워질 때까지 무기한 더 긴 기간 동안 데이터를 저장할 수 있습니다. 이를 통해 페이지 / 앱의 모든 창, 프레임, 탭 패널, 팝업 등에서 데이터를 공유 할 수 있으며 하나의 코드 세그먼트에서 단순한 "정적 / 전역 변수"보다 훨씬 강력합니다.
그것은 최상위 전역 변수, 즉 Window.myglobal의 범위, 수명, 의미론, 역학 등과 관련된 모든 번거 로움을 피합니다. 얼마나 효율적인지 모르지만 적당한 속도로 액세스되는 적당한 양의 데이터에는 중요하지 않습니다.
"sessionStorage.mydata = anything"로 쉽게 액세스하고 유사하게 검색합니다. "JavaScript : The Definitive Guide, Sixth Edition", David Flanagan, ISBN : 978-0-596-80552-4, 20 장, 섹션 20.1을 참조하십시오. 이것은 간단한 검색이나 O'Reilly Safaribooks 구독 (골드 무게의 가치)을 통해 PDF로 쉽게 다운로드 할 수 있습니다.
나머지뿐만 아니라, 현재 초안 (거기 단계-2의 제안 에) ECMA의 제안을 소개하고 그 static
공공 클래스의 필드. ( 사설 분야 고려 )
제안의 예를 사용하면 제안 된 static
구문은 다음과 같습니다.
class CustomDate {
// ...
static epoch = new CustomDate(0);
}
다른 사람들이 강조한 다음과 동일해야합니다.
class CustomDate {
// ...
}
CustomDate.epoch = new CustomDate(0);
그런 다음을 통해 액세스 할 수 있습니다 CustomDate.epoch
.
에서 새 제안을 추적 할 수 있습니다 proposal-static-class-features
.
현재 babel은 사용할 수 있는 transform 클래스 속성 플러그인 으로이 기능을 지원 합니다. 또한 아직 진행 중이지만 V8
이를 구현하고 있습니다.
함수의 / 클래스는 객체 범위에 대해 단일 생성자 만 허용합니다. 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, 속성) 사용
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 패턴에 비해 단순한 설탕입니다. 편리한 선언적 형식 하나를 사용하면 클래스 패턴을 더 쉽게 사용할 수 있고 상호 운용성을 높일 수 있습니다. 클래스는 프로토 타입 기반 상속, 슈퍼 호출, 인스턴스 및 정적 메서드 및 생성자를 지원합니다.
예 : 이전 게시물을 참조하십시오.
자바 스크립트에는 용어 나 키워드가 정적 인 것이 없지만 이러한 데이터를 함수 객체에 직접 넣을 수 있습니다 (다른 객체와 마찬가지로).
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
자바 스크립트에서 함수 로컬 정적 변수를 에뮬레이션하는 방법에는 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
창 수준 변수는 직접 참조를 사용할 수 있고 앱의 모든 부분에서 사용할 수 있다는 점에서 정적과 비슷합니다.
Javascript에는 정적 변수와 같은 것이 없습니다. 이 언어는 프로토 타입 기반 객체 지향이므로 클래스는 없지만 객체가 자신을 "복사"하는 프로토 타입입니다.
전역 변수 또는 프로토 타이핑 (프로토 타입에 속성 추가)을 사용하여 시뮬레이션 할 수 있습니다.
function circle(){
}
circle.prototype.pi=3.14159
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);
프로토 타입을 사용하려면 방법이 있습니다.
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);
이렇게하면 모든 인스턴스에서 카운터 변수에 액세스 할 수 있으며 속성의 변경 사항이 즉시 반영됩니다 !!
그래서 다른 답변에서 보는 것은 객체 지향 프로그래밍에서 정적 속성의 기본적인 아키텍처 요구 사항을 해결하지 않는다는 것입니다.
객체 지향 프로그래밍에는 실제로 '클래스 기반'(C ++, C #, Java 등)과 '프로토 티팔'(자바 스크립트)의 두 가지 스타일이 있습니다. 클래스 기반 언어에서 '정적 속성'은 인스턴스화 된 객체가 아니라 클래스와 연관되어야합니다. 이 개념은 실제로 속성을 부모 프로토 타입의 값으로 할당하기 때문에 Javascript와 같은 프로토 타입 언어에서 훨씬 더 직관적으로 작동합니다.
function MyObject() {};
MyObject.prototype.staticAttribute = "some value";
그리고이 생성자에서 인스턴스화 된 모든 객체에서 액세스합니다.
var childObject1 = new MyObject(); // Instantiate a child object
var childObject2 = new MyObject(); // Instantiate another child object
console.log(childObject.staticAttribute); // Access the static Attribute from child 1
console.log(childObject.staticAttribute); // Access the static Attribute from child 2
이제 계속 진행하여 MyObject.prototype.staticAttribute
변경 사항이 즉시 상속되는 자식 개체로 계단식으로 내려갑니다.
그러나이 속성의 '정적'특성을 크게 훼손하거나 보안 취약성을 남길 수있는 몇 가지 '잘못'이 있습니다.
먼저 생성자를 jQuery 준비 메서드와 같은 다른 함수 안에 포함하여 전역 네임 스페이스에서 생성자를 숨겨야합니다.
$(document).ready(function () {
function MyObject() {
// some constructor instructions
};
MyObject.prototype.staticAttribute = "some value";
var childObject = new MyObject(); // instantiate child object
console.log(childObject.staticAttribute); // test attribute
});
Second and lastly, even if you do this, the attribute is still editable from any of the other parts of your own script, so it could be the case that a bug in your code writes over the attribute on one of the child objects and detaches it from the parent prototype, so if you change the parent attribute it will no longer cascade and change the static attribute for the child object. See this jsfiddle. In different scenarios we could either Object.freeze(obj)
to stop any changes to the child object, or we could set up a setter and getter method in the constructor and access a closure, both of these have associated complexities.
It seems to me that there is not a perfect analogue between the class-based idea of a 'static attribute' and this Javascript implementation. So I think it might be better in the long run to use a different code pattern that is more Javascript friendly. Such as a central datastore or cache or even a dedicated helper object to hold all the necessary static variables.
I didn't see this idea in any of the answers so just adding it to the list. If it's a duplicate just let me know and i'll delete it and upvote the other.
I created a sort of super global in my website. Since I have several js files that are loaded on every page load and dozens of other js files that are only loaded on some pages I put all of the "global" function into a single global variable.
내 첫 번째 포함 된 "전역"파일의 맨 위에는 다음과 같은 선언이 있습니다.
var cgf = {}; // Custom global functions.
그런 다음 여러 글로벌 도우미 기능을 관리합니다.
cgf.formBehaviors = function()
{
// My form behaviors that get attached in every page load.
}
그런 다음 정적 변수가 필요한 경우 문서 준비 또는 동작 첨부 외부와 같이 범위 외부에 저장합니다. (나는 jquery를 사용하지만 자바 스크립트에서 작동합니다)
cgf.first = true;
$.on('click', '.my-button', function()
{
// Don't allow the user to press the submit twice.
if (cgf.first)
{
// first time behavior. such as submit
}
cgf.first = false;
}
물론 이것은 정적이 아닌 전역이지만 모든 페이지로드에서 다시 초기화되므로 동일한 목적을 달성합니다.
개인 정적 변수의 경우 다음과 같이 찾았습니다.
function Class()
{
}
Class.prototype = new function()
{
_privateStatic = 1;
this.get = function() { return _privateStatic; }
this.inc = function() { _privateStatic++; }
};
var o1 = new Class();
var o2 = new Class();
o1.inc();
console.log(o1.get());
console.log(o2.get()); // 2
이걸로 해봐:
속성을 정의하고 Getter 및 Setter를 재정 의하여 Function Object 속성을 사용하면 이론적으로 자바 스크립트에서 정적 변수를 가질 수 있습니다.
예를 들면 :
function Animal() {
if (isNaN(this.totalAnimalCount)) {
this.totalAnimalCount = 0;
}
this.totalAnimalCount++;
};
Object.defineProperty(Animal.prototype, 'totalAnimalCount', {
get: function() {
return Animal['totalAnimalCount'];
},
set: function(val) {
Animal['totalAnimalCount'] = val;
}
});
var cat = new Animal();
console.log(cat.totalAnimalCount); //Will produce 1
var dog = new Animal();
console.log(cat.totalAnimalCount); //Will produce 2 and so on.
참고 URL : https://stackoverflow.com/questions/1535631/static-variables-in-javascript
'Program Tip' 카테고리의 다른 글
jQuery의 SELECT 요소에서 특정 옵션을 어떻게 선택합니까? (0) | 2020.09.30 |
---|---|
문자열을 효율적으로 연결하는 방법 (0) | 2020.09.30 |
Java의 핵심 라이브러리에있는 GoF 디자인 패턴의 예 (0) | 2020.09.30 |
구현 vs 확장 : 언제 사용합니까? (0) | 2020.09.30 |
애플리케이션 서버와 웹 서버의 차이점은 무엇입니까? (0) | 2020.09.30 |